1.視圖簡介
做用:接受web請求,返回web響應html
本質:一個函數,定義在views.py文件中(定義在其餘地方也行,約定俗成)python
流程:(若是匹配不到,報一個404錯誤)-----結果返回http response對象mysql
1.1 視圖配置
在settings.py文件的ROOT_URLCONF部分指定根級url的配置(指向urls.py文件)web
查找流程,mannage.py→settings.py→urls.py正則表達式
習慣上,每一個應用(APP)單獨配置本身的urls.py,不寫在根目錄,防止由於應用過多,看起來太混亂很差維護,sql
配置本身的url:只需建立應用後在應用文件中建立urls.py文件(在根目錄中包含)數據庫
1.2 簡單的演示
根目錄下的urls.py文件django
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^booktest/', include('booktest.urls')), ]
app目錄下的url.py文件瀏覽器
from django.conf.urls import url from booktest import views urlpatterns = [ url(r'^$',views.index), ]
views.py文件緩存
from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse("Hello World!")
啓動django
python manage.py runserver
訪問網址
1.3 匹配規則
第一步:去掉域名和端口號
第二步:在根目錄下匹配(匹配成功,進入include)
第三步:去掉根目錄裏面已經匹配成功的,繼續在APP中urls.py匹配(匹配成功,執行對應views.py中的函數)
第四步:執行view.py中的函數
匹配的時候,能夠利用正則中的()能夠保留匹配的內容,形如:(\d+)
1.4 urlconf
#正則表達式非命名組,經過位置參數傳遞給視圖 url(r'^([0-9]+)/$', views.detail, name='detail'), #正則表達式命名組,經過關鍵字參數傳遞給視圖,本例中關鍵字參數爲id url(r'^(?P<id>[0-9]+)/$', views.detail, name='detail'),
- 參數匹配規則:優先使用關鍵字(命名)參數,若是沒有命名參數則使用位置參數
- 每一個捕獲的參數都做爲一個普通的python字符串傳遞給視圖
- 性能:urlpatterns中的每一個正則表達式在第一次訪問它們時被編譯,這使得系統至關快
# namespace跟url裏面的name同樣,起名字用於反向解析 url(r'^', include('booktest.urls', namespace='booktest')),
1.5 反向解析(以後在寫)
- 若是在視圖、模板中使用硬編碼的連接,在urlconf發生改變時,維護是一件很是麻煩的事情
- 解決:在作連接時,經過指向urlconf的名稱,動態生成連接地址
- 視圖:使用django.core.urlresolvers.reverse()函數
- 模板:使用url模板標籤
2. 視圖函數
2.1 基本視圖
調用,views內對應的函數便可,
2.2 錯誤視圖(404未找到,500服務器未響應,400錯誤來自客戶端)
Django原生自帶幾個默認視圖用於處理HTTP錯誤
第一步:項目目錄下,添加templates文件夾
第二步:settings.py 中添加模板路徑
第三步:在templates中建立404.html(調試狀態下,看不到這頁面)
settings.py 設置DEBUG爲False
設置容許誰請求主機
404.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>找不到,404</h1> {{ request_path}}} </body> </html>
啓動,錯誤的訪問的結果爲:
3. Reqeust對象(接收的對象)
在django.http模塊中定義了HttpRequest對象的API
3.1 屬性
下面除非特別說明,屬性都是隻讀的
path:一個字符串,表示請求的頁面的完整路徑,不包含域名
def index(request): return HttpResponse(request.path)
method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST'
encoding:一個字符串,表示提交的數據的編碼方式
若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8
這個屬性是可寫的,能夠經過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值
GET:一個相似於字典的對象,包含get請求方式的全部參數
POST:一個相似於字典的對象,包含post請求方式的全部參數
FILES:一個相似於字典的對象,包含全部的上傳文件
COOKIES:一個標準的Python字典,包含全部的cookie,鍵和值都爲字符串
session:一個既可讀又可寫的相似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見「狀態保持」
這些屬性的用法相似
from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse( # request.path, # request.method, # request.encoding, request.GET, # request.POST, # request.FILES, # request.COOKIES, # request.session, )
3.2 相似字典對象(QueryDict對象)
字典:鍵值對,鍵不能相同
QueryDict:鍵值對,鍵能相同,若是同一鍵有多個值,獲取最後一個值
get():根據鍵獲取值,類字典
dict.get('鍵',default) #或簡寫爲 dict['鍵']
getlist():根據鍵獲取多個值
#將鍵的值以列表返回,能夠獲取一個鍵的多個值 dict.getlist('鍵',default)
3.3 GET屬性
- QueryDict類型的對象
- 包含get請求方式的全部參數
- 與url請求地址中的參數對應,位於?後面
- 參數的格式是鍵值對,如key1=value1
- 多個參數之間,使用&鏈接,如key1=value1&key2=value2
- 鍵是開發人員定下來的,值是可變的
對應三種視圖getTest1用於定義連接,getTest2用於接收一鍵一值,getTest3用於接收一鍵多值
views.py
from django.shortcuts import render # Create your views here. # 展現連接的頁面 def getTest1(request): return render(request, 'booktest/getTest1.html') # 接收一鍵一值的狀況 def getTest2(request): # request.GET.get('a') # 根據鍵接收值 a1 = request.GET['a'] b1 = request.GET['b'] c1 = request.GET['c'] # 構造上下文 context = {'a':a1,'b':b1,'c':c1} # 向模板傳遞上下文,並渲染 return render(request, 'booktest/getTest2.html', context=context) # 接收一鍵多值的狀況 def getTest3(request): # 獲得最後一個 a1 = request.GET['a'] # 獲得多個 a2 = request.GET.getlist('a') c1 = request.GET['c'] contest = {'a':a1,'a1':a2,'c':c1} return render(request, 'booktest/getTest3.html',context=contest)
配置urls.py(APP裏面的)
from django.conf.urls import url from booktest import views urlpatterns = [ url(r'^getTest1/$',views.getTest1), url(r'^getTest2/$',views.getTest2), url(r'^getTest3/$',views.getTest3), ]
配置模板
getTest1.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>test1</title> </head> <body> 一鍵一值:<a href="/booktest/getTest2/?a=1&b=2&c=3">test2</a> <hr> 一鍵多值:<a href="/booktest/getTest3/?a=1&a=2&c=3">test3</a> </body> </html>
效果:
getTest2.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>test2</title> </head> <body> a:{{a}} <hr> b:{{b}} <hr> c:{{c}} </body> </html>
效果
getTest3.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>test3</title> </head> <body> a:{{a}} <br> a1:{{a1}} <br> a2:{%for item in a1 %} {{ item }} {% endfor %} <br> c:{{c}} </body> </html>
效果
3.4 POST屬性
- QueryDict類型的對象
- 包含post請求方式的全部參數
- 與form表單中的控件對應
- 問:表單中哪些控件會被提交?
- 答:控件要有name屬性,則name屬性的值爲鍵,value屬性的值爲鍵,構成鍵值對提交
- 對於checkbox控件,name屬性同樣爲一組,當控件被選中後會被提交,存在一鍵多值的狀況
- 鍵是開發人員定下來的,值是可變的
使用表單提交,註釋掉settings.py中的中間件crsf
views.py
from django.shortcuts import render # Create your views here. # 提交表單 def postTest1(request): return render(request,'booktest/postTest1.html') # 展現提交的表單內容 def postTest2(request): # 表單的name做爲鍵,value做爲值傳遞過來 uname = request.POST['uname'] upwd = request.POST['upwd'] ugender = request.POST['ugender'] uhobby = request.POST.getlist('uhobby') context = {'uname': uname, 'upwd': upwd, 'ugender': ugender, 'uhobby': uhobby} return render(request,'booktest/postTest2.html',context=context)
配置urls.py(APP裏面的)
from django.conf.urls import url from booktest import views urlpatterns = [ # url(r'^getTest1/$',views.getTest1), # url(r'^getTest2/$',views.getTest2), # url(r'^getTest3/$',views.getTest3), url(r'^postTest1/$',views.postTest1), url(r'^postTest2/$',views.postTest2), ]
配置模板
postTest1.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>postTest1</title> </head> <body> <form action="/booktest/postTest2/" method="post"> 姓名:<input type="text" name="uname"/><br> 密碼:<input type="password" name="upwd"/><br> 性別:<input type="radio" name="ugender" value="1"/>男 <input type="radio" name="ugender" value="0"/>女<br> 愛好:<input type="checkbox" name="uhobby" value="玩LOL"/>玩LOL <input type="checkbox" name="uhobby" value="跳樓"/>跳樓 <input type="checkbox" name="uhobby" value="喝酒"/>喝酒 <input type="checkbox" name="uhobby" value="登山"/>登山<br> <input type="submit" value="提交"/> </form> </body> </html>
效果:
postTest2.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>postTest2</title> </head> <body> {{ uname }}<br> {{ upwd }}<br> {{ ugender }}<br> {{ uhobby }} </body> </html>
效果:
4. Response對象(發送的對象)
4.1 屬性
- content:表示返回的內容,字符串類型
- charset:表示response採用的編碼字符集,字符串類型
- status_code:響應的HTTP響應狀態碼
- content-type:指定輸出的MIME類型(解析方式)
4.2 方法
- init :使用頁內容實例化HttpResponse對象
- write(content):以文件的方式寫
- flush():以文件的方式輸出緩存區
- set_cookie(key, value='', max_age=None, expires=None):設置Cookie
- key、value都是字符串類型
- max_age是一個整數,表示在指定秒數後過時
- expires是一個datetime或timedelta對象,會話將在這個指定的日期/時間過時,注意datetime和timedelta值只有在使用PickleSerializer時纔可序列化
- max_age與expires二選一
- 若是不指定過時時間,則兩個星期後過時
views.py
from django.shortcuts import render from django.http import HttpResponse from datetime import * # Create your views here. def cookieTest(request): response = HttpResponse() cookie = request.COOKIES if 't1' in cookie: response.write(cookie['t1']) response.set_cookie('t1','abcaaa') return response
urls.py
url(r'^cookieTest/$',views.cookieTest),
效果:
4.3 重定向
通常做爲:登陸成功後,轉向新的頁面
HttpResponseRedirect類繼承於HttpResponse
views.py
from django.shortcuts import render,redirect from django.http import HttpResponse,HttpResponseRedirect # Create your views here. def redTest1(request): # return HttpResponseRedirect('/booktest/redTest2/') # 跟上面功能一致,也用於重定向(簡寫) return redirect('/booktest/redTest2/') # 轉向來的頁面 def redTest2(request): return HttpResponse("這是轉向來的頁面")
urls.py
url(r'^redTest1/$',views.redTest1), url(r'^redTest2/$',views.redTest2),
效果:訪問:http://127.0.0.1:8000/booktest/redTest1/
自動跳轉,效果
4.4 狀態保持
- http協議是無狀態的:每次請求都是一次新的請求,不會記得以前通訊的狀態
- 客戶端與服務器端的一次通訊,就是一次會話
- 實現狀態保持的方式:在客戶端或服務器端存儲與會話有關的數據
- 存儲方式包括cookie、session,會話通常指session對象
- 使用cookie,全部數據存儲在客戶端,注意不要存儲敏感信息
- 推薦使用sesison方式,全部數據存儲在服務器端,在客戶端cookie中存儲session_id
- 狀態保持的目的是在一段時間內跟蹤請求者的狀態,能夠實現跨頁面訪問當前請求者的數據
- 注意:不一樣的請求者之間不會共享這個數據,與請求者一一對應
Django默認就啓用Session,不用就去settings.py中禁用
使用Session(會存到數據庫中去)
- 啓用會話後,每一個HttpRequest對象將具備一個session屬性,它是一個類字典對象
- get(key, default=None):根據鍵獲取會話的值
- clear():清除全部會話
- flush():刪除當前的會話數據並刪除會話的Cookie
- del request.session['member_id']:刪除會話
views.py
from django.shortcuts import render, redirect from django.http import HttpResponse, HttpResponseRedirect # Create your views here. # 第一個登陸顯示頁面 def session1(request): # 鍵不存在,設置默認值 uname = request.session.get('myname','未登陸') context = {'uname': uname} return render(request, 'booktest/session1.html', context=context) # 登陸表單提交階段 def session2(request): return render(request, 'booktest/session2.html') # 刪除session,退出 def session3(request): del request.session['myname'] return redirect('/booktest/session1/') def session2_handle(request): uname = request.POST['uname'] # session對象(字典) 往session對象中寫對象 request.session['myname'] = uname # 重定向,顯示登陸的頁面 return redirect('/booktest/session1/')
urls.py
url(r'^session1/$',views.session1), url(r'^session2/$',views.session2), url(r'^session2_handle/$',views.session2_handle), url(r'^session3/$',views.session3),
session1.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>login</title> </head> <body> <h1>你好:{{ uname }}</h1> <br> <a href="/booktest/session2/">登陸</a> <br> <a href="/booktest/session3/">退出</a> </body> </html>
效果:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>表單</title> </head> <body> <form action="/booktest/session2_handle/" method="post"> <input type="text" name="uname"> <input type="submit" name="登陸"> </form> </body> </html>
效果:
由於Session須要存到數據庫:須要進行數據遷移-------這個須要運行前先遷移
settings.py(能夠用已經遷移過的數據庫、表)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test2', 'USER':'root', 'PASSWORD':'', 'HOST':'localhost', 'POST':'3306', } }
提交表單後效果
點擊退出後的效果(使用默認值,清楚session)
4.5 會話
會話過時時間
- set_expiry(value):設置會話的超時時間
- 若是沒有指定,則兩個星期後過時
- 若是value是一個整數,會話將在values秒沒有活動後過時
- 若果value是一個imedelta對象,會話將在當前時間加上這個指定的日期/時間過時
- 若是value爲0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時
- 若是value爲None,那麼會話永不過時
- 修改視圖中session2_handle函數,查看效果
def session2_handle(request): uname = request.POST['uname'] # session對象(字典) 往session對象中寫對象 request.session['myname'] = uname # 設置會話過時時間 request.session.set_expiry(0) # 重定向,顯示登陸的頁面 return redirect('/booktest/session1/')
存儲session
數據庫中的session
base64解碼--session_data
- 使用存儲會話的方式,能夠使用settings.py的SESSION_ENGINE項指定
- 基於數據庫的會話:這是django默認的會話存儲方式,須要添加django.contrib.sessions到的INSTALLED_APPS設置中,運行manage.py migrate在數據庫中安裝會話表,可顯示指定爲
SESSION_ENGINE='django.contrib.sessions.backends.db'
存在緩存
SESSION_ENGINE='django.contrib.sessions.backends.cache'
存在數據庫+緩存
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
流程