前戏篇:Web框架推导

Web框架本质

web框架本质上可以看成是一个功能强大的socket服务端,用户的浏览器可以看成是拥有可视化界面的socket客户端。两者通过网络请求实现数据交互,学者们也可以从架构层面上先简单的将Web框架看做是对前端、数据库的全方位整合

 

纯手工撸web框架

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)
    print(data)
    
    # 服务端响应的数据需要符合HTTP响应格式
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    # 将客户端请求相关数据转成字符串
    data_str = data.decode('utf-8')
    # 研究发现可以采用字符串切片
    current_path = data_str.split(' ')[1]
    # 根据后缀的不同返回不同的内容
    if current_path == '/index':
        conn.send(b'hello index')
    elif current_path == '/login':
        conn.send(b'hello login')
    else:
        with open(r'ershou.html','rb') as f:
            conn.send(f.read())
    conn.close()

基于wsgiref模块搭建web框架

基础代码

from wsgiref.simple_server import make_server
def run(env,response):  # 这里定义什么函数名都可以
    """
    :param env: 请求相关的所有数据,以字典的形式呈现
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的数据
    """
    print(env)
    response('200 OK', [])  # 响应首行 响应头(固定编写无需掌握)
    # 从env中取
    current_path = env.get('PATH_INFO')
    if current_path == '/index':
        return [b'index']
    elif current_path == '/login':
        return [b'login']
    return [b'404 error']

if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run)
    '''会实时监听127.0.0.1:8080地址 只要有客户端来了
    都会交给run函数处理(加括号触发run函数的运行)'''
    server.serve_forever()  # 启动服务端

升级代码

from wsgiref.simple_server import make_server

def index():
    return 'index'
def login():
    return 'login'
def error():
    return '404 error'

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

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()
    else:
        res = error()
    return [res.encode('utf-8')]

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

路由拆分协议流程

-views.py(存储视图函数)

# 存储视图函数(存放后端业务逻辑)
def index():
    return 'index'
def login():
    return 'login'
def error():
    return '404 error'

# 动态网页设计
# 获取进入网站的时间
import datetime
def get_time():
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
    # 如何将后端获取到的数据"传递"给html文件
    with open(r'templates/01 get_time.html', 'r', encoding='utf-8') as f:
        data = f.read()
    data = data.replace('shijianbiao',current_time)  # 在后端html页面处理好之后再返回前端
    return data

# 将一个字典传递给html文件,并且可以在html文件上方便快捷的操作字典数据
from jinja2 import Template
def get_dict():
    user_dic = {'username':'jiang','age':110,'gender':'male','hobby':'sleep'}
    with open(r'templates/02 get_dict.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user=user_dic)
    # 给get_dict.html传递了一个值 页面上通过变量名user就能够拿到user_dict
    return res

import pymysql
def get_user():
    # 去数据库中获取数据 传递给html页面 借助于模版语法 发送给浏览器
    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        password = 'root',
        db='wsgiref01',
        charset = 'utf8',
        autocommit = True
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from user_info'
    affect_rows = cursor.execute(sql)
    data_list = cursor.fetchall()  # [{},{},{}]
    # 将获取到的数据传递给html文件
    with open(r'templates/get_data.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user_list=data_list)
    # 给get_dict.html传递了一个值 页面上通过变量名user就能够拿到user_dict
    return res

if __name__ == '__main__':
    get_user(111)
views.py

-urls.py(存储路由与视图函数的对应关系)

# 存储路由与视图函数的对应关系
from views import *
urls = [
    ('/index',index),
    ('/login',login),
    ('/get_time',get_time),
    ('/get_dict',get_dict),
]
urls.py

-server.py(存储启动及分配diamagnetic)

# 存储启动及分配代码
from wsgiref.simple_server import make_server
from views import *
from urls import urls

def run(env, response):
    print(env)
    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()
    else:
        res = error()

    return [res.encode('utf-8')]

if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()  # 启动服务端
server.py

-templates文件夹(模板文件  存储html文件)

# 存储html文件

mytime.html
<body>
<h1>我真的是一个html文件</h1>
datetime
</body>

get_dict.html
<body>
<h1>我是一个页面</h1>
{{ user }}
{{ user.get('username')}}
{{ user.age }}
{{ user['hobby'] }}
</body>

get_data.html
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">用户数据</h1>
            <table class="table table-hover table-striped">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>username</th>
                        <th>password</th>
                        <th>hobby</th>
                    </tr>
                </thead>
                <tbody>
<!--                    [{},{},{},{},{}]-->
                    {% for user_dict in user_list %}
                        <tr>
                            <td>{{ user_dict.id}}</td>
                            <td>{{ user_dict.username}}</td>
                            <td>{{ user_dict.password}}</td>
                            <td>{{ user_dict.hobby}}</td>
                        </tr>
                    {% endfor%}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
View Code

-static文件夹(静态文件  存储html页面所需静态资源)

模板语法之jinja2模块

# 模板语法可以将后端的内容传递给HTML页面,实现前端数据的动态展现
第三方模块需要先下载再使用
pip3 install jinja2
"""模版语法是在后端起作用的"""

# 模版语法(非常贴近python语法)
{{ user }}
{{ user.get('username')}}
{{ user.age }}
{{ user['hobby'] }}
{
% for user_dict in user_list %} <tr> <td>{{ user_dict.id}}</td> <td>{{ user_dict.username}}</td> <td>{{ user_dict.password}}</td> <td>{{ user_dict.hobby}}</td> </tr> {% endfor%}

web框架请求流程图

"""
wsgiref模块
    1、请求来的时候解析http格式的数据 封装成大字典
    2、响应走的时候给数据打包成符合http格式 再返回给浏览器
"""

主要关键字

urls.py
    后缀与函数名对应关系
  ('/index',register)
      后缀专业名词称之为'路由'
        函数名专业名词称之为'视图函数'
        urls.py专业名词称之为'路由层'

views.py
    专门编写业务逻辑代码
      可以是函数 也可以是类
        函数专业名词称之为'视图函数'
        类专业名词称之为'视图类'
        views.py专业名词称之为'视图层'

templates文件夹
    专门存储html文件
      html文件专业名词称之为'模板文件'
        templates文件夹专业名词称之为'模板层'
 
static文件夹
    专门存储静态文件资源
      页面所需css文件、js文件、图片文件、第三方文件可统称为'静态资源'
View Code
posted @ 2023-02-19 17:00  猿小姜  阅读(17)  评论(0编辑  收藏  举报