引入
纯手撸的web框架
复习 软件开发架构 : c/s b/s
cs client 客户端 -------server 服务端
bs browser 浏览器 -------server 服务端
HTTP协议 : 超文本传输协议 规定了 浏览器 与 服务端之间的数据传输格式
HTTP 四大特性
1 基于 请求响应
2 基于 tcp/ip 协议之上 作用于 应用层
3 无状态 (浏览器 无法保存用户的 状态 后产生了 session 和 cookie)
4 无连接 (请求一次响应一次 之后 立马断开 链接 两者之间没有任何联系)
长连接 websocket
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
http的请求数据格式: 请求首行(标识HTTP协议版本 和 请求方式) 请求头 (一堆的 k,v 键值对) /r/n (这也是一行 重点) 请求体(携带的是一些敏感的信息如 密码 身份证) http响应数据的格式: 响应首行(标识HTTP协议版本 响应状态码) 响应头(一大堆k,v键值对) /r/n (这也是一行 重点) 响应体(返回给浏览器页面的数据 通常响应体都是html界面)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
补充 响应状态码: 用一串简单的数字来表示一些复杂的状态或者提示信息 1XX:服务端已经成功接收了你的数据正在处理 你可以继续提交额外的数据 2XX:服务端成功响应 你想要的数据(请求成功200) 3XX:重定向(当你在访问一个需要登录之后才能访问的页面 你会发现窗口会自动调到登录页面 301 302) 4XX:请求错误(请求资源不存在404,请求不合法不符合内部规定会权限不够403) 5XX:服务器内部错误(500) 补充 请求方式 1.get请求 朝服务端要资源(比如浏览器窗口输入www.baidu.com) 2.post请求 朝服务端提交数据(比如用户登录 提交用户名和密码) URL:统一资源定位符(大白话 就是网址)
HTTP GET请求的格式
HTTP响应的格式:
纯手撸版 web框架
''' 请求首行 请求方式 http版本信息 b'GET / HTTP/1.1\r\n 请求体 k v 键值对 Host: 127.0.0.1:9527\r\n Connection: keep-alive\r\n Cache-Control: max-age=0\r\n ....... \r\n' 请求体 ....... ''' import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('127.0.0.1', 8000)) sock.listen() while True: conn, addr = sock.accept() data = conn.recv(8096) # 给回复的消息加上响应状态行 conn.send(b"HTTP/1.1 200 OK\r\n\r\n") conn.send(b"OK") conn.close()
类型转换的技巧
data = b'hello world' data = str(data,encoding='utf-8') print(data) data = bytes(data,encoding='utf-8') print(data)
通过 分割 来过去 用户输入的路径 后缀
data = conn.recv(1024) data = str(data,encoding='utf-8') # 获取get提交数据的后缀 # print(data) current_path = data.split('\r\n')[0].split(' ')[1] print(current_path)
因为 写 socket 太麻烦 所以 有的模块就帮我们封装了 wsgiref模块
# 导入模块 simple 简单的 from wsgiref.simple_server import make_server def run(env , response): # env 信封 是请求相关的 # response 响应 是响应相关的 print(env) # 他是一个大字典 response('200 OK', []) current_path = env.get('PATH_INFO') # 获取 后缀 if current_path == 'login': return [b'login'] return [b'he llo baby'] # 只要有客户端连接 就会触发run方法 if __name__ == '__main__': server = make_server('127.0.0.1',8080,run) # 实时监测127.0.0.1 8080地址 一旦有客户端连接 会自动 加括号调用 run方法 # flask伏笔 flask run是一个 类 自动加括号 实例化对象! # host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
不同的后缀就应该有不同的功能 但是 功能如果太多 我们就需要一次一次的判断 很麻烦 我们就可以写一个 字典套 元组 元祖里面放 功能后缀和 函数 使用 for 循环来判断在不在里面 然后执行函数
func = None for url in urls: # 判断当前url在不在元组内 if url[0] == current_path: # 只要匹配上了 就把url后缀对应的函数名赋值给func func = url[1] # 一旦匹配上 应该立刻退出for循环 节省资源 break # 对变量func做判断 就怕他匹配不上! if func: res = func(env)
else: res = errors(env) return [res.encode('utf-8')] 处理之后 每一个函数就不需要编码了
基于wsgiref模块及拆分成不同的文件之后
加一个功能只需要在两个地方修改代码即可
1.urls.py 路由与视图函数的对应关系 >>> urls = [('/index',index),]
2.views.py 视图函数
动静态网页
静态网页 数据是写死的,万年不变 动态网页 数据不是写死的 是动态获取到的 比如: 1.后端实时获取当前时间"传递"给前端页面展示 2.后端从数据库获取数据"传递"给前端页面展示 传递给前端页面 >>> 页面渲染
templates里面写 html文件
推导: 读取文件 然后 使用replace 替换 其中的符号 然后保存 返回客户端
但是 我现在想把一个字典放在 html里面 可以通过 字典取值 我们就需要 jinja2模块
jinja2 pip3 install jinja2 由于flask框架是依赖于jinja2的 所以下载flask框架也会自带jinja2模块 模板的渲染 包含了 模板语法 模板--- html文件 模板语法(贴近python语法) 前端也能够使用后端的一些语法 操作后端传入的数据
{{}} {%%} <p>{{data}}</p> <p>{{data['username']}}</p> <p>{{data.password}}</p> <p>{{data.get('hobby')}}</p> {%for user_dict in user_list%} <tr> <td>{{user_dict.id}}</td> <td>{{user_dict.name}}</td> <td>{{user_dict.password}}</td> </tr> {%endfor%}
from jinja2 import Template def get_user(env): user_dict = {'username':'jason','password':'123','hobby':['read','game','running']} with open(r'templates/03 get_user.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(data = user_dict) # 将user_dict传递给前端页面 前端页面通过变量名data就能够获取到该字典 return res
总结
1.纯手撸web框架
1.手动书写socket代码
2.手动处理http数据
2.基于wsgiref模块帮助我们处理scoket以及http数据
wsgiref模块
1.请求来的时候 解析http数据 帮你打包成一个字典传输给你 便于你操作各项数据
2.响应走的时候 自动帮你把数据再打包成符合http协议格式的样子 再返回给前端
3.封装路由与视图函数对应关系 以及视图函数文件 网站用到的所有的html文件全部放在了templates文件夹下
1.urls.py 路由与视图函数对应关系
2.views.py 视图函数(视图函数不单单指函数 也可以是类)
3.templates 模板文件夹
4.基于jinja2实现模板的渲染
模板的渲染
后端生成好数据 通过某种方式传递给前端页面使用(前端页面可以基于模板语法更加快捷简便使用后端传过来的数据)