1. 程式人生 > >Django框架基本原理1

Django框架基本原理1

patch body code spl 所有 net username register django框架

Django之請求的本質

  1. 本質上django程序就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端;

  2. 在遵循http協議的基礎上兩方進行通訊;

    以django為例: 涉及到底層socket方面(接收和解析瀏覽器的請求信息, 響應頭和響應體的發送都是由django的wsgi模塊完成的,用戶只需要實現路由和視圖函數,模板等代碼部分即可):

  3. 請求頭和請求體以兩個\r\n分隔開, 請求頭的內容也是以\r\n分開, 相應頭和響應體同理;

  4. 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程序內部所發生的事情;
具體步驟如下:

  1. 當用戶在瀏覽器輸入url時, 然後瀏覽器會生成請求頭和請求體發送給服務器;
  1. url經過wsgi---中間件---最後到達路由映射表, 按順序進行正則匹配,若匹配到,則進入對應的視圖函數或者類(CBV)中;
  2. 視圖函數根據客戶端的請求,取出數據並渲染到模板中,其中可能涉及ORM操作(增刪改查)或從緩存取出數據, 最終以字符串的形式返回;

技術分享圖片


CBV模式

工作原理

  1. 一個url對應一個視圖類
  2. 用戶提交HTTP請求之後, 經過過wsgi和中間件,最後到URL路由, 再判斷出是走哪個類,接著進入views相關的類, 然後此類調用父類的dispatch()
    ,dispatch會根據http請求頭裏的methodget還是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