Ⅰ Web框架
【一】Web框架本质
- web框架本质上可以看成是一个功能强大的socket服务端,用户的浏览器可以看成是拥有可视化界面的socket客户端。
- 两者通过网络请求实现数据交互,从架构层面上先简单的将Web框架看做是对前端、数据库的全方位整合
# TCP服务端与客户端进行交互的过程
# web框架其实就是一个 TCP 服务端
# 客户端和服务端进行数据交互就是基于 socket 协议进行数据传输
# 客户端 (浏览器/App界面) <-> 服务端(web框架 Django / flask / fastapi ... ) <->数据库 (MySQL / Redis / MongoDB ...)
【二】手写Web框架
- 前面的课程我们已经学习了网络编程并掌握了socket套接字编程
- 接下来我们就可以自己编写出一个简易的web框架
【1】原始版本
(1)服务端
# 【一】导入模块
import socket
# 【二】定义通信IP和端口
IP = '127.0.0.1'
PORT = 8809
# 【三】创建socket对象
server = socket.socket()
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 就是它,在bind前加
# 【四】监听端口
server.bind((IP, PORT))
# 【五】创建半连接池
server.listen(5)
while True:
# 【六】接收客户端链接和地址
sock, addr = server.accept()
# 【七】接收数据
data = sock.recv(1024)
print(f'这是来自客户端的信息 :>>>> {data.decode("utf-8")}')
# 【八】回送数据
sock.send(b'hello client')
(2)客户端
# 【一】导入模块
import socket
# 【二】定义通信IP和端口
IP = '127.0.0.1'
PORT = 8809
# 【三】创建连接对象
client = socket.socket()
client.connect((IP, PORT))
while True:
# 【四】发送数据
client.send(b"hello server")
# 【五】接收数据
data = client.recv(1024)
print(f"这是来自服务端的数据 :>>>> {data.decode('utf-8')}")
- 浏览器访问指定的IP和端口访问服务端
- 127.0.0.1:8809
- 发生了错误 : 返回的信息无效
【2】浏览器发送请求—>增加 HTTP 响应模型格式
-
遵循HTTP协议
-
四大特性
- 1.基于请求与响应的模型
- 2.无状态
- 3.基于TCP/IP之上的应用层协议
- 4.短连接
-
数据格式
-
# 请求格式 # 请求首行 请求方法 请求路径 协议版本 # 请求头 kv键值对 # 换行 # 请求体
-
# 【2】响应格式 # 响应首行 响应状态码 协议版本 # 响应头 # 换行 # 响应体
-
-
响应状态码
-
import socket
server = socket.socket()
ip = "127.0.0.1"
port = 8809
addr = (ip, port)
server.bind(addr)
server.listen(5)
conn, addr = server.accept()
from_client_data = conn.recv(1024)
from_client_data = from_client_data.decode()
print("from_client_data :>>>>", from_client_data)
# 响应首行 协议版本 + 状态码 + 换行
back_statue = "HTTP/1.1" + "200 OK" + "\r\n\r\n"
# 响应体数据
to_client_data = "this is a message"
response_data = back_statue + to_client_data
response_data = response_data.encode()
conn.send(response_data)
"""
# 我们在浏览器上会看到指定的路由访问地址
# 127.0.0.1:8809/login
# 127.0.0.1:8809/register
【3】路由对应响应
- 基于不同的后缀相应不同的内容
- 如何获取用户输入的url后缀
- HTTP请求数据
- /favicon.ico直接忽略 不影响判断
- 利用字符串切割和索引取值获取相应数据
import socket
server = socket.socket()
ip = "127.0.0.1"
port = 8809
addr = (ip, port)
server.bind(addr)
server.listen(5)
conn, addr = server.accept()
def response(visit_path):
# 响应首行 协议版本 + 状态码 + 换行
back_statue = "HTTP/1.1" + "200 OK" + "\r\n\r\n"
if visit_path == "/":
# 响应体数据
to_client_data = "this is main index"
elif visit_path == "/login":
to_client_data = "this is login index"
elif visit_path == "/register":
to_client_data = "this is register index"
else:
to_client_data = "404"
response_data = back_statue + to_client_data
response_data = response_data.encode()
return response_data
from_client_data = conn.recv(1024)
from_client_data = from_client_data.decode()
# print("from_client_data :>>>>", from_client_data)
visit_path = from_client_data.split(" ")[1]
conn.send(response(visit_path))
【4】小结
- 纯手撸框架缺陷:
- socket代码过于重复(每次搭建服务端都需要反复造轮子)
- 针对HTTP请求数据没有完善的处理方式(目前只能定向切割)
- 无法实现服务端的并发
【三】基于wsgiref模块搭建web框架
【1】模块封装功能
from wsgiref import simple_server
def run(request, response):
"""
:param request: 请求相关的数据
:param response: 响应相关的数据
:return: 返回给客户端的展示数据
"""
response('200 OK', []) # 固定编写 无需掌握
return [b'Hello World']
if __name__ == '__main__':
'''服务端监听的IP和端口'''
IP = '127.0.0.1'
PORT = 8080
'''创建一个服务端对象'''
server = simple_server.make_server(IP, PORT, run)
'''监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
server.serve_forever()
# 模块封装了socket代码并将请求数据处理成诸多k:v键值对
【2】路由对应响应
from wsgiref import simple_server
def run(request, response):
"""
:param request: 请求相关的数据
:param response: 响应相关的数据
:return: 返回给客户端的展示数据
"""
response('200 OK', []) # 固定编写 无需掌握
# 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']
if __name__ == '__main__':
'''服务端监听的IP和端口'''
IP = '127.0.0.1'
PORT = 8080
'''创建一个服务端对象'''
server = simple_server.make_server(IP, PORT, run)
'''监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
server.serve_forever()
# 模块封装了socket代码并将请求数据处理成诸多k:v键值对
【四】优化方案
【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文件夹 存储项目所需的'静态文件'
【2】优化方案实现
(1)路由和响应模块化
- 当有很多路由和响应的情况下不可能无限制编写if判断语句,应该设置对应关系并动态调用
from wsgiref import simple_server
def run(request, response):
"""
:param request: 请求相关的数据
:param response: 响应相关的数据
:return: 返回给客户端的展示数据
"""
response('200 OK', []) # 固定编写 无需掌握
# 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']
if __name__ == '__main__':
'''服务端监听的IP和端口'''
IP = '127.0.0.1'
PORT = 8080
'''创建一个服务端对象'''
server = simple_server.make_server(IP, PORT, run)
'''监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
server.serve_forever()
# 模块封装了socket代码并将请求数据处理成诸多k:v键值对
(2)根据功能划分模块
- 根据功能的不同拆分成不同的py文件
- manage.py
# 对浏览器的访问路径进行分配
import socket
from server.response import response
from server.urls import urlpatterns
server = socket.socket()
ip = "127.0.0.1"
port = 8809
addr = (ip, port)
server.bind(addr)
server.listen(5)
conn, addr = server.accept()
from_client_data = conn.recv(1024)
from_client_data = from_client_data.decode()
# print("from_client_data :>>>>", from_client_data)
visit_path = from_client_data.split(" ")[1]
for path_view in urlpatterns:
path, view = path_view
if path == visit_path:
data = view()
conn.send(response(data))
- response.py
def response(to_client_data):
# 响应首行 协议版本 + 状态码 + 换行
back_statue = "HTTP/1.1" + "200 OK" + "\r\n\r\n"
response_data = back_statue + to_client_data
response_data = response_data.encode()
return response_data
- urls.py
from .view import index, login, register
urlpatterns = [
("/", index),
("/login", login),
("/register", register),
]
- view.py
def read_data(path):
with open(path, mode="r", encoding="utf-8") as file:
return file.read()
def index():
to_client_data = "this is main index"
return to_client_data
def login():
# 可以返回指定的HTML页面
# 这个页面是死的页面 静态页面 所有数据都是固定死的 没办法重新渲染数据
# 动态页面 : 通过其他请求获取到 json / 其他格式的数据
# 通过 js 动作动态加载进去 inputEle.text()
to_client_data = read_data("login.html")
return to_client_data
def register():
to_client_data = "this is register index"
return to_client_data
总结:
拆分后好处在于要想新增一个功能,只需要在views.py中编写函数,urls.py添加对应关系即可
(3)模板文件与静态文件
- templates文件夹
--存储html文件 - .static文件夹
--存储html页面所需静态资源(后续详细讲解或自行百度)
【五】动静态网页
【1】静态网页
(1)介绍
- 静态网页 是一种基本的网页形式,其中的数据和布局在编写 HTML 文件时就已经固定下来,不随用户的请求或时间的变化而改变。
- 静态网页内容主要包括 HTML、CSS 和 JavaScript 等前端技术构建的页面结构、样式和行为。
- 由于其内容不依赖于服务器端动态处理,因此它们具有以下特点
(2)特点
- 内容固定:页面上的所有数据(文本、图片、链接等)都直接写入 HTML 文件,不会因为用户的不同请求或时间的变化而变化。
- 无需服务器处理:当用户访问静态网页时,浏览器直接从服务器下载对应的 HTML 文件并显示内容,服务器主要负责存储和分发已存在的网页资源。
- 加载速度快:由于内容不需服务器进一步处理,所以加载速度较快。
(3)示例
- 常见例子有:error.html、func.html等预定义的错误提示页面、功能说明页面等。
【2】动态网页
(1)介绍
- 动态网页则是在服务器端运行脚本语言(如 PHP、Python、JavaScript 或 Java 等)来生成和处理数据,然后再将处理后的数据以 HTML 格式发送至浏览器。
(2)特点
- 内容实时更新:页面上的数据可以根据用户的请求、数据库查询结果或其他服务器端逻辑动态生成,这意味着同一页面可以呈现不同的内容给不同的用户或在不同时间访问的用户。
- 需要服务器处理:当用户访问 动态网页时,服务器会根据请求执行相应的脚本程序,调用后台数据库进行查询、计算等操作,然后再将处理后的数据返回给浏览器,浏览器负责渲染这些动态内容。
- 数据交互性强:动态网页支持与用户交互,如表单提交、搜索功能等,能更好地满足用户实时需求和个性化体验。
(3)示例
- 展示当前时间:服务器端定时获取系统时间,动态生成包含当前时间的 HTML 内容发送给浏览器显示。
- 显示数据库数据:根据用户的请求,从数据库查询相关数据,生成带有动态内容的 HTML 页面供用户浏览。
【3】总结
- 静态网页适合用于内容较少且不需要频繁更新的场景,如关于我们、联系我们等基础介绍页面。
- 动态网页则更适用于需要实时交互、内容丰富且需要定期更新的场景,如新闻资讯、在线购物平台等,通过服务器端的动态处理,提供了更好的用户体验和更高的业务复杂性处理能力。
【六】Jinja2模板语法
【1】页面展示当前时间
(1)后端
from wsgiref import simple_server
import time
import re
# pip install jinjia2
# Template : 模版
from jinja2 import Template
def get_time():
c_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
with open("login.html", "r", encoding='utf-8') as fp:
data = fp.read()
pattern = re.compile("<p >(.*)</p>")
pattern.sub(c_time, data)
return data
def get_dict():
user_dict = {'name': 'silence', '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)
# 模版对象的 render 渲染方法
res = temp_obj.render({'user': user_dict, 'new_list': new_list})
return res
def run(request, response):
# 固定响应格式
response("200 OK", [])
return [get_dict().encode()]
if __name__ == '__main__':
ip = "127.0.0.1"
port = 8819
server = simple_server.make_server(ip, port, run)
server.serve_forever()
(2)前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<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>
</body>
</html>
【2】jinja2模板语法
(1)下载安装
- 第三方模块需要先下载后使用
pip3 install jinja2
(2)功能
- 支持将数据传递到html页面并提供近似于后端的处理方式简单快捷的操作数据
(3)views.py
from jinja2 import Template
def get_dict(request):
user_dict = {'name': 'silence', '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
(4)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>
【七】框架请求流程图片
【八】关键字
【1】urls.py
- 后缀与函数名对应关系
- ('/index',register)
- 后缀专业名词称之为'路由'
- 函数名专业名词称之为'视图函数'
- urls.py专业名词称之为'路由层'
【2】views.py
- 专门编写业务逻辑代码
- 可以是函数 也可以是类
- 函数专业名词称之为'视图函数'
- 类专业名词称之为'视图类'
- views.py专业名词称之为'视图层'
【3】templates文件夹
- 专门存储html文件
- html文件专业名词称之为'模板文件'
- templates文件夹专业名词称之为'模板层'
【4】static文件夹
- 专门存储静态文件资源
- 页面所需css文件、js文件、图片文件、第三方文件可统称为'静态资源'
Ⅱ Python框架初识
【一】网络框架及MVC架构
【1】网络框架
- 所谓网络框架是指这样的一组Python包,它能够使开发者专注于网站应用业务逻辑的开发,而无须处理网络应用底层的协议、线程、进程等方面。这样能大大提高开发者的工作效率,同时提高网络应用程序的质量。
- 在目前Python语言的几十个开发框架中,几乎所有的全栈网络框架都强制或引导开发者使用MVC架构开发Web应用。
- 所谓全栈网络框架,是指除了封装网络和线程操作,还提供HTTP栈、数据库读写管理、HTML模板引擎等一系列功能的网络框架。
- 本文重点讲解的Django、Tornado和Flask是全栈网络框架的典型标杆;而Twisted更专注于网络底层的高性能封装而不提供HTML模板引擎等界面功能,所以不能称之为全栈框架。
【2】MVC架构
- MVC(Model-View-Controller)模式最早由Trygve Reenskaug在1978年提出,在20世纪80年代是程序语言Smalltalk的一种内部架构。
- 后来MVC被其他语言所借鉴,成为了软件工程中的一种软件架构模式。
- MVC把Web应用系统分为3个基本部分。
(1)模型(Model)
- 用于封装与应用程序的业务逻辑相关的数据及对数据的处理方法,是Web应用程序中用于处理应用程序的数据逻辑的部分,Model只提供功能性的接口,通过这些接口可以获取Model的所有功能。
- Model不依赖于View和Controller,它们可以在任何时候调用Model访问数据。
- 有些Model还提供了事件通知机制,为在其上注册过的View或Controller提供实时的数据更新。
(2)视图(View)
- 负责数据的显示和呈现,View是对用户的直接输出。
- MVC中的一个Model通常为多个View提供服务。
- 为了获取Model的实时更新数据,View应该尽早地注册到Model中。
(3)控制器(Controller)
- 负责从用户端收集用户的输入,可以看成提供View的反向功能。
- 当用户的输入导致View发生变化时,这种变化必须是通过Model反映给View的。
- 在MVC架构下,Controller一般不能与View直接通信,这样提高了业务数据的一致性,即以Model作为数据中心。
【3】MVC架构图
- 这3个基本部分互相分离,使得在改进和升级界面及用户交互流程时,不需要重写业务逻辑及数据访问代码。MVC架构如图1所示。
注意:MVC在除Python外的其他语言中也有广泛应用,例如VC++的MFC、Java的Structs及Spring、C#的.NET开发框架,读者应该有深刻的体会。
【二】Python主流的后端框架
【1】Django
(1)介绍
- 相对于Python的其他Web框架,Django的功能是最完整的,Django定义了服务发布、路由映射、模板编程、数据处理的一整套功能。
- 这也意味着Django模块之间紧密耦合,开发者需要学习Django自己定义的这一整套技术。
(2)特点
1.完善的文档
- 经过10多年的发展和完善,Django有广泛的应用和完善的在线文档,开发者遇到问题时可以搜索在线文档寻求解决方案。
2.集成数据访问组件
- Django的Model层自带数据库ORM组件,使开发者无须学习其他数据库访问技术(dbi、SQLAlchemy等)。
3.强大的URL映射技术
- Django使用正则表达式管理URL映射,因此给开发者带来了极高的灵活性。
4.后台管理系统自动生成
- 开发者只需通过简单的几行配置和代码就可以实现完整的后台数据管理Web控制台。
5.错误信息非常完整
- 在开发调试过程中如果出现运行异常,则Django可以提供非常完整的错误信息帮助开发者定位问题,比如缺少xxx组件的配置引用等,这样可以使开发者马上改正错误。
(3)组成结构
- Django是遵循MVC架构的Web开发框架,其主要由以下几部分组成。
- 管理工具(Management):一套内置的创建站点、迁移数据、维护静态文件的命令工具。
- 模型(Model):提供数据访问接口和模块,包括数据字段、元数据、数据关系等的定义及操作。
- 视图(View):Django的视图层封装了HTTP Request和Response的一系列操作和数据流,其主要功能包括URL映射机制、绑定模板等。
- 模板(Template):是一套Django自己的页面渲染模板语言,用若干内置的tags和filters定义页面的生成方式。
- 表单(Form):通过内置的数据类型和控件生成HTML表单。
- 管理站(Admin):通过声明需要管理的Model,快速生成后台数据管理网站。
(4)总结
- 大而全
- 自带的功能非常的多
- 但是有时候会略显笨重
- 类似于'航空母舰'
【2】Flask
(1)介绍
- Flask是Python Web框架族里比较年轻的一个,于2010年出现,这使得它吸收了其他框架的优点,并且把自己的主要领域定义在了微小项目上。
- 同时,它是可扩展的,Flask让开发者自己选择用什么数据库插件存储他们的数据。
- 很多功能简单但性能卓越的网站就是基于Flask框架而搭建的,比如httpbin.org就是一个功能简单但性能强大的HTTP测试项目。
- Flask是一个面向简单需求和小型应用的微框架。
(2)特点
1.内置开发服务器和调试器
-
网络程序调试是在将编制好的网站投入实际运行前,用手工或编译程序等方法进行测试,修正语法错误和逻辑错误的过程。
-
- 有经验的开发者都知道,这是保证网站系统能够正式应用的必要步骤。
-
Flask 自带的开发服务器使开发者在调试程序时无须再安装其他任何网络服务器,比如Tomcat、JBoss、Apache等。
-
Flask默认处于调试状态,使得运行中的任何错误会同时向两个目标发送信息:
-
- 一个是Python Console,即启动Python程序的控制台;
- 另一个是HTTP客户端,即Flask开发服务器将调试信息传递给了客户端。
2.与Python单元测试功能无缝衔接
- 单元测试是对最小软件开发单元的测试,其重点测试程序的内部结构,主要采用白盒测试方法,由开发人员负责。
- 单元测试的主要目标是保证函数在给定的输入状态下,能够得到预想的输出,在不符合要求时能够提醒开发人员进行检查。
- Flask提供了一个与Python自带的单元测试框架unitest无缝衔接的测试接口,即Flask对象的test_client()函数。
- 通过test_client()函数,测试程序可以模拟进行HTTP访问的客户端来调用Flask路由处理函数,并且获取函数的输出来进行自定义的验证。
3.使用Jinja2模板
- 将HTML页面与后台应用程序联系起来一直是网站程序框架的一个重要目标。
- Flask通过使用Jinja2模板技术解决了这个问题。
- Jinja2是一个非常灵活的HTML模板技术,它是从Django模板发展而来的,但是比Django模板使用起来更加自由且更加高效。
- Jinja2模板使用配制的语义系统,提供灵活的模板继承技术,自动抗击XSS跨站攻击并且易于调试。
4.完全兼容WSGI 1.0标准
- WSGI(Web Server Gateway Interface)具有很强的伸缩性且能运行于多线程或多进程环境下,因为Python线程全局锁的存在,使得WSGI的这个特性至关重要。
- WSGI已经是Python界的一个主要标准,各种大型网路服务器对其都有良好的支持。
- WSGI位于Web应用程序与Web服务器之间,与WSGI完全兼容使得Flask能够配置到各种大型网络服务器中。
5.基于Unicode编码
- Flask是完全基于Unicode的。这对制作非纯ASCII字符集的网站来说非常方便。
- HTTP本身是基于字节的,也就是说任何编码格式都可以在HTTP中传输。
- 但是,HTTP要求在HTTP Head中显式地声明在本次传输中所应用的编码格式。
- 在默认情况下,Flask会自动添加一个UTF-8编码格式的HTTP Head,使程序员无须担心编码的问题。
(3)总结
- 小而精
- 自带的功能非常的少
- 但是第三方模块非常的多
- 类似于'游骑兵'
- flask的第三方模块加到一起甚至比django还多
- 并且也越来越像django
- flask由于过多的依赖于第三方模块
- 有时候也会受制于第三方模块
【3】Tornado
(1)介绍
- Tornado是使用Python编写的一个强大的可扩展的Web服务器。
- 它在处理高网络流量时表现得足够强健,却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。
- Tornado作为FriendFeed网站的基础框架,于2009年9月10日发布,目前已经获得了很多社区的支持,并且在一系列不同的场合中得到应用。
- 除FriendFeed和Facebook外,还有很多公司在生产上转向Tornado,包括Quora、Turntable.fm、Bit.ly、Hipmunk及MyYearbook等。
(2)特点
- 完备的Web框架:与Django、Flask等一样,Tornado也提供了URL路由映射、Request上下文、基于模板的页面渲染技术等开发Web应用的必备工具。
- 是一个高效的网络库,性能与Twisted、Gevent等底层Python框架相媲美:提供了异步I/O支持、超时事件处理。这使得Tornado除了可以作为Web应用服务器框架,还可以用来做爬虫应用、物联网关、游戏服务器等后台应用。
- 提供高效HTTPClient:除了服务器端框架,Tornado还提供了基于异步框架的HTTP客户端。
- 提供高效的内部HTTP服务器:虽然其他Python网络框架(Django、Flask)也提供了内部HTTP服务器,但它们的HTTP服务器由于性能原因只能用于测试环境。而Tornado的HTTP服务器与Tornado异步调用紧密结合,可以直接用于生产环境。
- 完备的WebSocket支持:WebSocket是HTML5的一种新标准,实现了浏览器与服务器之间的双向实时通信。
(3)总结
- 异步非阻塞框架
- 速度极快
- 常被用作大型站点的接口服务框架
- 甚至可以用于充当游戏服务器
【4】Fastapi
(1)介绍
- FastAPI 是一个现代 Web 框架,速度相对较快,用于基于标准 Python 类型提示使用 Python 3.7+ 构建 API。
- FastAPI还帮助我们自动为我们的Web服务生成文档,以便其他开发人员可以快速了解如何使用它。
- FastAPI 具有许多功能,例如它可以显着提高开发速度,还可以减少代码中的人为错误。
- 它很容易学习并且完全可以用于生产。
- FastAPI 与众所周知的 API 标准(即OpenAPI 和JSON schema)完全兼容。
(2)特点
1.自动文档
- FastAPI 使用 OpenAPI 标准自动生成交互式 API 文档。
- 可以通过访问应用程序中的特定端点来访问此文档,这使得理解和测试 API 变得非常容易,而无需手动编写大量文档。
2.Python 类型提示
- FastAPI 的突出功能之一是它使用 Python 类型提示。
- 通过使用类型提示注释函数参数和返回类型,不仅可以提高代码可读性,还可以使 FastAPI 自动验证传入数据并生成准确的 API 文档。
- 此功能使我们的代码不易出错并且更加自我记录。
3.数据验证
- FastAPI 使用 Pydantic 模型进行数据验证。
- 可以使用 Pydantic 的架构和验证功能定义数据模型。
- 这可确保传入数据自动验证、序列化和反序列化,从而降低在应用程序中处理无效数据的风险。
4.异步支持
- 随着Python异步编程的兴起,FastAPI完全拥抱异步操作。
- 可以使用Python的async和await关键字来编写异步端点,使其非常适合处理I/O密集型任务并提高应用程序的整体响应能力。
5.依赖注入
- FastAPI 支持依赖注入,允许声明端点的依赖关系。
- 这有助于保持代码模块化、可测试和可维护。
- 我们可以将数据库连接、身份验证等依赖项无缝地注入到的路由中。
6.安全功能
- FastAPI 包含各种开箱即用的安全功能,例如对 OAuth2、JWT(JSON Web 令牌)的支持以及请求数据的自动验证,以防止 SQL 注入和跨站点脚本 (XSS) 攻击等常见安全漏洞。
【三】Python框架官网(部分)
框架的核心逻辑几乎是一致的 我们在学习的时候只需要先学会一种之后就可以触类旁通
- 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/
【四】Django框架版本
【1】框架版本介绍
- Django 是一个高级的Python Web框架,由荷兰人Armin Ronacher创建。
- 随着版本的迭代和功能的不断优化,Django在处理异步请求方面也有了显著的进步。
(1)Django1.x
- 默认不支持异步
- Django 1.x主要集中在传统的Web开发上,其设计思想倾向于同步HTTP请求处理。
- 默认情况下,并未内置对异步编程的支持,开发者若要在Django 1.x中实现异步处理,通常需要借助第三方库如django-celery或django-tornado等来结合其他异步框架(如Celery、Tornado等)来实现后台任务的异步执行。
(2)Django2.x
- 默认不支持异步
- 在Django 2.x版本中,虽然核心框架并未直接提供对异步HTTP请求的支持,但已经开始引入一些异步相关的新特性和API,比如asgi (Asynchronous Server Gateway Interface) 标准的初步支持。
- 开发者可以通过安装第三方ASGI服务器(如daphne或uvicorn),配合channels库使用,来实现Websockets和消息队列等场景下的部分异步功能。
(3)Django3.x
- 自带异步功能
- Django 3.x标志着其正式对异步编程的支持,它引入了channels框架作为标准库的一部分,实现了全栈的WebSocket支持以及与asyncio的集成,使得开发者可以直接在视图层、消费者层以及中间件层面编写异步代码,提供了ASGI和HTTP/2协议的底层支持。
- 此外,django-redis、django-socketio等第三方库也进一步丰富了异步应用的构建能力。
(4)Django4.x
- 在Django 4.x版本之后,异步功能得到了持续加强和完善。
- 例如,在4.0中,channels框架进行了重大重构,使其更加轻量级和模块化,同时引入了websockets库作为默认WebSocket支持,大大简化了开发者配置和使用的复杂度。
- 此外,对于长期支持计划(LTS)版本,Django会确保异步相关的API和工具在后续更新中得到稳定且兼容的维护和支持,以满足现代Web应用对高性能、低延迟的需求。
【2】推荐学习
(1)推荐版本
- 学习基于Django2.x/3.x版本即可
(2)推荐原因
- Django1.x在老项目中使用频率最高、最广泛的版本!!!
- Django2.X功能几乎一致
- Django3.X最主要的区别在于新增了一个异步的功能
- 近几年随着技术的迭代和进步,大部分的企业项目已经完成了最基础的迭代,所以学习Django1.x太过于古老
- 我们选择学习低于最新版本的下一个版本 Django 3.x 版本
- Django3.x和Django2.x在语法上区别不大,主要是对某些功能进行了优化,所以问题不大
Ⅲ Django框架安装
【一】首先要清楚的知道自己的系统环境
【1】如何区分我当前使用的是哪个版本的 python
- 根据你的系统环境变量的python解释器的定义顺序决定的
- 哪个解释器的路径在上边默认就是哪个解释器
【2】知道自己的默认解释器后
- 默认是哪个解释器 pip 就是哪个解释器的
- pip 安装的包就会安装给指定的解释器
【二】Django框架下载
【1】pip安装
- 如果在终端输入
pip3 install django==
- 则会出现各种版本信息
- 使用 pip 命令安装指定版本的第三方包
pip3 install django==3.2.12
- 如果之前下载了其他版本不用管
- Python解释器会将旧版本卸载,安装指定的版本,即自动替换!!!
【2】安装注意事项
- 计算机名称不要出现中文
- python解释器版本不同可能会出现启动报错
- Django项目名和路径名不要出现中文!
- 多个项目文件尽量不要嵌套,做到一项一夹
【3】可能会存在的报错
- 启动如果报错,根据提示找到修改widgets.py文件第152行源码,删除最后的逗号即可
【三】如何检验是否安装成功
【1】通过控制台输出
pip3 install django==3.2.12
# Requirement already satisfied: pytz in e:\python\python310\lib\site-packages (from django==3.2.12) (2024.1)
# 会提示将Django安装到指定版本的解释器身上了
【2】命令行终端
- 终端输入会出现如下,原理就是调用了Scripts下的django-admin
- 如果确定自己安装成功了,但是就是在终端没效果,那一定是你的环境有问题!
- 当前是否能正常打印Python解释器版本
- 核验自己安装的Django到底是安装在了哪个Python解释器上
django-admin
【3】去指定的文件路径下找
- 解释器下的
Scripts
文件夹下
【四】使用Django创建项目
【1】命令行创建
(1)语法
django-admin startproject 项目名
django-admin startproject first_django
# 在指定目录下执行命令后会出现一个文件夹 first_django
- 在python中打开刚才创建的first_django
(2)命令行创建APP(应用)
Django框架就相当于一个大学 大学
在大学里面开设很多个专业 养猪
专业下面又有很多单位和相应功能 老师 学生
cd first_django
python manage.py startapp app名字
# app名字一般为英文
python manage.py startapp user
【2】启动Django项目
(1)语法
python3 manage.py runserver [IP:PORT]
- IP和PORT可可以指定,默认是本地的 127.0.0.1:8000
(2)示例
- 进入到创建好的文件目录下
- 注意这个文件目录是你当前目录下有 manage.py 文件才行
python manage.py runserver
- 或者是通过python终端
- 访问底下提示的链接地址
【五】通过pycharm创建
【1】创建项目
【2】通过python终端创建APP
python manage.py startapp app名字
# app名字一般为英文
python manage.py startapp patch
【3】指定启动ip
【4】两个错误
- 一个是没有启动Django支持
- 如果把对号勾掉,再打开运行/调试配置
- 一个是没有选择Django项目根路径及配置文件
【六】注册app使用app
【1】注册app
- 创建APP后,如果想使用相关的功能,必须将创建的APP注册到配置文件中
- 即在settings中加入下述内容
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 必须注册app才能使用app
'user'
]
【2】使用app
- 第一步 前提是注册app了
- 第二步 定义视图函数
user/views.py
- 视图函数必须有一个位置参数交 request
from django.shortcuts import render
# Create your views here.
# 定义一个视图函数 必须有一个位置参数
def login(request):
# render 渲染前端页面的语法
# 前端文件名必须在 templates 文件夹下
# 返回的是一个 HTML 页面
return render(request,"login.html")
- 第三步 要在路由映射关系
first_django/urls.py
注册映射关系
from django.contrib import admin
from django.urls import path
from user.views import login
urlpatterns = [
path('admin/', admin.site.urls),
# 默认访问根目录的时候 会执行 login 视图函数返回数据
path('', login),
]
- 启动项目 访问指定的路径
【3】代码展示
- views.py
from django.shortcuts import render
# Create your views here.
# 定义一个视图函数 必须有一个位置参数
def login(request):
# user_data = {"username": "admin", "password": "<PASSWORD>"}
# render渲染前端页面的语法
# 前端文件名必须在templates 文件夹下
return render(request, 'login.html')
# return render(request, 'login.html', locals())
- login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>当前是登录页面</h1>
</body>
</html>
- urls.py
from django.contrib import admin
from django.urls import path
from user.views import login
urlpatterns = [
path('admin/', admin.site.urls),
path('', login),
]
【七】使用app字典使用
- urls.py
from django.contrib import admin
from django.urls import path
from user.views import login
urlpatterns = [
path('admin/', admin.site.urls),
path('', login),
]
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ user }}
{{ user_data }}
{{ user_data.username }}
</body>
</html>
- views.py
from django.shortcuts import render
# Create your views here.
# 定义一个视图函数 必须有一个位置参数
def login(request):
user_data = {"username": "admin", "password": "<PASSWORD>"}
# render渲染前端页面的语法
# 前端文件名必须在templates 文件夹下
# return render(request, 'login.html', {"user": user_data})
# 上面这种根据键名user取到字典
return render(request, 'login.html', locals())
# locals局部变量 这种根据键名user_data取到字典 或者是user_data.username取到值
标签:Web,框架,server,初识,client,django,Django,data
From: https://www.cnblogs.com/zyb123/p/18253141