Web框架前戏
Web框架本质
web框架本质上可以看成是一个功能强大的socket服务端,用户的浏览器可以看成是拥有可视化界面的socket客户端。两者通过网络请求实现数据交互,学者们也可以从架构层面上先简单的将Web框架看做是对前端、数据库的全方位整合
纯手撸web框架
前面的课程我们已经学习了网络编程并掌握了socket套接字编程,接下来我们就可以自己编写出一个简易的web框架
1.搭建socket服务端
import socket server = socket.socket() server.bind(('127.0.0.1', 8082)) server.listen(5) while True: sock, addr = server.accept() data = sock.recv(1024) # 此处一会儿需要按照步骤2、3做修改 sock.send(b'hello jasonNB')
2.浏览器发送请求
# 服务端响应的数据需要符合HTTP响应格式 sock.send(b'HTTP1.1 200 OK\r\n\r\nhello jasonNB')
3.路由对应响应
# 将客户端请求相关数据先转成字符串 data_str = data.decode('utf8') # 研究发现可以采用字符串切割获取路由 current_path = data_str.split(' ')[1] # 根据后缀的不同返回不同的内容 if current_path == '/login': sock.send(b'hello jason login!!!') elif current_path == '/register': sock.send(b'hello jason register') else: sock.send(b'404 jason error')
总结
""" 纯手撸框架缺陷: 1.socket代码过于重复(每次搭建服务端都需要反复造轮子) 2.针对HTTP请求数据没有完善的处理方式(目前只能定向切割) """
from wsgiref import simple_server def run(request, response): """ :param request: 请求相关的数据 :param response: 响应相关的数据 :return: 返回给客户端的展示数据 """ response('200 OK', []) # 固定编写 无需掌握
return [b'hello jason'] if __name__ == '__main__': server = simple_server.make_server('127.0.0.1', 8080, run) '''监听本机8080端口 一旦有请求访问 自动触发run方法的执行''' server.serve_forever() # 模块封装了socket代码并将请求数据处理成诸多k:v键值对
2.路由对应响应
# run函数体中添加下列代码 current_path = request.get("PATH_INFO") if current_path == '/login': return [b'hello login html'] elif current_path == '/register': return [b'hello register html'] return [b'404 error']
3.路由拆分流程
1.当有很多路由和响应的情况下不可能无限制编写if判断语句,应该设置对应关系并动态调用
def register(request): return 'register' def login(request): return 'login' def error(request): with open(r'templates/error.html', 'r', encoding='utf8') as f: return f.read() urls = ( ('/login',login), ('/register',register) ) def run(request, response): func_name = None for url_tuple in urls: if current_path == url_tuple[0]: # 先获取对应的函数名 func_name = url_tuple[1] # 一旦匹配上了 后续的对应关系就无需在循环比对了 break # for循环运行完毕之后 func_name也有可能是None if func_name: res = func_name(request) else: res = error(request) # 顺手将request也传给函数 便于后续数据的获取 return [res.encode('utf8')]
2.根据功能的不同拆分成不同的py文件
-views.py
--存储路由与函数对应关系
""" 讲师:JasonJi 外号:鸡哥 邮箱:18817628568@163.com 微信:15618087189、18817628568(备注来源) """ # 功能函数 def register(request): return 'register' def login(request): return 'login' def index(request): return 'index' def error(request): with open(r'templates/error.html', 'r', encoding='utf8') as f: return f.read()
-urls.py
--存储函数
""" 讲师:JasonJi 外号:鸡哥 邮箱:18817628568@163.com 微信:15618087189、18817628568(备注来源) """ from views import * # 后缀匹配 urls = ( ('/register', register), ('/login', login), ('/index', index), )
-server.py
--存储启动及分配代码
""" 讲师:JasonJi 外号:鸡哥 邮箱:18817628568@163.com 微信:15618087189、18817628568(备注来源) """ from wsgiref import simple_server from urls import urls from views import error def run(request, response): response('200 OK', []) current_path = request.get("PATH_INFO") func_name = None for url_tuple in urls: # ('/register', register) if current_path == url_tuple[0]: func_name = url_tuple[1] break if func_name: res = func_name(request) else: res = error(request) return [res.encode('utf8')] if __name__ == '__main__': server = simple_server.make_server('127.0.0.1', 8080, run) server.serve_forever()
总结:拆分后好处在于要想新增一个功能,只需要在views.py中编写函数,urls.py添加对应关系即可
3.模板文件与静态文件
-templates文件夹
--存储html文件
-static文件夹
--存储html页面所需静态资源(后续详细讲解或自行百度)
Jinja2模板语法
1.页面展示当前时间
def get_time(request): # 1.获取当前时间 import time c_time = time.strftime('%Y-%m-%d %X') # 2.读取html文件 with open(r'templates/get_time.html','r',encoding='utf8') as f: data = f.read() # 3.思考:如何给字符串添加一些额外的字符串数据>>>:字符串替换 new_data = data.replace('random_str',c_time) return new_data
<h1>展示后端获取的时间数据</h1> <span>random_str</span>
2.jinja2模板语法
第三方模块需要先下载后使用
pip3 install jinja2
功能阐述:支持将数据传递到html页面并提供近似于后端的处理方式简单快捷的操作数据
-views.py
from jinja2 import Template def get_dict(request): user_dict = {'name': 'jason', 'pwd': 123, 'hobby': 'read'} new_list = [11, 22, 33, 44, 55, 66] with open(r'templates/get_dict.html', 'r', encoding='utf8') as f: data = f.read() temp_obj = Template(data) res = temp_obj.render({'user':user_dict,'new_list':new_list}) return res
-templates
--get_dict.html
<h1>字典数据展示</h1> <p>{{ user }}</p> <p>{{ user.name }}</p> <p>{{ user['pwd'] }}</p> <p>{{ user.get('hobby') }}</p> <h1>列表数据展示</h1> <p> {% for i in new_list%} <span>元素:{{ i }}</span> {% endfor %} </p>
练习:获取数据库数据并展示到浏览器页面上
框架请求流程
主要关键字
urls.py 后缀与函数名对应关系 ('/index',register) 后缀专业名词称之为'路由' 函数名专业名词称之为'视图函数' urls.py专业名词称之为'路由层' views.py 专门编写业务逻辑代码 可以是函数 也可以是类 函数专业名词称之为'视图函数' 类专业名词称之为'视图类' views.py专业名词称之为'视图层' templates文件夹 专门存储html文件 html文件专业名词称之为'模板文件' templates文件夹专业名词称之为'模板层' static文件夹 专门存储静态文件资源 页面所需css文件、js文件、图片文件、第三方文件可统称为'静态资源'