Django框架基本原理1
阿新 • • 發佈:2018-04-02
patch body code spl 所有 net username register django框架
Django之請求的本質
本質上django程序就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端;
在遵循http協議的基礎上兩方進行通訊;
以django為例: 涉及到底層socket方面(接收和解析瀏覽器的請求信息, 響應頭和響應體的發送都是由django的wsgi模塊完成的,用戶只需要實現路由和視圖函數,模板等代碼部分即可):
請求頭和請求體以兩個
\r\n
分隔開, 請求頭的內容也是以\r\n
分開, 相應頭和響應體同理;Cookie信息是在請求頭和響應頭中存放的;
// 在瀏覽器輸入 http://127.0.0.1:8001/ 即可看到發送的信息 import socket def handle_request(client): # 相當於接收用戶信息,在做出相應的反饋... buf = client.recv(1024) # response(響應頭和響應體) client.send("HTTP/1.1 200 OK\r\n\r\n<h1 style=‘color:red‘>Hello, yuan</h1>".encode("utf8")) # 響應體也可以分開寫 # client.send("<h1 style=‘color:red‘>Hello, yuan</h1>".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind((‘localhost‘, 8002)) sock.listen(5) while True: connection, address = sock.accept() # 處理用戶信息 handle_request(connection) connection.close() if __name__ == ‘__main__‘: main()
自定義web框架
可以將這個三部分分為放在三個文件中,在bin主代碼區導入urls和view函數即可;
# views文件 ------------------------------- def f1(request): f = open("alex.html", ‘rb‘) data = f.read() f.close() return [data] def f2(request): f = open("egon.html", ‘rb‘) data = f.read() f.close() return [data] def log_in(request): f = open("login.html", ‘rb‘) data = f.read() f.close() return [data] def auth(request): data = request.get(‘QUERY_STRING‘).strip().split("&") username = data[0].split("=")[1] password = data[1].split("=")[1] print(username, password) if username=="alex" and password=="abc123": return [b"login success"] else: return [b"wrong username or password"] def register(request): f = open("register.html", ‘rb‘) data = f.read() f.close() return [data] # urls文件 ---------------------------------- def routers(): URLpattern = [ ("/alex", f1), ("/egon", f2), ("/login", log_in), ("/auth", auth), ("/register", register) ] return URLpattern # bin文件 --------------------------------- from wsgiref.simple_server import make_server from .urls import routers def application(environ, start_response): # 1. 接收請求, 所有的請求信息都保存在environ對象中 path = environ.get("PATH_INFO") # 取出請求的文件路徑名稱 # 2. 向瀏覽器返回響應信息(響應頭信息) start_response(‘200 OK‘, [(‘Content-Type‘, ‘text/html‘)]) url_patterns = routers() # 取出url和函數的鍵值對 # 3. 循環遍歷(url)鍵值對,若匹配則賦值對應的函數 func = None for item in url_patterns: if path == item[0]: func = item[1] break if func: # 4. 調用視圖函數, 返回響應體信息 return func(environ) # 註意,這裏必須return調用函數,否則會報錯! else: return [b"<h1>404</h1>"] # 列表中, 元素是二進制字節 s = make_server("127.0.0.1", 8800, application) s.serve_forever()
Django之請求的生命周期
Django的請求生命周期是指當用戶在瀏覽器上輸入url到用戶看到網頁的這個時間段內,Django程序內部所發生的事情;
具體步驟如下:
- 當用戶在瀏覽器輸入url時, 然後瀏覽器會生成請求頭和請求體發送給服務器;
- url經過wsgi---中間件---最後到達路由映射表, 按順序進行正則匹配,若匹配到,則進入對應的視圖函數或者類(CBV)中;
- 視圖函數根據客戶端的請求,取出數據並渲染到模板中,其中可能涉及ORM操作(增刪改查)或從緩存取出數據, 最終以字符串的形式返回;
CBV模式
工作原理
- 一個url對應一個視圖類
- 用戶提交HTTP請求之後, 經過過wsgi和中間件,最後到URL路由, 再判斷出是走哪個類,接著進入views相關的類, 然後此類調用父類的
dispatch()
method
是get
還是post
方法來執行相應的函數。
Dispatch結合session實現用戶授權訪問
方法1: 直接在類中重載dispaych方法
弊端: 代碼重復使用!
from django.views import View
class LoginView(View):
def get(self, request):
return render(request, ‘login.html‘)
def post(self, request):
request.session[‘user_info‘] = {‘username‘: ‘bob‘, ‘info‘: ‘‘}
return redirect(‘/index.html‘)
class IndexView(View):
def dispatch(self, request, *args, **kwargs):
# 不存在session信息則直接跳轉至登錄界面
if not request.session.get(‘user_info‘, ‘‘):
return redirect(‘/login.html‘)
ret = super(IndexView, self).dispatch(request, *args, **kwargs)
return ret
def get(self, request):
return render(request, ‘index.html‘)
方法2: 使用裝飾器
內置的裝飾器csrf_exempt
是特例,只能裝飾dispatch函數才能起到作用,是的post請求無須通過csrf中間件的驗證
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
def test(func):
"""裝飾器函數"""
def inner(*args, **kwargs):
return func(*args, **kwargs)
return inner
class LoginView(View):
# 方式1,作用於dispatch函數
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
ret = super(LoginView, self).dispatch(request, *args, **kwargs)
print(‘login after‘)
return ret
# 方式2: 裝飾get函數
# @method_decorator()
def get(self, request):
return render(request, ‘login.html‘)
# @method_decorator(csrf_exempt)
def post(self, request):
username = request.POST.get(‘username‘, ‘‘)
password = request.POST.get(‘password‘, ‘‘)
if username and password:
request.session[‘user_info‘] = {‘user‘:username, ‘pwd‘:password}
return redirect(‘/index.html‘)
else:
return render(request, ‘login.html‘)
# @method_decorator(func)
class IndexView(View):
def dispatch(self, request, *args, **kwargs):
if not request.session.get(‘user_info‘):
return redirect(‘/login.html‘)
ret = super(IndexView, self).dispatch(request, *args, **kwargs)
return ret
def get(self, request):
return render(request, ‘index.html‘)
Django框架基本原理1