纯手撸简易版本的Python web框架

纯手撸web框架

  1. socket代码需要我们自己写;
  2. http格式的数据自己处理(只能拿到用户输入的路由);
# web框架可以理解成服务器,也就是B/S架构中的服务端
import socket

server = socket.socket()
# 绑定的参数是元组:IP地址、端口号
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    # 浏览器客户端请求二进制数据,请求数据长度为1024个字节
    data = conn.recv(1024)
    # 将获取的二进制数据解码成字符串
    data = data.decode("utf-8")
    # print(data,type(data))
    # 返回请求的状态信息
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
	
    # 获取路由根目录进行判断
    current_path = data.split(' ')[1]
    if current_path == '/index':
        conn.send(b'welcome to index Page!')
    elif current_path == '/login':
        conn.send(b'welcome to login page!')
    else:
        conn.send(b'<h2>Hello World</h2>')
    conn.close()

在这里插入图片描述

=======================================================================================
                               data的详细数据信息
========================================================================================
GET /login HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

基于wsgiref模块的web服务器的实现

  1. 帮助我们封装了socket代码;
  2. 大字典封装处理了http格式的数据;

web服务网关接口

  • 请求来时,帮助我们自动拆分http格式的数据并封装成非常方便处理的数据格式。
  • 响应走时,帮我们将数据再打包成符合http格式。
from wsgiref.simple_server import make_server

# 业务逻辑的视图函数,封装成views.py
def index(env):
    return 'welcome to index page.'

def login(env):
    return 'welcome to login page.'

def error(env):
    return '404 Not Found!'

# 路由层:urls.py
urls = [
    ('/index',index),
    ('/login',login),
]

def run(env,response):
    '''
    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的所有数据
    '''
    # 由wxgiref模块帮你处理好http格式的数据,封装成了大字典
    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]
            print(url[0])
            # 匹配到一个之后,立刻结束for循环
            break
    # 判断func是否有值
    if func:
        res = func(env)
    else:
        res = error(env)
    # 将字符串转换为二进制数据,返回到路由映射的前端页面
    return [res.encode('utf-8')]

if __name__ == '__main__':
    """
        实时监听127.0.0.1:8080端口地址,如果有客户端发起请求
        则会交给源函数处理,即触发run函数运行
    """
    server = make_server('127.0.0.1',8080,run)
    server.serve_forever()

在这里插入图片描述
根据上述的编写逻辑,将代码解耦封装如下:


start_server.py

from wsgiref.simple_server import make_server
from app.urls import urls
from app.views import *

def run(env,response):
    '''
    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回给浏览器的所有数据
    '''
    # 由wxgiref模块帮你处理好http格式的数据,封装成了大字典
    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]
            print(url[0])
            # 匹配到一个之后,立刻结束for循环
            break
    # 判断func是否有值
    if func:
        res = func(env)
    else:
        res = error(env)
    # 将字符串转换为二进制数据
    return [res.encode('utf-8')]

if __name__ == '__main__':
    """
        实时监听127.0.0.1:8080端口地址,如果有客户端发起请求
        则会交给源函数处理,即触发run函数运行
    """
    server = make_server('127.0.0.1',8080,run)
    server.serve_forever()

urls.py

from app import views
# 路由层:urls.py
urls = [
    ('/index',views.index),
    ('/login',views.login),
]

views.py

# 业务逻辑的视图函数,封装成views.py
def index(env):
    return 'welcome to index page.'

def login(env):
    return 'welcome to login page.'

def error(env):
    return '404 Not Found!'
  • urls.py:路由与视图函数的映射关系;
  • views.py:视图函数(后端业务的处理逻辑);
  • templates文件夹:专门用来存储html文件;

按照功能的不同划分之后,后续添加功能只需要在urls.py书写对应关系后,在views.py书写业务逻辑即可。


动静态网页

  • 静态网页:
    • 页面上的数据是写死的
  • 动态网页:
    • 数据是实时获取的,由视图函数将处理的结果反馈到前端的html页面中
    • 功能需求:
      1. 后端获取当前时间展示到html页面上;
      2. 数据字典是从数据库中获取的展示到html页面上;
  • views.py
import datetime
from jinja2 import Template
# 业务逻辑的视图函数,封装成views.py

def get_time(env):
    current_time = datetime.datetime.now()
    # 如何将后端获取的数据“传递”给前端的html文件?
    # 方式一:读写文件
    with open(r'templates/currentTime.html','r',encoding='utf-8') as f:
        data = f.read()
        # 字符串处理函数渲染前端页面
    current_time = str(current_time)
    data.replace("current_time",current_time)
    print(data)
    # 在后端将html页面处理好之后再返回给前端
    return data

def get_dict(env):
    # 定义一个存储用户信息的字典
    user_dic = {'username':'trainingl','age':21,'hobby':'studying'}
    user_list = [
        {'username':'zhangsan','age':21,'hobby':'studying'},
        {'username':'lisi','age':22,'hobby':'reading'},
        {'username':'wangwu','age':20,'hobby':'sleeping'},
        {'username':'zhangliu','age':23,'hobby':'playing'}
    ]
    with open(r'templates/get_dict.html','r',encoding='utf-8') as f:
        data = f.read()
    # 模版语法是在后端起作用的
    tmp = Template(data)
    res = tmp.render(user=user_dic,users=user_list)
    # 给get_dict.html传递了一个值 页面上通过变量名userInfo就能够拿到user_dict
    return res
  • urls.py
from app import views
# 路由层:urls.py
urls = [
    ('/index',views.index),
    ('/login',views.login),
    ('/get_time',views.get_time),
    ('/get_dict',views.get_dict)
]
  • templates/get_dict.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>字典传值</title>
</head>
<body>
    <h2>模版语法之Jinja2模块</h2>
    {{user}}<br/>
    取值的三种方式:<br/>
    {{user.get('username')}}<br/>
    {{user.age}}<br/>
    {{user['hobby']}}<br/><hr/>
<table border="1px red solid" cellspacing="0" align="center">
    <caption>用户信息表</caption>
    <tr>
        <th>用户名</th>
        <th>年龄</th>
        <th>爱好</th>
    </tr>
    {% for user_item in users%}
    <tr>
            <td>{{ user_item.username}}</td>
            <td>{{ user_item.age}}</td>
            <td>{{ user_item.hobby}}</td>
    </tr>
    {% endfor %}
</table>

</body>
</html>

在这里插入图片描述

小结

自定义简易版本的web框架请求流程(基于wsgiref模块):

  1. 请求来时,解析http格式的数据,封装成大字典envrequest;
  2. 响应走时,给数据打包成符合http格式,再返回给浏览器
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值