1. 程式人生 > 其它 >web框架 wsgiref模組優化 jinja2模組 前後端資料庫聯動

web框架 wsgiref模組優化 jinja2模組 前後端資料庫聯動

手寫web框架

1.web框架的本質
連線前端與資料庫的中間介質 就是服務端
socket服務端
2.手寫的web框架
編寫socket服務端程式碼
瀏覽器訪問響應無效>>>: 因為資料格式不一樣, HTTP協議(規定了瀏覽器與服務端之間資料互動的格式)
根據網址的路由不同獲取不同的頁面內容
獲取到使用者輸入的路由>>>: 檢視請求資料內 找到規則獲取路由
"請求首行 GET /login HTTP/1.1 找到規則 處理請求資料獲取網址路由"


import socket

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

while True:
    sock , address = server.accept() # 等待連線
    date = sock.recv(1024) # 接收資訊
    sock.send(b'HTTP/1.1 200 ok\r\n\r\n')
    date_str = date.decode('utf8')  # 請求頭 decode解碼 獲取字串
    target_url = date_str.split(' ')[1]  # 切割獲取 路由
    if target_url =='/index':
        with open(r'index.html','rb')as f:  # 可以傳送一個頁面過去
            sock.send(f.read())
    elif target_url == '/login':
        sock.send(b'hellow login')
    else:
        sock.send(b'hellow baby')
        
   問題:
"""
1.sock的程式碼 重複太多
2. 針對請求資料的處理過於繁瑣
3. 路由匹配邏輯過於 低端
"""

基於wsgiref模組

wsgiref是自帶的內建模組, 很多web框架底層都使用到的模組。

功能: 1.封裝了socket程式碼 2.處理了請求資料

from wsgiref.simple_server import make_server

def run(request,response):
    """
    :param request:   請求相關資料
    :param response: 響應相關資料
    :return:  返回給客戶端的真實資料
    """
    response('200 ok', [])  # 固定格式
    # print(request)   # (字典形式的資料)
    path_info = request.get('PATH_INFO')
    if path_info =='/index':
        return [b'hello index']
    elif path_info =='/admin':
        return [b'hello admin']
    return [b'hello baby!']

if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run) # 實施監聽127.0,0,1:8080的請求,一旦有請求自動給run加括號並呼叫
    server.serve_forever()  # 啟動伺服器
    
優點:
1.固定的程式碼啟動服務端
2.檢視處理之後的request 發現是 以 大字典的形式的資料
3.研究大字典鍵值對找到 含有路由的鍵值對>>> get 方法獲取路由
4. 發現 還是要進行if判斷 思考解決方法

優化後代碼

  1. 解決 路由獲取後的 判斷問題

  2. 思考路由匹配成功後 執行程式碼可能會很多也可能會很少
    2.1 將if分支的程式碼封裝成多個函式 (views.py)

    ​ 2.2 建立函式與路由之間的對應關係 (urls.py)

    ​ 2.3 獲取路由後進行迴圈匹配 自動執行該路由對應函式

    ​ 2.4 後續 新增功能只需要新增函式再進行新增對應關係

  3. 為了使函式體程式碼中業務邏輯有更多的資料可用

​ 3.1 把request 大字典當做實參 傳給函式

"""根據不同的功能拆分成不同的py檔案
	views.py		儲存核心業務邏輯(功能函式)
 	urls.py			儲存網址字尾與函式名對應關係
 	templates目錄	   儲存html頁面檔案""" 

views.py

def index(request):
    with open(r'templates/index.html', 'r',encoding='utf8') as f:
        return f.read()
"html檔案存放與  templates目錄"
def login(request):
    return 'hello login'
def error(request):
    return '404'

urls.py

from views import *

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

啟動檔案

from wsgiref.simple_server import make_server

from urls import urls
from views import *

def run(request,response):
    """
    :param request:   請求相關資料
    :param response: 響應相關資料
    :return:  返回給客戶端的真實資料
    """
    response('200 ok', [])  # 固定格式
    path_info = request.get('PATH_INFO')
    func_name= None  # 定義一個用於儲存函式名的變數
    for url_type in urls:
        if path_info == url_type[0]:
            func_name = url_type[1]
            break  # 匹配到了就不用接著匹配了
    if func_name:   # 判斷如果有值+()呼叫
        res = func_name(request) # 接收函式的返回值
    else:
        res = error(request)
    return [res.encode('utf8')]

if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run) # 實施監聽127.0,0,1:8080的請求,一旦有請求自動給run加括號並呼叫
    server.serve_forever()  # 啟動伺服器

動靜態網頁

1.動態網頁
頁面資料來源於後端

def get_time(request):
    import time
    ctime = time.strftime('%Y-%m-%d %X')  # 過去當前時間
    with open(r'templates/gettime.html','r',encoding='utf8') as f:
        date= f.read()  # 獲取html 裡的資料 字串格式
    res = date.replace('asd',ctime) # 利用替 換把我們提前設定好需要放時間的地方的字串替換成時間
    return res
    
   
 urls = [
    ('/index',index),
    ('/login',login),
    ('/home',get_time)
]

啟動檔案還是上面優化後的就不展示了


  • 如果想要把字典 傳給 頁面 並可以通過字典的操作方式獲取字典內的資料,必須要使用模板語法>>>:jinja2 模組

2.靜態網頁
頁面資料直接在html裡寫死

jinja2模組

  • 將字典資料傳輸到頁面並還可以用後端的操作獲取到字典的資料進行展示
def get_dict(request):
    user_dict = {'name':'李阿雞','age':28,'hobby':'花姑娘'}
    with open(r'templates/get_dict.html' ,'r',encoding='utf8') as f:
        data=f.read()
    temp_obj = Template(data)  # 把頁面資料交給jinjia2模板處理
    res=temp_obj.render({'d1':user_dict})   # 給頁面傳一個變數名是d1的字典
    return res

頁面內資料:
<p>資料展示</p>
<p>{{d1}}</p>
<p>{{d1.name}}</p>
<p>{{d1['age']}}</p>
<p>{{d1.get('hobby')}}</p>

前端,後端,資料庫

前端瀏覽器訪問/table 後端連線資料庫查詢userinfo表中所有的資料 傳遞到get_table頁面 設定好標籤樣式 再發送給瀏覽器展示

前端

<div class="container">
     <div class="row">
        <h1 class="text-center">資料展示</h1>
          <div class="col-md-8 col-md-offset-2">
            <table class="table table-hover table-striped">
                  <thead>
                            <tr>
                              <th>ID</th>
                              <th>Name</th>
                              <th>Age</th>
                            </tr>
                 </thead>
                        <tbody>
                              {%for user_dict in user_list %}  、
                              <tr>
                                <td>{{user_dict.id}}</td>
                                <td>{{user_dict.name}}</td>
                                <td>{{user_dict.age}}</td>
                              </tr>
                              {% endfor %}
      </tbody>
    </table>
    </div>
  </div>
</div>

後端

from jinja2 import Template
import pymysql
def get_table(request):
    conn=pymysql.connect(
        user='root',
        password='321',
        host='127.0.0.1',
        port=3306,
        database='djiango01',
        charset='utf8',
        autocommit=True
           )
    curses = conn.cursor(cursor=pymysql.cursors.DictCursor) # 以字典形式傳
    sql = 'select * from userinfo;' # 編寫sql語句
    curses.execute(sql)  # 傳送語句
    user_data = curses.fetchall() #  接收查詢後所有資料[{},{}]
    print(user_data)
    with open(r'templates/get_table.html','r',encoding='utf8') as f:
        data= f.read()
    temp_obj= Template(data)  # 把頁面資料交給jinjia2模板處理
    res = temp_obj.render({'user_list':user_data})  # 給頁面傳一個變數名是user_list的字典
    return res

關係層:
from views import *

urls = [
    ('/index',index),
    ('/login',login),
    ('/home',get_time),
    ('/dict',get_dict),
    ('/table',get_table)
]

資料庫

建立一個庫,接著建立一個userinfo表儲存使用者資料,錄入使用者資料,先把資料準備好

create database day01;
create table userinfo(id int primary key auto_increment,name varchar(32),age int);
insert into userinfo(name,age) values('李阿雞',18),('jason',27),('牛小妹',16),('tank',22);
===============================
+----+-----------+------+
| id | name      | age  |
+----+-----------+------+
|  1 | 李阿雞    |   18 |
|  2 | jason     |   27 |
|  3 | 牛小妹    |   16 |
|  4 | tank      |   22 |
+----+-----------+------+
===============================
delete from userinfo where id=2;