Django那些事
Django
1. 簡述Http協議?
即超文字傳輸協議
特點:
無狀態:請求響應之後,再次發起請求時,並沒有儲存客戶端和服務端臨時對話產生的資料。
短連線:一次請求和一次響應就斷開連線。
格式:
GET請求:
輸入地址回車:https://passport.jd.com/new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F
請求由兩部分組成:請求頭和請求體,請求頭和請求體通過\r\n\r\n分割,請求頭和請求頭之間通過\r\n分割。
"""GET /new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F http1.1\r\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\r\nHost:jd.com\r\n\r\n"""
響應由兩部分組成:響應頭和響應體,
b'HTTP/1.1 200 OK\r\nDate: Mon, 05 Nov 2018 01:15:31 GMT\r\nServer: Apache\r\nLast-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\nETag: "51-47cf7e6ee8400"\r\nAccept-Ranges: bytes\r\nContent-Length: 81\r\nCache-Control: max-age=86400\r\nExpires: Tue, 06 Nov 2018 01:15:31 GMT\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n <html><head> .... </html>'
POST請求:
請求由兩部分組成:請求頭和請求頭
"""POST /new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F http1.1\r\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\r\nHost:jd.com\r\n\r\nusername=haoxu666&password=123"""
響應:
b'HTTP/1.1 200 OK\r\nDate: Mon, 05 Nov 2018 01:15:31 GMT\r\nServer: Apache\r\nLast-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\nETag: "51-47cf7e6ee8400"\r\nAccept-Ranges: bytes\r\nContent-Length: 81\r\nCache-Control: max-age=86400\r\nExpires: Tue, 06 Nov 2018 01:15:31 GMT\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n使用者名稱或密碼錯誤
2. 你瞭解的請求頭都有什麼?
- User-Agent,裝置資訊。
- Host,當前訪問的主機名稱。
- referrer,做防盜鏈。
- Content-Type: ....
- cookie:
- accept
響應頭:
- Connection:keep-Alive 做優化
- Set Cookie
3. 你瞭解的請求方式有哪些?
- GET/POST/PUT/PATCH/DELETE/OPTIONS
4. django請求的生命週期/瀏覽器上輸入 http://www.oldboyedu.com 地址回車發生了什麼?
- 瀏覽器輸入:http://www.oldboyedu.com 回車
- DNS解析,將域名解析成IP。
- 瀏覽器(socket客戶端),根據IP和埠(80)建立連線,傳送請求。
- 服務端接收請求
- 實現了wsgi協議的模組,如:wsgiref接收到使用者請求。
- 然後將請求轉交給django的中介軟體,執行中介軟體的process_request(process_view)。
- 路由系統進行路由匹配。
- 匹配成功執行檢視函式,檢視函式進行業務處理(ORM操作資料+模板渲染)
- 交給中介軟體的process_response方法
- wsigref的socket.send,將結果返回給瀏覽器。
- 斷開socket連線。
- 瀏覽器斷開連線。
詳細:見django請求生命週期圖
5. 什麼是wsgi?
wsgi,web服務閘道器介面,他是一套協議。
實現wsgi協議有:
- wsgiref 只能用於本地測試,效能差 單程序單執行緒
- uwsgi 可併發
實現wsgi協議的所有的模組本質:socket服務端。
6. django中介軟體的作用?應用場景?
中介軟體,可以對所有請求進行批量操作。
應用場景:
- 自己玩
- 記錄日誌
- IP黑名單
- 工作場景:
- 許可權系統中的許可權校驗
- 解決跨域:編寫一箇中間件,在中介軟體中定義一個process_response,新增一個響應頭(CORS,跨站資源共享)
- 使用者登入
- csrf_token驗證(django內建功能)
細節:
- 5個方法:process_request/process_response + 3
- 執行流程
正常流程:
- 所有process_request
- 所有process_view
- 所有process_response
非正常流程:
- django 1.10及以後:平級返回
- django 1.10以前:找到最後的process_response
- 任意匯入一個原始碼檢視,如: # from django.middleware.common import CommonMiddleware MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]忘記方法名稱或方法引數個數
- 執行流程是如何實現的?
將中介軟體的相關方法新增到對應的 5個列表中,以後迴圈執行(順序、倒序)
原始碼:
class BaseHandler(object):
def init(self):
self._request_middleware = None
self._view_middleware = None
self._template_response_middleware = None
self._response_middleware = None
self._exception_middleware = None
self._middleware_chain = None
def load_middleware(self):
“”"
Populate middleware lists from settings.MIDDLEWARE (or the deprecated
MIDDLEWARE_CLASSES).
Must be called after the environment is fixed (see call in subclasses).
“”"
self._request_middleware = []
self._view_middleware = []
self._template_response_middleware = []
self._response_middleware = []
self._exception_middleware = []
if settings.MIDDLEWARE is None:
warnings.warn(
"Old-style middleware using settings.MIDDLEWARE_CLASSES is "
"deprecated. Update your middleware and use settings.MIDDLEWARE "
“instead.”, RemovedInDjango20Warning
)
handler = convert_exception_to_response(self._legacy_get_response)
for middleware_path in settings.MIDDLEWARE_CLASSES:
mw_class = import_string(middleware_path)
try:
mw_instance = mw_class()
except MiddlewareNotUsed as exc:
if settings.DEBUG:
if six.text_type(exc):
logger.debug(‘MiddlewareNotUsed(%r): %s’, middleware_path, exc)
else:
logger.debug(‘MiddlewareNotUsed: %r’, middleware_path)
continue
if hasattr(mw_instance, ‘process_request’):
self._request_middleware.append(mw_instance.process_request)
if hasattr(mw_instance, ‘process_view’):
self._view_middleware.append(mw_instance.process_view)
if hasattr(mw_instance, ‘process_template_response’):
self._template_response_middleware.insert(0, mw_instance.process_template_response)
if hasattr(mw_instance, ‘process_response’):
self._response_middleware.insert(0, mw_instance.process_response)
if hasattr(mw_instance, ‘process_exception’):
self._exception_middleware.insert(0, mw_instance.process_exception)
else:
handler = convert_exception_to_response(self._get_response)
for middleware_path in reversed(settings.MIDDLEWARE):
middleware = import_string(middleware_path)
try:
mw_instance = middleware(handler)
except MiddlewareNotUsed as exc:
if settings.DEBUG:
if six.text_type(exc):
logger.debug(‘MiddlewareNotUsed(%r): %s’, middleware_path, exc)
else:
logger.debug(‘MiddlewareNotUsed: %r’, middleware_path)
continue
if mw_instance is None:
raise ImproperlyConfigured(
‘Middleware factory %s returned None.’ % middleware_path
)
if hasattr(mw_instance, ‘process_view’):
self._view_middleware.insert(0, mw_instance.process_view)
if hasattr(mw_instance, ‘process_template_response’):
self._template_response_middleware.append(mw_instance.process_template_response)
if hasattr(mw_instance, ‘process_exception’):
self._exception_middleware.append(mw_instance.process_exception)
handler = convert_exception_to_response(mw_instance)
# We only assign to this when initialization is complete as it is used
# as a flag for initialization being complete.
self._middleware_chain = handler
- 根據字串的形式匯入模組 + 根據反射找到模組中的成員
相關知識點:
- 流程實現原理:列表+列表翻轉
- 根據字串的形式匯入模組+反射
常見的狀態碼:
1XX系列:指定客戶端應相應的某些動作,代表請求已被接受,需要繼續處理。由於 HTTP/1.0 協議中沒有定義任何 1xx 狀態碼,所以除非在某些試驗條件下,伺服器禁止向此類客戶端傳送 1xx 響應。
2XX系列:代表請求已成功被伺服器接收、理解、並接受。這系列中最常見的有200、201狀態碼。
200狀態碼:表示請求已成功,請求所希望的響應頭或資料體將隨此響應返回
201狀態碼:表示請求成功並且伺服器建立了新的資源,且其 URI 已經隨Location 頭資訊返回。假如需要的資源無法及時建立的話,應當返回 ‘202 Accepted’
202狀態碼:伺服器已接受請求,但尚未處理
3XX系列:代表需要客戶端採取進一步的操作才能完成請求,這些狀態碼用來重定向,後續的請求地址(重定向目標)在本次響應的 Location 域中指明。這系列中最常見的有301、302狀態碼。
301狀態碼:被請求的資源已永久移動到新位置。伺服器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。
302狀態碼:請求的資源臨時從不同的URI響應請求,但請求者應繼續使用原有位置來進行以後的請求
304自從上次請求後,請求的網頁未修改過。伺服器返回此響應時,不會返回網頁內容。 如果網頁自請求者上次請求後再也沒有更改過,您應將伺服器配置為返回此響應(稱為 If</span>-Modified-<span style="color: #000000">Since HTTP 標頭)。
4XX系列:表示請求錯誤。代表了客戶端看起來可能發生了錯誤,妨礙了伺服器的處理。常見有:401、404狀態碼。
401狀態碼:請求要求身份驗證。 對於需要登入的網頁,伺服器可能返回此響應。
403狀態碼:伺服器已經理解請求,但是拒絕執行它。與401響應不同的是,身份驗證並不能提供任何幫助,而且這個請求也不應該被重複提交。
404狀態碼:請求失敗,請求所希望得到的資源未被在伺服器上發現。沒有資訊能夠告訴使用者這個狀況到底是暫時的還是永久的。假如伺服器知道情況的話,應當使用410狀態碼來告知舊資源因為某些內部的配置機制問題,已經永久的不可用,而且沒有任何可以跳轉的地址。404這個狀態碼被廣泛應用於當伺服器不想揭示到底為何請求被拒絕或者沒有其他適合的響應可用的情況下。
5xx系列:代表了伺服器在處理請求的過程中有錯誤或者異常狀態發生,也有可能是伺服器意識到以當前的軟硬體資源無法完成對請求的處理。常見有500、503狀態碼。
500狀態碼:伺服器遇到了一個未曾預料的狀況,導致了它無法完成對請求的處理。一般來說,這個問題都會在伺服器的程式碼出錯時出現。
503狀態碼:由於臨時的伺服器維護或者過載,伺服器當前無法處理請求。通常,這個是暫時狀態,一段時間會恢復