1.web框架概念
web框架可以理解为是基于互联网的web服务端(socket服务端)
2.步骤
- socket服务端代码
- HTTP协议
- 根据网址后缀的不同请求不同的内容
- 请求方式
(1)GET:朝服务端索要数据
(2)POST:朝服务端提交数据- 从请求数据格式中筛选出用户输入的网址后缀
target_url = data.decode('utf8').split(' ')[1]
- 1
- 代码的缺陷:
(1)socket代码重复编写造轮子
(2)针对请求数据格式的处理复杂且重复
(3)针对不同网址后缀的匹配方式过于简单
3.未优化代码展示
import socket server = socket.socket() # TCP协议 server.bind(('127.0.0.1', 8080)) # IP协议 PORT协议 server.listen(5) # 连接池 while True: sock, address = server.accept() data = sock.recv(1024) sock.send(b'HTTP/1.1 200 OK\r\n\r\n') # print(data.decode('utf8')) # 从字符串中截取出需要的内容 target_url = data.decode('utf8').split(' ')[1] # / /index /login /reg /xxx if target_url == '/index': sock.send(b'index view') # with open(r'my html.html','rb') as f: # sock.send(f.read()) elif target_url == '/login': sock.send(b'login view') elif target_url == '/reg': sock.send(b'reg view') else: sock.send(b'404 error')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
wsgiref内置模块:
wsgiref内部封装了socket代码和对请求数据的处理。from wsgiref.simple_server import make_server def run(request, response): """ :param request: 请求数据 :param response: 响应数据 :return: 返回给客户端的数据 """ print(request) # 自动将请求数据全部处理成字典k:v键值对形式 response('200 OK', []) # 固定代码 无需掌握 return [b'hello big baby'] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用 server.serve_forever() # 永久启动
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- wsgiref模块解决了两个问题:
(1)socket代码重复编写造轮子
(2)针对请求数据格式的处理复杂且重复- 思考如何再次实现根据不同的网址后缀返回不同的内容(函数化)
先从大字典中查找出记录网址后缀的键值对。
(1)不推荐使用连续的多个if判断
(2)针对面条版的代码首先应该考虑封装成函数def index(request): return 'index' def login(request): return 'login' def register(request): return 'register' def error(request): return '404 error' urls = ( ('/index', index), ('/login', login), ('/register', register), )
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 根据py文件中功能的不同划分到不同的py文件(模块化)
py文件 功能 urls.py 对应关系 views.py 功能函数 start.py 启动文件 templates文件夹 存储html
封装之后的最终代码启动文件 (start.py ): from wsgiref.simple_server import make_server from urls import urls from views import * def run(request, response): response('200 OK', []) target_path = request.get('PATH_INFO') # /login func_name = None for url_tuple in urls: # ('/index',index) ('/login',login) if url_tuple[0] == target_path: func_name = url_tuple[1] # 先存储匹配到的函数名 break # 一旦匹配到了内容立刻结束for循环 # for循环结束之后还需要判断func_name是不是为None(有可能存在没有匹配上) 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的请求都会给第三个参数加括号调用 server.serve_forever() # 永久启动
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
功能函数(views.py ) def index(request): return 'index' def login(request): return 'login' def register(request): return 'register' def error(request): return 'error'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
对应关系(urls.py) `from views import * urls = ( ('/index',index), ('/login',login), ('/register',register), ) ``
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
1.动态页面
页面上的数据不是全部写死的,有些是动态获取(后端传入)
2.静态网页
页面上的数据直接写死的,要想改变只能修改源码。
3.实际需求
后端代码获取当前时间,然后让前端页面展示:
(1)字符串替换def get_time(request): import time ctime = time.strftime('%Y-%m-%d %X') with open(r'html_get_time.html','r',encoding='utf8')as f: data = f.read() # 如何将时间嵌入html内部,之后再返回给前端浏览器(字符串的替换) data = data.replace('lalala',ctime) return data
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
(2)将字典数据传递给html页面并且想要在页面上操作字典数据;
def get_dict(request): user_dict = {'name':'jason','pwd':123,'hobby':['read','run','music']} with open(r'html_get_dict.html','r',encoding='utf8')as f: data = f.read() # 如何将时间嵌入html内部,之后再返回给前端浏览器(字符串的替换) data = data.replace('hahaha',str(user_dict)) return data
- 1
- 2
- 3
- 4
- 5
- 6
- 7
考虑到问题:我们无法自己实现在html页面上使用类似于后端的语法操作数据。所以引出jinja2模块。
1.jinjia2说明
jinja2能够让我们在html文件内使用类似于后端的语法来操作各种数据类型。
2.jinja2下载pip3 install jinja2
- 1
3.举个栗子——字典实现页面展示
views.py:from jinja2 import Template def get_dict(request): user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']} with open(r'templates/myhtml04.html','r',encoding='utf8') as f: data = f.read() temp = Template(data) res = temp.render(data=user_dict) # 将字典传递给html页面 页面上通过>data即可获取(data仅仅是一个变量名) return res
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
start.pyfrom wsgiref.simple_server import make_server from urls import urls from views import * def run(request, response): response('200 OK', []) target_path = request.get('PATH_INFO') # /login func_name = None for url_tuple in urls: # ('/index',index) ('/login',login) if url_tuple[0] == target_path: func_name = url_tuple[1] # 先存储匹配到的函数名 break # 一旦匹配到了内容立刻结束for循环 # for循环结束之后还需要判断func_name是不是为None(有可能存在没有匹配上) 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的请求都会给第三个参数加括号调用 server.serve_forever() # 永久启动
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
urls.pyfrom views import * urls = ( ('/get_dict',get_dict), )
- 1
- 2
- 3
- 4
html_get_dict_htmlDOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Titletitle> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js">script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">