一 模版
一模版的組成
HTML代碼+邏輯控制代碼
二 邏輯控制代碼的組成
1 變量(使用雙大括號來引用變量)
{{var_name}}
2 標簽(tag)的使用(使用大括號和百分比的組合來表示使用tag)
{%load staticfiles%}
3 過濾器(filter)的使用
{{ship_date|date:"Fj,Y"}},ship_date變量傳給data過濾器,date過濾器通過使用"FJ,Y"這幾個參數來格式化日期數據。"|"代表類似Unix命令中的管道操作。
三 常用標簽
1 {%if%} 的使用
可以使用你的and,or,not來組織的邏輯。但不允許and和or同時出現在條件語句中。新版本中已經支持了 {%elif%} 這樣的用法。
2 {% for %}的使用
用來循環一個序列, 還可以使用reserser關鍵字來進行倒序遍歷,一般可以先用if語句判斷序列是否為空,再進行遍歷;還可以使用empty關鍵字來進行為空時的跳轉
3 {%csrf_token%}
用於生成csrf_token的標簽,用於防治跨站攻擊驗證。
注意如果你在view的index里用的是render_to_response方法,此時標簽由於沒有上下文的關系所以沒有效果,需要:
或者直接使用render。
其實,這里是會生成一個input標簽,和其他表單標簽一起提交給后台的。
4 {% load %}: 加載標簽庫
5 {% url %}: 引用路由配置的地址
6 {% with %}:用更簡單的變量名替代復雜的變量名
7 {% verbatim %}: 禁止render
{% verbatim %}
{{ hello }}
{% endverbatim %}
四 常用過濾器
1 add : 給變量加上相應的值
2 addslashes: 給變量中的引號前加上斜線
3 capfirst : 首字母大寫
4 cut : 從字符串中移除指定的字符
5 date : 格式化日期字符串
6 default : 如果值是False,就替換成設置的默認值,否則就是用本來的值
7 default_if_none:如果值是None,就替換成設置的默認值,否則就使用本來的值
五 模版的包含和繼承
包含:{% include %} 允許在模版中包含其他模版的內容。
標簽的參數可以是:模版名稱,變量,字符串
{% include 'nav.html' %}
{% include 'app/nav.html'%}
{% include template_name %}
繼承:本質上說,模版繼承就是先構造一個基礎框架模版,而后在其子模版中對它所包含站點共用部分和定義進行重載。
1 {% block %}
定義塊
2 {% extends %}
繼承父模版
注意:
1 包含和繼承可以把一些共用的網頁模塊獨立出來,以減少代碼的冗余。
2 如果在模塊里使用{% extends %}d的話,這個標簽必須在所有模版標簽的最前面,否則模版繼承不工作。
3 通常盡可能模版里的{% block %}越多越好,子模版不必定義所有的父block
4 如果你需要父模版的塊內容,{{block.super}}變量可以幫你完成工作,當你需要為父塊添加內容而不是取代它的時候這就很有用。
5 不能在同一模版(無論是父模版還是子模版)里定義多個同名{% block %} ,因為塊標簽同時在兩個地方工作,不僅在子模版中,而且在父模版中也填充內容,如果子模版有兩個同名的標簽,父模版將不能決定使用哪一個塊內容來使用。
二 admin的配置
django admin是django自帶的一個后台app,提供了后台的管理功能。
基礎知識點:
一 認識ModelAdmin
管理界面的定制類,如需擴展特定的model界面需從該類繼承
二 注冊medel類到admin的兩種方式:
1 使用register的方法
2 使用register的裝飾器
三 掌握一些常用的設置技巧
list_display: 指定要顯示的字段
search_fields:指定搜索的字段
list_filter: 指定列表過濾器
ordering:指定排序字段
三 Form
一 什么是Form?什么是DjangoForm?
Django表單系統中,所有的表單類都作為django.forms.Form的子類創建,包括ModelForm
關於django的表單系統,主要分兩種
基於django.forms.Form:所有表單類的父類
基於django.forms.ModelForm:可以和模型類綁定的Form
實例:實現添加出版社信息的功能
二 不使用Django Form的情況
三 使用Form的情況
首先,在app01中建立forms.py

######################################################### #app01下新建的forms.py from django import forms class Mypub_form(forms.Form): name = forms.CharField(label='名稱',error_messages={'required':'必填'}) address = forms.CharField(label='地址',error_messages={'required':'必填'}) city = forms.CharField(label='城市',error_messages={'required':'必填'}) state_province = forms.CharField(label='省份',error_messages={'required':'必填'}) country = forms.CharField(label='國家',error_messages={'required':'必填'}) website = forms.URLField(label='網址',error_messages={'required':'必填'}) ####################################################### #app01.views def add_publisher(req): if req.method=='POST': # #不使用django form # print(req.POST) # name=req.POST['name'] # address=req.POST.get('address') # city=req.POST['city'] # province=req.POST['province'] # country=req.POST['country'] # website=req.POST['website'] # Publisher.objects.create( # name=name, # city=city, # address=address, # state_province=province, # country=country, # website=website # ) # return HttpResponse("添加出版社信息成功!") #使用django form的情況 Mypub_form_obj=Mypub_form(req.POST) if Mypub_form_obj.is_valid(): Publisher.objects.create( name=Mypub_form_obj.cleaned_data["name"], address=Mypub_form_obj.cleaned_data["address"], city=Mypub_form_obj.cleaned_data["city"], state_province=Mypub_form_obj.cleaned_data["state_province"], country=Mypub_form_obj.cleaned_data["country"], website=Mypub_form_obj.cleaned_data["website"], ) return HttpResponse("添加出版社信息成功!") else: Mypub_form_obj=Mypub_form() return render(req,'add_publisher.html',locals()) ####################################################### #add_publisher.html <body> <form action="{% url 'add_pub' %}" method="post"> {% csrf_token %} {# 名稱:<input type="text" name="name"><br>#} {# 地址:<input type="text" name="address"><br>#} {# 城市:<input type="text" name="city"><br>#} {# 省份:<input type="text" name="province"><br>#} {# 國家:<input type="text" name="country"><br>#} {# 網址:<input type="text" name="website"><br>#} {# <input type="submit" value="提交"><br>#} {{ Mypub_form_obj.as_p }} <input type="submit" value="提交"><br> </form> </body>
四 使用ModelForm的情況

####################################################### #app01.views def add_publisher(req): if req.method=='POST': # #不使用django form # print(req.POST) # name=req.POST['name'] # address=req.POST.get('address') # city=req.POST['city'] # province=req.POST['province'] # country=req.POST['country'] # website=req.POST['website'] # Publisher.objects.create( # name=name, # city=city, # address=address, # state_province=province, # country=country, # website=website # ) # return HttpResponse("添加出版社信息成功!") #使用django form的情況 Mypub_form_obj=Mypub_form(req.POST) if Mypub_form_obj.is_valid(): # Publisher.objects.create( # name=Mypub_form_obj.cleaned_data["name"], # address=Mypub_form_obj.cleaned_data["address"], # city=Mypub_form_obj.cleaned_data["city"], # state_province=Mypub_form_obj.cleaned_data["state_province"], # country=Mypub_form_obj.cleaned_data["country"], # website=Mypub_form_obj.cleaned_data["website"], # ) Mypub_form_obj.save() return HttpResponse("添加出版社信息成功!") else: Mypub_form_obj=Mypub_form() return render(req,'add_publisher.html',locals()) ####################################################### #add_publisher.html <body> <form action="{% url 'add_pub' %}" method="post"> {% csrf_token %} {# 名稱:<input type="text" name="name"><br>#} {# 地址:<input type="text" name="address"><br>#} {# 城市:<input type="text" name="city"><br>#} {# 省份:<input type="text" name="province"><br>#} {# 國家:<input type="text" name="country"><br>#} {# 網址:<input type="text" name="website"><br>#} {# <input type="submit" value="提交"><br>#} {{ Mypub_form_obj.as_p }} <input type="submit" value="提交"><br> </form> </body>
思考:為什么有的顯示漢子,有的顯示英文
總結:
使用Django中Form可以大大簡化代碼,常用的表單功能特性都整合到了Form中,而ModelForm可以和Model進行綁定,更進一步簡化操作。
四 Form 驗證
django提供了3種方式來驗證表單
實例:自定義驗證,不能插入重名的出版社名稱。
一 表單字段的驗證器
二 clean_filedname,驗證字段,針對某個字段進行驗證。
三 表單clean方法,可針對整個表單進行驗證
像注冊時需要輸入兩次密碼的驗證,用clean來做就非常好,因為前兩種都只是針對某一個字段進行驗證,而確認密碼則需要將兩個字段信息都拿來進行匹配。
五 cookie和session
1、cookie不屬於http協議范圍,由於http協議無法保持狀態,但實際情況,我們卻又需要“保持狀態”,因此cookie就是在這樣一個場景下誕生。
cookie的工作原理是:由服務器產生內容,瀏覽器收到請求后保存在本地;當瀏覽器再次訪問時,瀏覽器會自動帶上cookie,這樣服務器就能通過cookie的內容來判斷這個是“誰”了。
2、cookie雖然在一定程度上解決了“保持狀態”的需求,但是由於cookie本身最大支持4096字節,以及cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節,並且他保存在服務器,有較高的安全性。這就是session。
問題來了,基於http協議的無狀態特征,服務器根本就不知道訪問者是“誰”。那么上述的cookie就起到橋接的作用。
我們可以給每個客戶端的cookie分配一個唯一的id,這樣用戶在訪問時,通過cookie,服務器就知道來的人是“誰”。然后我們再根據不同的cookie的id,在服務器上保存一段時間的私密資料,如“賬號密碼”等等。
3、總結而言:cookie彌補了http無狀態的不足,讓服務器知道來的人是“誰”;但是cookie以文本的形式保存在本地,自身安全性較差;所以我們就通過cookie識別不同的用戶,對應的在session里保存私密的信息以及超過4096字節的文本。
4、另外,上述所說的cookie和session其實是共通性的東西,不限於語言和框架
前幾節的介紹中我們已經有能力制作一個登陸頁面,在驗證了用戶名和密碼的正確性后跳轉到后台的頁面。但是測試后也發現,如果繞過登陸頁面。直接輸入后台的url地址也可以直接訪問的。這個顯然是不合理的。其實我們缺失的就是cookie和session配合的驗證。有了這個驗證過程,我們就可以實現和其他網站一樣必須登錄才能進入后台頁面了。
先說一下這種認證的機制。每當我們使用一款瀏覽器訪問一個登陸頁面的時候,一旦我們通過了認證。服務器端就會發送一組隨機唯一的字符串(假設是123abc)到瀏覽器端,這個被存儲在瀏覽端的東西就叫cookie。而服務器端也會自己存儲一下用戶當前的狀態,比如login=true,username=hahaha之類的用戶信息。但是這種存儲是以字典形式存儲的,字典的唯一key就是剛才發給用戶的唯一的cookie值。那么如果在服務器端查看session信息的話,理論上就會看到如下樣子的字典
{'123abc':{'login':true,'username:hahaha'}}
因為每個cookie都是唯一的,所以我們在電腦上換個瀏覽器再登陸同一個網站也需要再次驗證。那么為什么說我們只是理論上看到這樣子的字典呢?因為處於安全性的考慮,其實對於上面那個大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服務器端也是一樣被加密的。所以我們服務器上就算打開session信息看到的也是類似與以下樣子的東西
{'123abc':dasdasdasd1231231da1231231}
借用一張別的大神畫的圖,可以更直觀的看出來cookie和session的關系
知道了原理,我們下面就來用代碼實現
先在templates目錄下創建兩個html,login.html負責登錄頁面。backend頁面代表后台頁面
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> <link rel="stylesheet" href="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <form action="login.html" method="post"> <div class="form-group"> <label class="sr-only">username</label> <input type="text" class="form-control" name="username" placeholder="用戶名"/> </div> <div class="form-group"> <label class="sr-only">Password</label> <input type="password" class="form-control" name="passwd" placeholder="密碼"/> </div> <div class="form-group"> <input class="btn btn-primary" type="submit" value="http://830909.blog.51cto.com/8311014/Submit"> </div> </form> </div> <script type="application/Javascript" src="http://830909.blog.51cto.com/static/js/jquery-2.2.1.min.js"></script> <script type="application/javascript" src="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script> </body> </html>
backend.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>backend</title> <link rel="stylesheet" href="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css"> <link rel="stylesheet" href="http://830909.blog.51cto.com/static/css/commons.css"> </head> <body> <div class="container"> <h2>cookie 內容是 {{ cookie_content }}</h2> <h2>session 內容是 {{ session_content }}</h2> <h2>登錄用戶名 :{{ username }}</h2> <a href="http://830909.blog.51cto.com/logout/">注銷</a> </div> <script type="application/javascript" src="http://830909.blog.51cto.com/static/js/jquery-2.2.1.min.js"></script> <script type="application/javascript" src="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script> </body> </html>
第二步 編輯app01應用下的views.py文件,編寫代碼邏輯部分
views.py
# /usr/bin/env python # coding:utf-8 from django.shortcuts import render from django.shortcuts import redirect def login(request): if request.method=="POST": username=request.POST['username'] pwd=request.POST['passwd'] if username=='abc' and pwd=='123': #設置session內部的字典內容 request.session['is_login']='true' request.session['username']='abc' #登錄成功就將url重定向到后台的url return redirect('/backend/') #登錄不成功或第一訪問就停留在登錄頁面 return render(request,'login.html') def backend(request): """ 這里必須用讀取字典的get()方法把is_login的value缺省設置為False, 當用戶訪問backend這個url先嘗試獲取這個瀏覽器對應的session中的 is_login的值。如果對方登錄成功的話,在login里就已經把is_login 的值修改為了True,反之這個值就是False的 """ is_login=request.session.get('is_login',False) #如果為真,就說明用戶是正常登陸的 if is_login: #獲取字典的內容並傳入頁面文件 cookie_content=request.COOKIES session_content=request.session username=request.session['username'] return render(request,'backend.html', { 'cookie_content':cookie_content, 'session_content':session_content, 'username':username }) else: """ 如果訪問的時候沒有攜帶正確的session, 就直接被重定向url回login頁面 """ return redirect('/login/') def logout(request): """ 直接通過request.session['is_login']回去返回的時候, 如果is_login對應的value值不存在會導致程序異常。所以 需要做異常處理 """ try: #刪除is_login對應的value值 del request.session['is_login'] except KeyError: pass #點擊注銷之后,直接重定向回登錄頁面 return redirect('/login/')
第三步,編輯mydjango目錄下的urls.py文件。設置函數與頁面的綁定關系
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^backend/', views.backend), url(r'^logout/', views.logout), ]
最后打開瀏覽器直接訪問/backend/頁面的時候直接就被重定向到了/login/
只有在輸入了正確的用戶名和密碼之后才進入到了/backend/頁面
從上圖中我們看到有一下幾點:
1、login頁面正確登錄的話,后台頁面可以獲取到瀏覽器攜帶的cookie的。
2、第一行的sessionid其實就是cookie值
3、session的內容是加密的,從客戶端獲取不到session的內容
4、服務端可以通過預設的key值取出session的內容並打印到前段
從火狐瀏覽器里查看cookie
django的session默認是存儲在數據庫里的,我們再到數據庫查看一下真正session內容
下面我們再來最后的總結一下cookie和session的知識點
一、操作Cookie
獲取cookie:request.COOKIES[key]
設置cookie:response.set_cookie(key,value)
由於cookie保存在客戶端的電腦上,所以,jquery也可以操作cookie。
<script src='http://830909.blog.51cto.com/static/js/jquery.cookie.js'></script> $.cookie("list_pager_num", 30,{ path: '/' });
二、操作Session(session默認在服務器端保存15天)
獲取session:request.session[key]
設置session:reqeust.session[key] = value
刪除session:del request.session[key]
(這個刪除其實就是把數據庫的session_data更新為一個其他的值了,並沒有立即刪除)
request.session.set_expiry(value) * 如果value是個整數,session會在些秒數后失效。 * 如果value是個datatime或timedelta,session就會在這個時間后失效。 * 如果value是0,用戶關閉瀏覽器session就會失效。 * 如果value是None,session會依賴全局session失效策略。
參考:
http://www.07net01.com/2016/03/1364624.html