47. web框架

news/2025/1/12 20:05:15/文章来源:https://www.cnblogs.com/hbutmeng/p/18665739

1. web框架本质

web框架本质上可以看成一个功能强大的socket服务端,用户的浏览器可以看成拥有可视化界面的socket客户端

通过网络请求实现数据交互,可简单的将web框架看做是对前端、数据库的全方位整合

2. 手写简易版web框架

服务端

import socketserver = socket.socket()
server.bind(('127.0.0.1', 9009))
server.listen(5)
while True:sock, addr = server.accept()data = sock.recv(1024)data_str = data.decode('utf-8')  # 将客户端请求数据转为字符串print(data_str)  # 打印客户端浏览器的请求数据sock.send(b'HTTP1.1 200 OK\r\n\r\n')  # 服务端响应的数据需要符合HTTP响应格式ask_path = data_str.split(' ')[1]  # 使用空字符串切割,索引为1的元素即浏览器请求的路径if ask_path == '/login':sock.send(b'login exists')elif ask_path == '/register':sock.send(b'register exists')else:sock.send(b'404 Not Found')

当端口之后不带路径时

同时打印的/favicon.ico可以忽略

当端口之后带有路径时

以上简易版web框架的缺点:

(1)服务端socket代码过于重复

(2)HTTP数据请求没有更多的处理方式(只能切割空字符)

(3)无法实现服务端高并发

3. 基于wsgiref模块搭建web框架

服务端

from wsgiref import simple_serverdef run(request, response):""":param request:与请求相关数据:param response: 与响应相关数据:return: 返回给客户端的数据"""# print(request)  # 字典类型的数据(HTTP请求相关)response("200 OK", [])  # 固定格式ask_path = request.get("PATH_INFO")if ask_path == "/":return [b'empty']elif ask_path == "/login":return [b'login exists']else:return [b'404 error']if __name__ == '__main__':server = simple_server.make_server('127.0.0.1', 9000, run)  # 一直监听本机9000端口,一旦有请求访问,自动触发run函数的运行server.serve_forever()

打印部分request请求字典类型的数据

不带路径时

带有路径时

4. wsgiref优化

4.1 优化方案思路

(1)问题

  如果网站很多,就要添加很多个elif

  每个分支下的功能都不相同,可能会有比较复杂的逻辑

(2)函数优化

  将匹配和功能,封装成元组和函数

  新的问题是,所有功能函数放在一个py文件中过于冗余,不便于后期管理维护

(3)模块优化

  根据功能的不同拆分成不同的py文件

    urls.py    对应关系的存储views.py   业务逻辑的编写 

  想要新增功能,只需要在urls.py中添加对应关系,view.py中编写业务逻辑函数

  新的问题是,业务函数代码中,可能会频繁的使用到不同的HTML页面

(4)模板优化

  为了避免文件类型的混乱,单独创建一个文件夹存储所有的HTML文件

templates文件夹        存储项目所需的HTML文件

  新的问题是,项目中的HTML文件,也有可能需要用到css、js、第三方框架文件

(5)静态优化

  HTML所需要的css、js、第三方框文件都是很少改变的文件

  所以可以统一放在某个文件夹下

static文件夹    存储项目所需的“静态文件”

4.2 优化方案实现

[1] 一个py文件

当有很多请求响应的情况下不可能无限制编写if判断语句,应该设置对应关系并动态调用.

from wsgiref import simple_serverdef login():return "login exists"def register():return "register exists"def error():return "error"urls = (("/login", login), ("/register", register))def run(request, response):""":param request:与请求相关数据:param response: 与响应相关数据:return: 返回给客户端的数据"""# print(request)  # 字典类型的数据(HTTP请求相关)response("200 OK", [])  # 固定格式ask_path = request.get("PATH_INFO")func_name = Nonefor url_one in urls:if ask_path == url_one[0]:  # 将请求的路径与已存在的路径进行比对func_name = url_one[1]  # 将路径名作为值赋值给函数名break  # 匹配成功则停止比对if func_name:  # for循环完毕之后,func_name有可能是None,因此要进行判断res = func_name()else:res = error()return [res.encode("utf8")]if __name__ == '__main__':server = simple_server.make_server('127.0.0.1', 9000, run)  # 一直监听本机9000端口,一旦有请求访问,自动触发run函数的运行server.serve_forever()

[2] 根据功能划分模块

(1)views.py   存储功能函数

def login():return "login exists"def register():return "register exists"def error():with open(r"templates/error.html", "r", encoding="utf-8") as f:return f.read()

(2)urls.py   存储对应关系

from views import *urls = (("/login", login), ("/register", register))

(3)server.py  核心代码

from wsgiref import simple_server
from urls import urls
from views import errordef run(request, response):""":param request:与请求相关数据:param response: 与响应相关数据:return: 返回给客户端的数据"""# print(request)  # 字典类型的数据(HTTP请求相关)response("200 OK", [])  # 固定格式ask_path = request.get("PATH_INFO")func_name = Nonefor url_one in urls:if ask_path == url_one[0]:  # 将请求的路径与已存在的路径进行比对func_name = url_one[1]  # 将路径名作为值赋值给函数名break  # 匹配成功则停止比对if func_name:  # for循环完毕之后,func_name有可能是None,因此要进行判断res = func_name()else:res = error()return [res.encode("utf8")]if __name__ == '__main__':server = simple_server.make_server('127.0.0.1', 9001, run)  # 一直监听本机9000端口,一旦有请求访问,自动触发run函数的运行server.serve_forever()

(4)模板文件与静态文件

templates文件夹:存储HTML文件

static文件夹:存储HTML文件所需静态资源(暂时为空)

总结:拆分后如果想要新增一个功能,只需要在views.py中编写函数,urls.py中添加对应关系即可。

5. 动静态网页

5.1 概念

静态网页:数据和布局在编写 HTML 文件时就已经固定下来,不随用户的请求或时间的变化而改变。

 

动态网页:在服务器端运行脚本语言(如 PHP、Python、JavaScript 或 Java 等)来生成和处理数据,然后再将处理后的数据以 HTML 格式发送至浏览器。

eg:1.页面上展示当前时间(后端获取传递给前端页面)

  2.页面上展示数据库数据(后端连接数据库查询数据再传递给页面)

5.2 案例1

需求:页面上展示当前时间

在4.2[2]的基础上,定义一个获取时间的函数,并添加对应关系

views.py

def get_time():c_time = time.strftime("%Y-%m-%d %X")with open(r'templates/get_time.html', 'r', encoding='utf-8') as f:data = f.read()  # 读取出来的数据是整个HTML代码new_data = data.replace('abcdefg', c_time)  # 将整个HTML代码的指定字符串内容替换为时间数据return new_data

urls.py

from views import *urls = (("/login", login), ("/register", register), ("/get_time", get_time))

get_time.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>abcdefg</p>
</body>
</html>

5.3 案例2

需求:将字典传递到页面上,并且在页面上还可以使用字典的操作方法

在4.2[2]的基础上,定义一个获取字典的函数,并添加对应关系

views.py

def get_dict():info = {'name': 'avril', 'pwd': 123, 'hobby': 'sing'}with open(r'templates/get_dict.html', 'r', encoding='utf-8') as f:data = f.read()new_data = data.replace('abcdefg', str(info))  # 将字典转换成了字符串格式return new_data

urls.py

from views import *urls = (("/login", login), ("/register", register), ("/get_time", get_time), ("/get_dict", get_dict))

get_dict.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>abcdefg</p>
</body>
</html>

以上代码将字典以字符串的形式在页面上展示,但是无法使用字典的操作方法

为了解决这个问题,引入了jinja2模块

6. jinja2模块

安装jinja2模块:pip install jinja2

模块功能介绍:在编写前后端不分离项目的时候,使用该模块提供的模板语法简单快速的在HTML页面可以用类似于后端的代码语法操作数据

在4.2[2]与5.3的基础上,对get_dict的py文件与html文件稍作修改

views.py

from jinja2 import Templatedef get_dict():info = {'name': 'avril', 'pwd': 123, 'hobby': 'sing'}with open(r'templates/get_dict.html', 'r', encoding='utf-8') as f:data = f.read()proj = Template(data)res = proj.render({'user_dict': info})  # 给页面传递一个变量名是user_dict,值为info(对应值是字典)的数据return res

get_dict.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>字典数据展示</p><p>{{user_dict}}</p><p>{{user_dict.name}}</p><p>{{user_dict['pwd']}}</p><p>{{user_dict.get('hobby')}}</p>
</body>
</html>

以上HTML代码使用python语法操作数据

7. 框架请求流程

7.1 流程图

7.2 关键字解释

[1] urls.py

urls = (("/login", login), ("/register", register), ("/get_time", get_time))

括号里路径专业名词称之为"路由"

括号里函数名专业名词称之为"视图函数"

urls.py专业名词称之为"路由层"

[2] views.py

def login():
return "login exists"def register():
return "register exists"

该文件用来编写业务逻辑代码,可以是函数、也可以是类

函数称之为"视图函数",类则称之为"视图类"

views.py称之为"视图层"

[3] templates文件夹

用来存储HTML文件

HTML文件称之为"模板文件"

templates文件夹称之为"模板层"

[4] static文件夹

用来存储静态文件资源

页面所需的css文件、js文件、图片、第三方文件可统称为"静态资源"

8. python主流web框架

Django框架官网:https://www.djangoproject.com/
Flask框架官网:https://flask.palletsprojects.com/en/3.0.x/
Fastapi框架官网:https://fastapi.tiangolo.com/
Pyramind框架官网:https://trypyramid.com/
Tornado框架官网:https://www.tornadoweb.org/en/stable/
Sanic框架官网:https://github.com/sanic-org/sanic
Fastapi框架官网:https://fastapi.tiangolo.com/
Aiohttp框架官网:https://docs.aiohttp.org/en/stable/

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/868321.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记一次生产事故:一年的数据被删除了

故事开始快要下班了,心情是这样的。 突然电话响了,一看电话号码是项目甲方负责人的号码菊花一紧,难道出什么问题了,硬着头皮接通了电话。@####@,你们程序怎么回事 ,某个业务的数据界面一条都查询不到了。。。。。我们马上排查一下,看看那什么情况(心理活动:尼玛,尼玛…

【Azure App Service】对App Service中CPU指标数据中系统占用部分(System CPU)的解释

问题描述 在使用Azure App Service服务时,对于它的CPU占比,从App Service Plan级别可以查看整个实例(vm)资源的CPU占比,而如果在具体的一个App Service服务中,则只能查看到当前应用所消耗的CPU时间,如果需要计算它的占比:需要使用公式【 CPU Time / (CPU核数 * 60 )】估算…

2024秋季学期 光学期末复习笔记

累了,懒得写文案了参考资料 [1] 赵凯华, 钟锡华. 光学(重排本)[M]. 北京大学出版社, 2017.10. [2] 崔宏滨, 李永平, 康学亮. 光学(第二版)[M]. 科学出版社, 2015.7. [3] 王安廷. 光学课程PPT[Z]. 中国科学技术大学, 2024. 干涉衍射偏振

Python 基础知识 之 选择(分支)结构 + 模式匹配结构(match)

选择结构按照条件选择执行不同的代码段1. 单分支结构if语法结构执行流程:如果表达式的值为True,就执行语句块,如果表达式的值为False,就跳过语句块,继续执行下面的语句 ⭐注意: ⭐⭐⭐表达式后面的冒号; 缩进,python中通过缩进来控制程序逻辑示例;# 1. 判断是否中奖 n…

中考英语优秀范文-热点话题-传统文化-003 Chinese Tea 中国茶

1 写作要求 第三次法国国际友好交流学校线上论坛拟于下周五举行。本期论坛的主题为“茶文化”,作为论坛特邀嘉宾,请你写一篇文章,向国际友好交流学校介绍中国的特色茶饮和中国茶文化。 内容包括: 1 茶的历史(中国人种茶、饮茶已有4000多年的历史)和种类(绿茶、红茶、乌龙…

Hetao P3804 Cut 题解 [ 蓝 ] [ AC 自动机 ] [ 差分 ]

AC 自动机简单题。Cut:AC 自动机简单题。思路 看见多个模式串以及求前缀,很显然能想到构建一个 AC 自动机。 那么在用 \(T\) 查询时,当前指针的深度就是该位置的最长前缀匹配长度。这个在字典树 insert 的时候就能求出来。 求出每一位的最长前缀后,因为这些部分都不能作为分…

Lec 14 文件系统与设备

Lec 14 文件系统与设备License 本内容版权归上海交通大学并行与分布式系统研究所所有 使用者可以将全部或部分本内容免费用于非商业用途 使用者在使用全部或部分本内容时请注明来源 资料来自上海交通大学并行与分布式系统研究所+材料名字 对于不遵守此声明或者其他违法使用本内…

Java基础学习(七)

Java基础学习(七):异常机制 目录Java基础学习(七):异常机制概念简单分类异常体系结构异常处理机制自定义异常 本文为个人学习记录,内容学习自 狂神说Java概念异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等 异常发生在程序运行期…

24. 基于项的控件

一、基于项的控件PySide6 有专门的显示数据的控件和存储数据的模型,可以显示和存储不同形式的数据。显示数据的控件分为两类,一类是基于 项(item)的控件,另一类是基于 模型(model)的控件,基于项的控件是基于模型的控件的简便类。基于项的控件把读取到的数据存储到项中,…

杂题选记

杂题选记在网上天天划水刷面经,见到 teaser 就记下来。我的想法是,把 8L 倒入 3L,把 3L 倒入 5L,把 8L 倒入 3L,把 3L 倒入 5L,这时候三个瓶子分别有 1L(8L) 2L(3L) 5L(5L) 括号里面表示瓶子最开始的容量。这时候把 1L 水倒掉,把容积为 8L 的瓶子里面的 2L 水倒到 容积为…

pytorch算子调用过程:以rand算子为例

通过pytorch的torch.profiler带调用栈采集运行过程可以看到如下信息,通过chrome://tracing查看,图上每个小条条表示一个traceEvent, json中的信息如下图所示,其中cat表示traceEvent的类型,有cpu_op,python_function等,前者表示torch的cpp代码中定义的操作,后者表示pytorc…

Wordpress更换域名后,网站显示框架和加载问题解决

最近建立了一个站点,由于先使用ip进行网站搭建,经过一段时间备案完成后,需要转成域名。直接在Wordpress后台操作后,直接导致网页框架显示异常,排版错乱,大概就是主题的框架无法加载导致的。 搞了很久,包括恢复数据库和重新建站都是这样,最终发现是伪静态的问题。 我是使…