一佑力、CBV版視圖
二式散、給視圖加裝飾器
三、request對象常用屬性
四打颤、url:路由系統(tǒng)
五暴拄、命名url和url的反向解析
六、session
七编饺、使用 pymysql 連接 mysql
八乖篷、內(nèi)置auth認(rèn)證
九、模板語法中的for循環(huán)
django官方文檔:django-documentation
-
一透且、CBV版視圖
veiw中寫函數(shù)有兩種寫法撕蔼,之前寫的def類都是FBV版。還有一種寫法是CBV版秽誊。就是將之前函數(shù)的寫法變類的寫法鲸沮,url中也要相應(yīng)變動一下。
例:
視圖中定義: from django.views import View Class AddBook(View): def dispatch(self, request, *args, **kwargs): print('處理請求之前') ret = super().dispatch(request, *args, **kwargs) print('處理請求之后') return ret def get(self,request): pass def post(self,request): pass
url中使用: url(r'^add_book/$',views.AddBook.as_view())
執(zhí)行過程: 1锅论,AddBook這個類讼溺,執(zhí)行了as_view()這個方法,但是棍厌,我們自定義的類里沒有寫這個方法肾胯; 這就要看繼承的父類里,View類有沒有了耘纱,查看敬肚,有此方法,是類方法束析。 2艳馒,這個類方法執(zhí)行到最后返回了一個view函數(shù),不帶括號,沒有執(zhí)行弄慰,等待連接后才執(zhí)行第美。 3,view函數(shù)執(zhí)行到最后返回了一個dispatch函數(shù)且執(zhí)行后的結(jié)果陆爽。 self = cls(**initkwargs) 實例化了一個對象 return self.dispatch(request, *args, **kwargs) 此時如果自己寫的類里有dispatch方法則會執(zhí)行自己的什往,沒有則會執(zhí)行父類的 4,dispatch(派遣的意思)函數(shù)過程中對接收到的請求方式進(jìn)行了判斷慌闭,并對其進(jìn)行了反射别威, handler = getattr(self, request.method.lower(), self.http_method_not_allowed) 反射得出方法 如果是get則執(zhí)行g(shù)et函數(shù),如果是post則執(zhí)行post函數(shù)驴剔,并將執(zhí)行結(jié)果返回省古。 return handler(request, *args, **kwargs) 執(zhí)行并返回結(jié)果 父類的dispatch(self, request, *args, **kwargs):方法 是執(zhí)行自己寫的get/post函數(shù)的一個過程。 理解dispatch: 上述分析丧失,函數(shù)走到dispatch后豺妓,是一個對象方法,如果在自己的類里寫了此方法布讹,那么他會走自己的方法琳拭。 但是,父類有這個方法為什么還要自己寫呢炒事?走自己的方法有什么用呢臀栈? 那就要看你的需求了蔫慧,函數(shù)走到那一步就會走dispatch這個函數(shù)挠乳, 如果自己感覺累了,想要先停一會兒姑躲,你就停幾分鐘睡扬,過一會兒再拿過來父類的dispatch運(yùn)行, 因為你自己的dispatch方法沒有父類的功能黍析,所以還得借用父類的dispatch方法卖怜。 簡版的流程: AddPublisher.as_view() ——》 view 函數(shù) 當(dāng)請求來的時候才執(zhí)行view view中執(zhí)行: 1. 先實例化AddPublisher,給self 2. 執(zhí)行self.dispatch() self 有dispatch 就執(zhí)行自己的 沒有就是執(zhí)行 父類(View)的dispatch方法 3. dispatch中執(zhí)行: 先通過反射獲取到AddPublisher中定義get或者post方法阐枣。 執(zhí)行g(shù)et或者post方法 返回httpresponse對象 4. view接收到dispatch的返回值——httpresponse對象 5. view返回httpresponse對象
-
二马靠、給視圖加裝飾器
裝飾器: def wrapper(func): def inner(*args, **kwargs): start_time = time.time() ret = func(*args, **kwargs) end_time = time.time() print("used:", end_time-start_time) return ret return inner
# FBV版添加裝飾器 @wrapper def add_class(request): if request.method == "POST": class_name = request.POST.get("class_name") models.Classes.objects.create(name=class_name) return redirect("/class_list/") return render(request, "add_class.html")
# CBV版添加裝飾器 from django.views import View from django.utils.decorators import method_decorator 第一種:(給各自加) class AddClass(View): @method_decorator(wrapper) def get(self, request): pass @method_decorator(wrapper) def post(self, request): pass 第二種:(給dispatch加) class AddClass(View): @method_decorator(wrapper) def dispatch(self, request, *args, **kwargs): print('before') obj = super(Login,self).dispatch(request, *args, **kwargs) print('after') return obj def get(self, request): pass def post(self, request): pass 第三種:(給類加) @method_decorator(wrapper,name='get') @method_decorator(wrapper,name='post') class AddClass(View): def get(self, request): pass def post(self, request): pass
-
三、request對象常用屬性
request.method 請求方式 GET POST request.GET 字典蔼两,URL上傳的參數(shù) request.POST 字典甩鳄,form表單傳的數(shù)據(jù) request.COOKIES.get 獲取cookie信息 request.session.get 獲取session信息 request.is_ajax() 判斷請求是不是ajax request.path_info ---》/add_publisher/ 用戶訪問的URL,不包括域名 request.body ---》一個字符串额划,代表請求報文的主體妙啃。在處理非 HTTP 形式的報文時非常有用,例如:二進(jìn)制圖片、XML,Json等揖赴。 但是馆匿,如果要處理表單數(shù)據(jù)的時候,推薦還是使用 HttpRequest.POST 燥滑。 request.FILES ---》一個類似于字典的對象渐北,包含所有的上傳文件信息。 FILES 中的每個鍵為<input type="file" name="" /> 中的name铭拧,值則為對應(yīng)的數(shù)據(jù)腔稀。 注意:FILES 只有在請求的方法為POST 且提交的<form> 帶有enctype="multipart/form-data" 的情況下才會 包含數(shù)據(jù)。否則羽历,F(xiàn)ILES 將為一個空的類似于字典的對象焊虏。 request.get_full_path() -->/test/?id=1 參數(shù)也拿到了 request.path_info -->/test/ 只拿到了url request.get_host -->IP+端口 127.0.0.1:8000
-
四、url:路由系統(tǒng)
(1) urlpatterns = [ url(正則表達(dá)式秕磷,views視圖诵闭,參數(shù),別名) ] (2) ^ 以...為開頭澎嚣,$以...為結(jié)尾 (3) 如果項目中沒有按照自己以為的去執(zhí)行函數(shù)疏尿,可能是因為正則匹配過程中匹配到了別的。 匹配時從上往下依次匹配易桃,如果上面有符合要求的褥琐,就不會走下面的。 url(r'^book/',) url(r'^book/asd') 一般可寫成url(r'^book/$')規(guī)定開頭結(jié)尾晤郑,約束 (4) url位置參數(shù)說明: # 用戶輸入url敌呈,滿足條件匹配上之后,才能將參數(shù)傳進(jìn)test函數(shù)造寝,讓test函數(shù)對url中分組內(nèi)的參數(shù)進(jìn)行處理磕洪。 # 即用戶可通過url輸入?yún)?shù),url匹配成功后诫龙,通過url進(jìn)行傳參析显,傳括號里的內(nèi)容傳給函數(shù)進(jìn)行處理。 無名分組: 實例1: 用戶輸入: 127.0.0.1:8000/test/2018/08 url: url(r'^test/([0-9]{4})/[0-9]{2}',views.test) 函數(shù): def test(request,*args,**kwargs): print(args) 輸出結(jié)果:('2018',) return HttpResponse('你自己輸入的{},你還愁啥'.format(args)) 頁面顯示:你自己輸入的('2018',),你還愁啥 實例2: 用戶輸入: 127.0.0.1:8000/test/嘀嗒嘀嗒嘀嗒嘀签赃。谷异。。锦聊。(隨便輸入) url: url(r'^test/([0-9]{4})/[0-9]{2}',views.test),不走這個 url(r'^test/(.+)',views.test1) 走這個 函數(shù): def test1(request,*args): return HttpResponse(args[0]) 頁面顯示:輸入什么就顯示什么 url(r'^test/(.{3})',views.test1),這個是不管輸入多少歹嘹,只顯示3個字 (5) # 是否開啟URL訪問地址后面不為/,也能跳轉(zhuǎn)至帶有/的路徑的配置項: 配置中寫入這個,不加/也能自動添加/再走一次 APPEND_SLASH=True (默認(rèn)為True括丁,所以不寫也能自動添加) 如果不想讓其自動添加荞下,就改為 False (6)分組命名匹配:(區(qū)別在于:函數(shù)中只接收正則中命名的名字作為參數(shù),將匹配到的結(jié)果傳給函數(shù)) 有名分組: 實例: 用戶輸入: http://127.0.0.1:8000/test/阿斯頓法國紅酒看來 url中: url(r'^test/(?P<nei_rong>.{2})',views.test2) views中: def test2(request,nei_rong): print(nei_rong) 輸出結(jié)果:阿斯 return HttpResponse('輸入的內(nèi)容為:{}'.format(nei_rong)) 頁面顯示:輸入的內(nèi)容為:阿斯 (7) 后端接收到的url中的參數(shù)都是字符串! (8) 視圖函數(shù)中指定默認(rèn)值 # urls.py中 from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), url(r'^blog/page(?P<num>[0-9]+)/$', views.page), ] # views.py中尖昏,可以為num指定默認(rèn)值 def page(request, num="1"): pass (9) 包含其他的url:(可將不同url寫進(jìn)不同的業(yè)務(wù)線下仰税,然后用總的包含) from django.conf.urls import include, url from app01 import urls urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^app01/', include('app01.urls')), # 可以包含其他的URLconfs文件 【1,不導(dǎo)入抽诉,寫字符串陨簇,反射找到】 from app01 import urls as app01_urls url(r'^app01/', include(app01_urls)) 【2,導(dǎo)入迹淌,不用寫成字符串】 ] (10) 當(dāng)兩個app寫了兩個相同的url河绽,反向解析時就會沖突,所以要將不同的app下的url寫不同的標(biāo)記唉窃,即 在總的url中耙饰,命名空間。 url(r'^app01/', include('app01.urls'),namespace='app01') url(r'^app02/', include('app02.urls'),namespace='app02') 反向解析時: url = reverse('app01:index') url = reverse('app02:index') 起了namespace纹份,都要用app01:加前綴 url = reverse('app01:book') (11) url中可傳參數(shù)(可以在url中自己寫一個參數(shù)苟跪,字典中的,傳給views中的相應(yīng)函數(shù)) urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
-
五蔓涧、命名url和url的反向解析
1件已,起名字: url(r'^json/',views.json_data,name='js') 2,用(可在視圖中用元暴,可在模板中用) 視圖中用: 導(dǎo)入reverse: from django.shortcuts import render,HttpResponse,reverse url = reverse('js') 結(jié)果是/json/篷扩,即使改為/jsonfgieue/,也能通過js找到茉盏。通過名字就能找到這個url鉴未, 比較靈活(不帶參數(shù)的),通過名字援岩,找到url歼狼,字符串類型 模板中用: url(r'baidusss/',views.baidu,name='baidu') <a href="/baidu/">這是跳轉(zhuǎn)到一個自定義的百度路由(寫死的)掏导,然后返回一個百度的連接</a> <a href="{% url 'baidu' %}">這個連接用的是反向解析享怀,如果views中的url變了,上面就找不到了</a> 3趟咆,作用:不怕url改名字添瓷。不管怎么改,我的模板中值纱,函數(shù)中鳞贷,都能找到此路由, 這就給自己提供了方便虐唠,即使路由改了搀愧,html頁面中或函數(shù)中要跳轉(zhuǎn)的路由不用改,只是用戶輸入時需要改。 因為程序內(nèi)部有這個反向解析的方法能找到咱筛,而用戶只能是提供什么url就寫什么url 4搓幌,帶參數(shù)的用法(無名分組) url(r'^testtttttt/([0-9]{4})/([0-9]{2})',views.test,name='test') 視圖中,需傳參 url = reverse('test',args=('1998','08)) 模板中,需傳參 <a href="{% url 'test' '1998' '08' %}">測試</a> 5迅箩,帶有名分組的參數(shù) url(r'^testtttttt/(溉愁?P<year>[0-9]{4})/(?P<month>[0-9]{2})',views.test,name='test') 視圖中,傳位置參數(shù) url = reverse('test',kwargs={'year':'1998','month':'08'}) 模板中饲趋,傳參 <a href="{% url 'test' '1998' '08' %}">測試</a> (對應(yīng)先后順序) 或者 <a href="{% url 'test' month='08' year='1998' %}">測試</a> (可換位置)
舉個栗子:
總路由: urlpatterns = [ url(r'^goods/', include('df_goods.urls', namespace='df_goods')), # 添加實例命名空間 ] 子路由: urlpatterns = [ url('^index/$', views.index, name="index"), ] 視圖應(yīng)用: print(reverse("df_goods:index")) # 利用reverse函數(shù)反向解析url # 打印結(jié)果為/goods/index/ 頁面應(yīng)用: <a href="{% url "df_goods:index" %}">反向解析</a>
-
六拐揭、session
Cookie雖然解決了“保持狀態(tài)”的需求,但是cookie最大支持4096字節(jié)奕塑,且cookie保存在客戶端堂污,可能被攔截或竊取。 因此就需要有一種新的東西龄砰,支持更多字節(jié)敷鸦,并且保存在服務(wù)器,有較高的安全性寝贡,這就是Session扒披。 Session 1,接收請求圃泡,返回響應(yīng) 2碟案,返回響應(yīng)時,生成一個特殊的字符串 3颇蜡,在后端開一塊空間价说,保存請求相關(guān)數(shù)據(jù) 4,返回響應(yīng) 下一次請求時: 1风秤,帶著之前發(fā)給瀏覽器的字符串 2鳖目,拿著字符串找相應(yīng)的箱子 3,在箱子中根據(jù)key取值 前提:django存儲session是在內(nèi)置的 django_session 表中缤弦,所以必須先生成其表领迈。 1. 設(shè)置Session: 不需要在響應(yīng)中設(shè)置,直接request.session['key']='value' 1. request.session[key] = value 2. request.session.setdefault(key, value) --> 有就啥都不干碍沐,沒有就賦值 2. 獲取session: if request.session.get('key','')== 'value': pass 1. request.session[key] 2. request.session.get(key) 推薦 3. 刪除Session 1. request.session.delete() 2. request.session.flush() --> 刪除Cookie和Session 4. 清空已經(jīng)過期的session數(shù)據(jù) request.session.clear_expired() 5. 設(shè)置Session過期時間 request.session.set_expiry(過期時間) session中的有效日期狸捅,默認(rèn)是兩周 6. settings配置中: SESSION_SAVE_EVERY_REQUEST = True # 一般設(shè)為True # 每次請求都更新超時時間,超時時間從最近的一次請求算起累提。 SESSION_COOKIE_AGE = 129600 --->默認(rèn)兩周
-
七尘喝、使用 pymysql 連接 mysql
1,創(chuàng)建mysql數(shù)據(jù)庫 2斋陪,settings配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'chubanshe_book', 'HOST': '127.0.0.1', 'POST': 3306, 'USER': 'root', 'PASSWORD': '', } } 3朽褪,告訴django使用pymysql來連接數(shù)據(jù)庫: 在與項目同名的文件夾下的__init__.py文件中寫: import pymysql pymysql.install_as_MySQLdb() 4置吓,在app01/models.py寫類(必須繼承models.Model) class Publisher(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32,null=False,unique=True) 5,執(zhí)行數(shù)據(jù)庫遷移兩條命令 python manage.py makemigrations # 保存models修改記錄 python manage.py migrate # 操作數(shù)據(jù)表 1 2 3 4 5 創(chuàng)表缔赠, 我要連(配置)交洗, 我要用什么連(pymysql), 形成映射關(guān)系(model)橡淑, 兩條命令
-
八构拳、內(nèi)置auth認(rèn)證
auth認(rèn)證:默認(rèn)django內(nèi)置的認(rèn)證系統(tǒng),默認(rèn)在數(shù)據(jù)庫使用auth_user表
-
擴(kuò)展內(nèi)置user表
models.py: from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): phone = models.CharField(max_length=11) settings.py: AUTH_USER_MODEL = "app01.UserInfo" views.py: models.UserInfo.objects.create_user(password=pwd,username=user,phone=pho)
django的登錄:
auth.login(request,user)
django的注銷:
auth.logout(request)
驗證用戶名密碼是否正確:
auth.authenticate(request, username=username, password=pwd)
登錄認(rèn)證裝飾器:
login_required
LOGIN_URL = '/login/' # 配置將內(nèi)置登錄路由替換成自己的登錄路由登錄用戶顯示用戶名梁棠,非登錄用戶請登錄:
user.is_authenticated
檢查原密碼:
check_password(password)
---> 修改密碼時使用
auth
提供的一個檢查密碼是否正確的方法置森,需要提供當(dāng)前請求用戶的密碼。
密碼正確返回True符糊,否則返回False凫海。
ok = request.user.check_password('密碼')
重置新密碼:
set_password(password)
---> 修改密碼時使用
auth
提供的一個修改密碼的方法,接收 要設(shè)置的新密碼 作為參數(shù)男娄。
注意:設(shè)置完一定要調(diào)用用戶對象的save
方法P刑啊!模闲!
request.user.set_password(密碼)
request.user.save()
-
九建瘫、模板語法中的for循環(huán)