框架推導過程 jinja2 wsgiref 三大主流框架初始

1.純手擼一個簡易版本的web框架
    1.手動處理socket請求
    2.手動處理http數據,獲取用戶訪問的url
    3.根據用戶訪問url的不一樣 響應不一樣的結果
2.wsgiref模塊(web服務端網關接口)
    封裝了socket代碼
    請求來的時候將http數據格式 拆封成一個大字典
    響應走的時候將數據打包成符合http協議要求的數據格式
        啓動
            server = make_server('127.0.0.1',8080,run)
            # 實時監測127.0.0.1:8080地址 一旦有客戶端來鏈接 會自動加括號調用run方法
            server.serve_forever()  # 啓動服務端
3.如何給html頁面傳遞數據 
    1.如何將當前日期渲染到html頁面  >>>  用r模式讀取html文件成字符串 利用字符串的替換
    2.如何將一個字典渲染到html頁面上而且還可以簡單快捷取值操做  
        模板的渲染  
        jinja2模塊
            1.模板的渲染(傳數據)
            2.模板語法(極其貼近python語法)
        
            from  jinja2 import Template
            將文本格式的html數據傳入Template
            render()
        
        模板語法
            {{ data }}
            {% for user in user_list %}
            {% endfor %}
            
            模板語法 只有兩種狀況 
                {{}}:變量相關
                {%%}:邏輯相關

4.對不一樣的功能拆封成不一樣的文件
    templates文件夾(專門放html文件)
    urls.py
    views.py
    
    對於咱們這個建議版本的web框架 若是想要新增一個功能只須要在
    上面兩個文件中各寫一點代碼便可

HTTP協議
    1.四大特性
        1.基於TCP/IP做用於應用層之上的協議
        2.基於請求響應
        3.無狀態
            cookie
            session
            token
        4.無鏈接
            keep-alive
            
            websocket(主要用在聊天室相關功能)
        
    2.請求響應數據格式
        請求首行(請求方式 協議版本)
        請求頭(一堆k:v鍵值對)  就相似於開路先鋒 攜帶了一些服務端能夠提早知道的信息
        
        請求體(發送post請求 攜帶的數據都會放在請求體中)
        
        
        
        響應數據格式同上
    3.響應狀態碼
        1XX
        2XX:200
        3XX:301/302
        4XX:404/403
        5XX:500

 參考:http://www.javashuo.com/article/p-oqghlwbb-db.htmlcss

1、手擼簡單web服務端

#數據類型轉換技巧html

data = b'hello world'
#類型轉換要不就用encode、decode,要不就用下面這種直接乾脆
data = str(data,encoding='utf-8')
data = bytes(data,encoding='utf-8')

咱們通常是使用瀏覽器當作客戶端,而後基於HTTP協議本身寫服務端代碼做爲服務端前端

import socket
server = socket.socket() #不傳參數是Tcp協議
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    data = conn.recv(1024) #接收請求,洪水攻擊會讓這裏一直處於接收狀態
    print(data)
    data = data.decode('utf-8')
    conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello world!')
    #HTTP協議格式發送響應給客戶端,響應首行(協議版本和響應狀態)+響應頭(空\r\n)+(\r\n)+響應體hello world!

    # conn.send(b'hello world!')
    #這裏若是直接發送'hello world!'客戶端會報錯響應無效

    conn.close()
"""
#請求首行
b'GET / HTTP/1.1\r\n
#請求頭
Host: 127.0.0.1:8080\r\n

Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
#這個是瀏覽器的標識,頭裏面沒有用這個就不是瀏覽器,爬蟲反扒措施
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n
Sec-Fetch-Site: none\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n  #這裏是那個空白行
#請求體 由於是ge請求因此這裏請求體爲空
'

b'GET /favicon.ico HTTP/1.1\r\n  #這下面的先不用管
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36\r\n
Accept: image/webp,image/apng,image/*,*/*;q=0.8\r\n
Referer: http://127.0.0.1:8080/\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n'
"""

2、手擼 根據不一樣url作出不一樣響應

上面的代碼已經實現了基本請求響應,那如何根據不一樣的請求做出不一樣的響應呢?

咱們輸入不一樣的url,看看服務器端會返回什麼

#分析請求python

 

 

咱們發現客戶端請求什麼,服務端收到的數據請求首行裏面就會出現什麼內容,那麼咱們能不能把這個數據取出來返回出去呢?

#得到請求內容做出響應mysql

import socket
server = socket.socket() 
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    data = conn.recv(1024)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    #流式協議,合着發和分開發是同樣的,這裏先發,後面發送響應體
    # print(data)
    data = data.decode('utf-8')
    current_path = data.split('\r\n')[0].split(' ')[1]
    # print(current_path)
    if current_path == '/index':
        # conn.send(b'index')
        #既然我能夠發送內容,那麼是否是也能夠根據不一樣請求發送不一樣前端代碼回去呢??
        with open(r'templates\01 純手擼html文件.html', 'rb') as f:
            conn.send(f.read())
    elif current_path == '/login':
        conn.send(b'login')
    else:
        conn.send(b'hello world!')
    conn.close()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<h1>我發送前端頁面了</h1>
</body>
</html>
html文件

#請求頁面成功接收jquery

 

 3、基於wsgiref模塊實現服務端

前面處理 scoket 和 http 的那堆代碼一般是不變的,且與業務邏輯沒什麼關係,若是每一個項目都要寫一遍,那豈不是很麻煩?那封裝成模塊嘛~

不過這個操做已經有人幫咱們作了,而且封裝的更增強大,就是 wsgiref 模塊

3.1 wsgiref幫咱們作了:

1.在請求來的時候,自動解析 HTTP 數據,並打包成一個字典,便於對請求發過來的數據進行操做
2. 發響應以前,自動幫忙把數據打包成符合 HTTP 協議的格式(響應數據格式,不須要再手動寫 conn.send(b'HTTP/1.1 200 OK\r\n\r\n') 了)

 

from wsgiref.simple_server import make_server

def run(env,response):
    # env是請求相關的數據
    # response是響應相關的數據
    print(env)  #發現env就是一個大字典,能夠看到其中有個 PATH_INFO 是咱們要的東西,如'登陸'(還有瀏覽器版本啊,USER-AGENT啊,客戶端系統環境變量啊之類的信息)
    response('200 OK',[])
    current_path = env.get('PATH_INFO')
    # print(current_path)
    if current_path == '/index':
        return [b'index']
    elif current_path == '/login':
        return [b'login']
    else:
        return [b'404 error']

if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run) # 實時監測127.0.0.1:8080地址 一旦有客戶端來鏈接 會自動加括號調用run方法
    server.serve_forever()  # 啓動服務端

#伏筆web

3.2 拆分服務端代碼

服務端代碼、路由配置、視圖函數,照目前的寫法全都冗在一起,後期功能擴展時,這個文件會變得很長,不方便維護,因此選擇把他拆分開來

就是將服務端代碼拆分紅以下三部分:sql

  • server.py 放服務端代碼數據庫

  • urls.py 放路由與視圖函數對應關係django

  • views.py 放視圖函數/類(處理業務邏輯)

views.py

def index(env):
    return 'index'

def login(env):
    return 'login'

urls.py

from views import *

urls = [
    ('/index', index),
    ('/login', login),
]

server.py

from wsgiref.simple_server import make_server  # 導模塊
from urls import urls  # 引入 urls.py 裏的 urls列表(命名的不是很規範)


def run(env, response):
    response('200 OK', [])
    current_path = env.get('PATH_INFO')

    func = None
    for url in urls:
        if current_path == url[0]:
            func = url[1]
            break

    if func:
        res = func(env)
    else:
        res = '404 Not Found.'
    return [res.encode('utf-8')]  # 注意這裏返回的是一個列表(可迭代對象才行),wsgiref 模塊規定的,可能還有其餘的用途吧

if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()

3.3 支持新的請求地址(添加新頁面/新功能)

通過上面的拆分後,後續想要支持其餘 url,只須要在 urls.py 中添加一條對應關係,在 views.py 中把該函數實現,重啓服務器便可訪問

以支持 http://127.0.0.1:8080/new_url 訪問爲例

urls.py

 

from views import *

urls = [
    ('/index', index),
    ('/login', login),
    ('/new_url', new_url),
]

views.py

def index(env):
    return 'index'

def login(env):
    return 'login'

def new_url(env):
    # 這裏能夠寫一堆邏輯代碼
    return 'new_url'

重啓服務器,打開瀏覽器便可訪問 http://127.0.0.1:8080/new_url

擴展性高了不少,且邏輯更清晰了,更不容易弄錯(框架的好處提現,也是爲何脫離了框架不會寫的緣由,這塊代碼寫的太少,不經常使用到,沒了框架又寫不出來)

4、動態靜態網頁--拆分模板文件

 

前面寫了那麼多,都只是一直在返回純文本信息,而咱們通常請求頁面返回的都是瀏覽器渲染好的華麗的頁面,那要怎麼放回華麗的頁面呢?
頁面嘛,就是 HTML + CSS + JS 渲染出來的,因此咱們也能夠把 HTML文件當成數據放在響應體裏直接返回回去
新建一個功能的步驟仍是複習一下

在 urls.py 裏面加一條路由與視圖函數的對應關係
在 views.py 裏面加上那個視圖函數,並寫好內部邏輯代碼
重啓服務器,瀏覽器打開頁面訪問

4.1 返回靜態頁面--案例

這裏我們就接着上面的 new_url 寫,用他來返回 一個網頁

新建一個 templates 文件夾,專門用來放 HTML 文件,便於管理

templates/new_url.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>New URL</h1>
    <h5>Wellcome!</h5>
</body>
</html>

views.py

def index(env):
    return 'index'

def login(env):
    return 'login'

def new_url(env):
    # 讀取並把 new_url 文件返回給客戶端(瀏覽器)
    with open(r'templates/new_url.html', 'rb') as f:
        html_data = f.read()
    return html_data.decode('utf-8')  # 由於 run 函數那裏作了 encode, 而二進制數據沒有 encode這個方法,因此這裏先解碼一下,而後那邊再編碼一下

重啓服務器,使用瀏覽器訪問

 

上面提到了靜態頁面,那什麼是靜態頁面?什麼又是動態頁面呢?

  • 靜態網頁:純html網頁,數據是寫死的,全部同url的請求拿到的數據都是同樣的

  • 動態網頁:後端數據拼接,數據不是寫死的,是動態拼接的,好比:

    ​ 後端實時獲取當前時間「傳遞」(塞)給前端頁面展現

    ​ 後端從數據庫獲取數據「傳遞」給前端頁面展現

4.2 實現返回時間--插值思路(動態頁面)

# 要怎麼在 html 裏插入時間呢?

往 html 裏的插入?那替換好像也能夠達到效果啊?

html_data = f.read() ? 好像 html 被讀出出來了,並且仍是二進制的,二進制能夠 decode 變成字符串,字符串有 replace方法能夠替換字符串,那我隨便在網頁裏寫點內容,而後替換成時間?

 

# templates/get_time.html 編寫展現頁面

put_times_here 用來作佔位符,一下子給他替換成時間

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>北京時間:</h1>
    <h1>put_time_here</h1>
</body>
</html>

urls.py 路由與視圖函數對應關係

from views import *

urls = [
    ('/index', index),
    ('/login', login),
    ('/new_url', new_url),
    ('/get_time', get_time),
]

views.py 實現視圖函數

def index(env):
    return 'index'

def login(env):
    return 'login'

def new_url(env):
    # 讀取並把 new_url 文件返回給客戶端(瀏覽器)
    with open(r'templates/new_url.html', 'rb') as f:
        html_data = f.read()
    return html_data

def get_time(env):
    # 讀取並把 get_time 文件返回給客戶端(瀏覽器)
    with open(r'templates/get_time.html', 'rb') as f:
        html_data = f.read().decode('utf-8')
    import time
    html_data = html_data.replace('put_time_here', time.strftime("%Y-%m-%d %X"))
    return html_data

重啓服務器並打開瀏覽器訪問 http://127.0.0.1:8080/get_time

關鍵思路:至關於佔位符,字符串替換,後期把前端要替換的字符的格式統一規定下,方便閱讀與統一處理,這其實也就是目前的模版語法的雛形

咱們只須要把處理好的字符串(HTML格式的)返回給瀏覽器,待瀏覽器渲染便可有頁面效果

5、利用 jinja2 模塊實現動態頁面

jinja2模塊有着一套 模板語法,能夠幫我更方便地在 html 寫代碼(就想寫後臺代碼同樣),讓前端也可以使用後端的一些語法操做後端傳入的數據

5.1 安裝 jinja2

jinja2 並非 python 解釋器自帶的,因此須要咱們本身安裝(命令行執行,

​ 因爲 flask 框架是依賴於 jinja2 的,所下載 flask 框架也會自帶把 jinja2 模塊裝上pip3 install jinja2)

5.2 初步使用

這裏只是知道有模板語法這麼一個東西可讓咱們很方便的往 html 寫一些變量同樣的東西,並不會講 jinja2 的語法,後續會有的

案例--展現字典信息

urls.py

from views import *

urls = [
    ('/index', index),
    ('/login', login),
    ('/new_url', new_url),
    ('/get_time', get_time),
    ('/show_dic', show_dic),
]

views.py

def index(env):
    return 'index'


def login(env):
    return 'login'


def new_url(env):
    # 讀取並把 new_url 文件返回給客戶端(瀏覽器)
    with open(r'templates/new_url.html', 'rb') as f:
        html_data = f.read()
    return html_data


def get_time(env):
    # 讀取並把 get_time 文件返回給客戶端(瀏覽器)
    with open(r'templates/get_time.html', 'rb') as f:
        html_data = f.read().decode('utf-8')
    import time
    html_data = html_data.replace('put_time_here', time.strftime("%Y-%m-%d %X"))
    return html_data


def show_dic(env):
    user = {
        "username": "jason",
        "age": 18,
    }
    with open(r'templates/show_dic.html', 'rb') as f:
        html_data = f.read()

    # 使用 jinja2 的模板語法來將數據渲染到頁面上(替換佔位符)
    from jinja2 import Template
    tmp = Template(html_data)
    res = tmp.render(dic=user)  # 將字典 user 傳遞給前端頁面,前端頁面經過變量名 dic 就可以獲取到該字典
    return res

templates/show_dic.html 寫頁面

jinja2 給字典擴展了點語法支持({{ dic.username }}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Nice to meet you~ i'm {{ dic.username }} , and i'm {{ dic.age }} years old.</h1>
    <p>username: {{ dic['username']}}</p>
    <p>age: {{ dic.get('age')}}</p>
</body>
</html>

重啓服務器並打開瀏覽器訪問 http://127.0.0.1:8080/show_dic

5.3 爲何說動態?

若是你改變了字典裏的值,那麼請求這個頁面,顯示的數據也會跟着改變(注意這個字典通常都是其餘地方獲取過來的)

模板語法(貼近python語法): 前端也可以使用後端的一些語法操做後端傳入的數據
    {{data.password}}  # jinja2 多給字典作了 點語法支持
    模板語法還有不少,先不考慮
    
    for 循環
    {%for user_dict in user_list%}
        <tr>
            <td>{{user_dict.id}}</td>
            <td>{{user_dict.name}}</td>
            <td>{{user_dict.password}}</td>
        </tr>
    {%endfor%}

6、進階案例--渲染數據庫數據到頁面

6.1 思路

pymsql 從數據庫取數據(指定成 列表套字典 的格式(DictCursor))
後臺 python 代碼處理數據
交由 jinja2 模塊語法渲染到 html 頁面上

數據條數不定怎麼辦?
    有多少條記錄就顯示多少條唄...循環?
    表格格式先寫好,而後循環渲染數據到標籤上(特定語法表示循環)

6.2 數據準備

建立數據庫 django_test_db,而後執行以下 SQL 命令

/*
 Navicat MySQL Data Transfer

 Source Server         : localhost-E
 Source Server Type    : MySQL
 Source Server Version : 50645
 Source Host           : localhost:3306
 Source Schema         : django_test_db

 Target Server Type    : MySQL
 Target Server Version : 50645
 File Encoding         : 65001

 Date: 15/09/2019 00:41:09
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (1, 'jason', '123');
INSERT INTO `user_info` VALUES (2, 'tank', '123');
INSERT INTO `user_info` VALUES (3, 'jerry', '123');
INSERT INTO `user_info` VALUES (4, 'egon', '456');

SET FOREIGN_KEY_CHECKS = 1;
View Code

6.3 配路由與視圖函數

urls.py

from views import *

urls = [
    ('/index', index),
    ('/login', login),
    ('/new_url', new_url),
    ('/get_time', get_time),
    ('/show_dic', show_dic),
    ('/get_users', get_users),
]

views.py

def index(env):
    return 'index'


def login(env):
    return 'login'


def new_url(env):
    # 讀取並把 new_url 文件返回給客戶端(瀏覽器)
    with open(r'templates/new_url.html', 'rb') as f:
        html_data = f.read()
    return html_data


def get_time(env):
    # 讀取並把 get_time 文件返回給客戶端(瀏覽器)
    with open(r'templates/get_time.html', 'rb') as f:
        html_data = f.read().decode('utf-8')
    import time
    html_data = html_data.replace('put_time_here', time.strftime("%Y-%m-%d %X"))
    return html_data


def show_dic(env):
    user = {
        "username": "jason",
        "age": 18,
    }
    with open(r'templates/show_dic.html', 'rb') as f:
        html_data = f.read()

    # 使用 jinja2 的模板語法來將數據渲染到頁面上(替換佔位符)
    from jinja2 import Template
    tmp = Template(html_data)
    res = tmp.render(dic=user)  # 將字典 user 傳遞給前端頁面,前端頁面經過變量名 dic 就可以獲取到該字典
    return res


# 先寫個空函數在這裏佔位置,去把 pymysql 查數據的寫了再過來完善
def get_users(env):
    # 從數據庫取到數據
    import op_mysql
    user_list = op_mysql.get_users()

    with open(r'templates/get_users.html', 'r', encoding='utf-8') as f:
        html_data = f.read()

    from jinja2 import Template  # 其實這個引入應該放在頁面最上方去的,但爲了漸進式演示代碼推動過程,就放在這裏了
    tmp = Template(html_data)
    res = tmp.render(user_list=user_list)
    return res

op_mysql.py 若是你的配置不同要本身改過來

import pymysql


def get_cursor():
    server = pymysql.connect(
        # 根據本身電腦上 mysql 的狀況配置這一塊的內容
        host='127.0.0.1',
        port=3306,
        user='root',
        password='000000',
        charset='utf8',  # 千萬注意這裏是 utf8 !
        database='django_test_db',
        autocommit=True
    )
    cursor = server.cursor(pymysql.cursors.DictCursor)
    return cursor


def get_users():
    cursor = get_cursor()  # 鏈接數據庫

    sql = "select * from user_info"  # 把用戶的全部信息查出來(通常不會把密碼放回給前端的,這裏只是爲了作演示)
    affect_rows = cursor.execute(sql)
    user_list = cursor.fetchall()
    return user_list

templates/get_users.html 用戶信息展現頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--  引入jquery bootstrap 文件的 CDN  -->
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">

            <div class="col-md-8 col-md-offset-2">
                <h2 class="text-center">用戶數據展現</h2>
                <table class="table table-hover table-bordered table-striped">
                    <thead>
                    <tr>
                        <th>id</th>
                        <th>username</th>
                        <th>password</th>
                    </tr>
                    </thead>
                    <tbody>
                    <!-- jinja2 的模版語法(for循環) -->
                    {%for user_dict in user_list%}
                    <tr>
                        <td>{{user_dict.id}}</td>
                        <td>{{user_dict.username}}</td>
                        <td>{{user_dict.password}}</td>
                    </tr>
                    {%endfor%}
                    </tbody>
                </table>
            </div>

        </div>
    </div>
</body>
</html>

用瀏覽器訪問 http://127.0.0.1:8080/get_users,重啓服務器,在切回瀏覽器便可看到頁面效果

7、推導流程與小總結

1.純手擼web框架
    1.手動書寫socket代碼,返回‘hello world!’
    2.手動處理http數據,發什麼返回什麼
  3.返回html文件 2.基於wsgiref模塊幫助咱們處理scoket以及http數據(代替上面的步驟) wsgiref模塊 1.請求來的時候 解析http數據幫你打包成一個字典傳輸給你 便於你操做各項數據 2.響應走的時候 自動幫你把數據再打包成符合http協議格式的樣子 再返回給前端 3.封裝路由與視圖函數對應關係 以及視圖函數文件 網站用到的全部的html文件所有放在了templates文件夾下 1.urls.py 路由與視圖函數對應關係 2.views.py 視圖函數 (視圖函數不僅僅指函數 也能夠是類) 3.templates 模板文件夾 4.基於jinja2實現模板的渲染 模板的渲染 後端生成好數據 經過某種方式傳遞給前端頁面使用(前端頁面能夠基於模板語法更加快捷簡便使用後端傳過來的數據)

流程圖

小擴展

在不知道是要 encode 仍是 decode 的時候,能夠用一下方法

數據類型轉換技巧(處理編碼)(數據 + encoding)

# 轉成 bytes 類型
bytes(data, encoding='utf-8')

# 轉成 str 類型
str(data, encoding='utf-8')

8、python三大Web主流框架分析對比

8.1 Django

大而全,自帶的功能特別特別多,就相似於航空母艦

缺點:有時過於笨重(小項目不少用不到)

8.2 Flask

短小精悍,自帶的功能特別少,全都是依賴於第三方組件(模塊)

第三方組件特別多 --> 若是把全部的第三方組件加起來,徹底能夠蓋過django

缺點:比較受限於第三方的開發者(可能有bug等)

8.3 Tornado

天生的異步非阻塞框架,速度特別快,可以抗住高併發

​ 能夠開發遊戲服務器(但開發遊戲,仍是 C 和C++用的多,執行效率更快)

8.4 手擼三大部分在框架中的狀況對比

前面的手擼推導過程,整個框架過程大體能夠分爲如下三部分

A:socket處理請求的接收與響應的發送

B:路由與視圖函數

C:模板語法給動態頁面渲染數據

Django

A:用的別人的 wsgiref 模塊
B:自帶路由與視圖函數文件
C:自帶一套模板語法

Flask

A:用的別人的werkzeug 模塊(基於 wsgiref 封裝的)
B:自帶路由與視圖函數文件
C:用人家的jinja2的模板語法

Tornado

A,B,C全都有本身的實現

相關文章
相關標籤/搜索