請求
回想一下,利用HTTP協議向服務器傳參有幾種途徑?
- 提取URL的特定部分,如/weather/beijing/2018,可以在服務器端的路由中用正則表達式截取;
- 查詢字符串(query string),形如key1=value1&key2=value2;
- 請求體(body)中發送的數據,比如表單數據、json、xml;
- 在http報文的頭(header)中。
1 URL路徑參數
在定義路由URL時,可以使用正則表達式提取參數的方法從URL中獲取請求參數,Django會將提取的參數直接傳遞到視圖的傳入參數中。
-
未命名參數按定義順序傳遞, 如
url(r'^weather/([a-z]+)/(\d{4})/$', views.weather), def weather(request, city, year): print('city=%s' % city) print('year=%s' % year) return HttpResponse('OK') -
命名參數按名字傳遞,如
url(r'^weather/(?P<city>[a-z]+)/(?P<year>\d{4})/$', views.weather), def weather(request, year, city): print('city=%s' % city) print('year=%s' % year) return HttpResponse('OK')
2 Django中的QueryDict對象
定義在django.http.QueryDict
HttpRequest對象的屬性GET、POST都是QueryDict類型的對象
與python字典不同,QueryDict類型的對象用來處理同一個鍵帶有多個值的情況
-
方法get():根據鍵獲取值
如果一個鍵同時擁有多個值將獲取最后一個值
如果鍵不存在則返回None值,可以設置默認值進行后續處理
dict.get('鍵',默認值) 可簡寫為 dict['鍵'] -
方法getlist():根據鍵獲取值,值以列表返回,可以獲取指定鍵的所有值
如果鍵不存在則返回空列表[],可以設置默認值進行后續處理
dict.getlist('鍵',默認值)
3. 查詢字符串Query String
獲取請求路徑中的查詢字符串參數(形如?k1=v1&k2=v2),可以通過request.GET屬性獲取,返回QueryDict對象。
# /qs/?a=1&b=2&a=3 def qs(request): a = request.GET.get('a') b = request.GET.get('b') alist = request.GET.getlist('a') print(a) # 3 print(b) # 2 print(alist) # ['1', '3'] return HttpResponse('OK')
重要:查詢字符串不區分請求方式,即假使客戶端進行POST方式的請求,依然可以通過request.GET獲取請求中的查詢字符串數據。
4 請求體
請求體數據格式不固定,可以是表單類型字符串,可以是JSON字符串,可以是XML字符串,應區別對待。
可以發送請求體數據的請求方式有POST、PUT、PATCH、DELETE。
Django默認開啟了CSRF防護,會對上述請求方式進行CSRF防護驗證,在測試時可以關閉CSRF防護機制,方法為在settings.py文件中注釋掉CSRF中間件,如:

4.1 表單類型 Form Data
前端發送的表單類型的請求體數據,可以通過request.POST屬性獲取,返回QueryDict對象。
def get_body(request): a = request.POST.get('a') b = request.POST.get('b') alist = request.POST.getlist('a') print(a) print(b) print(alist) return HttpResponse('OK')
重要:request.POST只能用來獲取POST方式的請求體表單數據。
4.2 非表單類型 Non-Form Data
非表單類型的請求體數據,Django無法自動解析,可以通過request.body屬性獲取最原始的請求體數據,自己按照請求體格式(JSON、XML等)進行解析。request.body返回bytes類型。
例如要獲取請求體中的如下JSON數據
{"a": 1, "b": 2}
可以進行如下方法操作:
import json def get_body_json(request): json_str = request.body json_str = json_str.decode() # python3.6 無需執行此步 req_data = json.loads(json_str) print(req_data['a']) print(req_data['b']) return HttpResponse('OK')
5 請求頭
可以通過request.META屬性獲取請求頭headers中的數據,request.META為字典類型。
常見的請求頭如:
CONTENT_LENGTH– The length of the request body (as a string).CONTENT_TYPE– The MIME type of the request body.HTTP_ACCEPT– Acceptable content types for the response.HTTP_ACCEPT_ENCODING– Acceptable encodings for the response.HTTP_ACCEPT_LANGUAGE– Acceptable languages for the response.HTTP_HOST– The HTTP Host header sent by the client.HTTP_REFERER– The referring page, if any.HTTP_USER_AGENT– The client’s user-agent string.QUERY_STRING– The query string, as a single (unparsed) string.REMOTE_ADDR– The IP address of the client.REMOTE_HOST– The hostname of the client.REMOTE_USER– The user authenticated by the Web server, if any.REQUEST_METHOD– A string such as"GET"or"POST".SERVER_NAME– The hostname of the server.SERVER_PORT– The port of the server (as a string).
具體使用如:
def get_headers(request): print(request.META['CONTENT_TYPE']) return HttpResponse('OK')
6 其他常用HttpRequest對象屬性
- method:一個字符串,表示請求使用的HTTP方法,常用值包括:'GET'、'POST'。
- user:請求的用戶對象。
- path:一個字符串,表示請求的頁面的完整路徑,不包含域名和參數部分。
- encoding:一個字符串,表示提交的數據的編碼方式。
- 如果為None則表示使用瀏覽器的默認設置,一般為utf-8。
- 這個屬性是可寫的,可以通過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值。
- FILES:一個類似於字典的對象,包含所有的上傳文件。
響應
視圖在接收請求並處理后,必須返回HttpResponse對象或子對象。HttpRequest對象由Django創建,HttpResponse對象由開發人員創建。
1 HttpResponse
可以使用django.http.HttpResponse來構造響應對象。
HttpResponse(content=響應體, content_type=響應體數據類型, status=狀態碼)
也可通過HttpResponse對象屬性來設置響應體、狀態碼:
- content:表示返回的內容。
- status_code:返回的HTTP響應狀態碼。
響應頭可以直接將HttpResponse對象當做字典進行響應頭鍵值對的設置:
response = HttpResponse()
response['Itcast'] = 'Python' # 自定義響應頭Itcast, 值為Python
示例:
from django.http import HttpResponse def demo_view(request): return HttpResponse('itcast python', status=400) 或者 response = HttpResponse('itcast python') response.status_code = 400 response['Itcast'] = 'Python' return response
2 HttpResponse子類
Django提供了一系列HttpResponse的子類,可以快速設置狀態碼
- HttpResponseRedirect 301
- HttpResponsePermanentRedirect 302
- HttpResponseNotModified 304
- HttpResponseBadRequest 400
- HttpResponseNotFound 404
- HttpResponseForbidden 403
- HttpResponseNotAllowed 405
- HttpResponseGone 410
- HttpResponseServerError 500
3 JsonResponse
若要返回json數據,可以使用JsonResponse來構造響應對象,作用:
- 幫助我們將數據轉換為json字符串
- 設置響應頭Content-Type為 application/json
from django.http import JsonResponse def demo_view(request): return JsonResponse({'city': 'beijing', 'subject': 'python'})
4 redirect重定向
from django.shortcuts import redirect def demo_view(request): return redirect('/index.html')
Cookie
Cookie,有時也用其復數形式Cookies,指某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據(通常經過加密)。Cookie最早是網景公司的前雇員Lou Montulli在1993年3月的發明。Cookie是由服務器端生成,發送給User-Agent(一般是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置為啟用cookie)。Cookie名稱和值可以由服務器端開發自己定義,這樣服務器可以知道該用戶是否是合法用戶以及是否需要重新登錄等。服務器可以利用Cookies包含信息的任意性來篩選並經常性維護這些信息,以判斷在HTTP傳輸中的狀態。Cookies最典型記住用戶名。
Cookie是存儲在瀏覽器中的一段純文本信息,建議不要存儲敏感信息如密碼,因為電腦上的瀏覽器可能被其它人使用。
Cookie的特點
- Cookie以鍵值對的格式進行信息的存儲。
- Cookie基於域名安全,不同域名的Cookie是不能互相訪問的,如訪問itcast.cn時向瀏覽器中寫了Cookie信息,使用同一瀏覽器訪問baidu.com時,無法訪問到itcast.cn寫的Cookie信息。
- 當瀏覽器請求某網站時,會將瀏覽器存儲的跟網站相關的所有Cookie信息提交給網站服務器。
1 設置Cookie
可以通過HttpResponse對象中的set_cookie方法來設置cookie。
HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
- max_age 單位為秒,默認為None。如果是臨時cookie,可將max_age設置為None。
示例:
def demo_view(request): response = HttpResponse('ok') response.set_cookie('itcast1', 'python1') # 臨時cookie response.set_cookie('itcast2', 'python2', max_age=3600) # 有效期一小時 return response
2 讀取Cookie
可以通過HttpRequest對象的COOKIES屬性來讀取本次請求攜帶的cookie值。request.COOKIES為字典類型。
def demo_view(request): cookie1 = request.COOKIES.get('itcast1') print(cookie1) return HttpResponse('OK')
Session
1 啟用Session
Django項目默認啟用Session。
可以在settings.py文件中查看,如圖所示

如需禁用session,將上圖中的session中間件注釋掉即可。
2 存儲方式
在settings.py文件中,可以設置session數據的存儲方式,可以保存在數據庫、本地緩存等。
2.1 數據庫
存儲在數據庫中,如下設置可以寫,也可以不寫,這是默認存儲方式。
SESSION_ENGINE='django.contrib.sessions.backends.db'
如果存儲在數據庫中,需要在項INSTALLED_APPS中安裝Session應用。

數據庫中的表如圖所示

表結構如下

由表結構可知,操作Session包括三個數據:鍵,值,過期時間。
2.2 本地緩存
存儲在本機內存中,如果丟失則不能找回,比數據庫的方式讀寫更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
2.3 混合存儲
優先從本機內存中存取,如果沒有則從數據庫中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
2.4 Redis
在redis中保存session,需要引入第三方擴展,我們可以使用django-redis來解決。
1) 安裝擴展
pip install django-redis
2)配置
在settings.py文件中做如下設置
CACHES = {
"default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"
注意
如果redis的ip地址不是本地回環127.0.0.1,而是其他地址,訪問Django時,可能出現Redis連接錯誤,如下:

解決方法:
修改redis的配置文件,添加特定ip地址。
打開redis的配置文件
sudo vim /etc/redis/redis.conf
在如下配置項進行修改(如要添加10.211.55.5地址)

重新啟動redis服務
sudo service redis-server restart
3 Session操作
通過HttpRequest對象的session屬性進行會話的讀寫操作。
1) 以鍵值對的格式寫session。
request.session['鍵']=值
2)根據鍵讀取值。
request.session.get('鍵',默認值)
3)清除所有session,在存儲中刪除值部分。
request.session.clear()
4)清除session數據,在存儲中刪除session的整條數據。
request.session.flush()
5)刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值。
del request.session['鍵']
6)設置session的有效期
request.session.set_expiry(value)
- 如果value是一個整數,session將在value秒沒有活動后過期。
- 如果value為0,那么用戶session的Cookie將在用戶的瀏覽器關閉時過期。
- 如果value為None,那么session有效期將采用系統默認值,默認為兩周,可以通過在settings.py中設置SESSION_COOKIE_AGE來設置全局默認值。
