20221110_测试开发-web开发和flask
本文讲述web后端框架及flask简单实现
概念
web开发
web即万维网, 基于html和超文本的图形信息系统, web应用基本上就是指现在B/S架构上的应用
web开发: 即web应用开发, 编写代码服务端的代码, 对Browser的请求作出响应从而提供信息服务,目前比较流行MVC模式的框架
B/S架构: Browser/Server模式, 服务和数据库都运行在服务端, 由Browser提供客户查看的web页面
C/S架构: Client-Server模式, 服务运行在客户端, 数据库运行在服务器端,适用于比较重的应用, 比如Office, 端游
HTTP协议
即Hybridtext Transport Protocol , 超文本传输协议. B/S架构中Browser和Server进行通信的协议,基于TCP/IP
Http请求四要素
- 请求方法: Restful API中主要用于表明请求的行为
- 请求url: 请求资源路径
- 请求头: token, cookie, 表明请求体格式信息等
- 请求体: 请求payload,如json数据, 文件二进制数据等
Http响应要素:
- 状态码: 表明技术层面的请求结果
- 响应头: cookie, 表明请求体格式信息等
- 响应体: 放置Browser想要的数据
HTML
即Hybridtext Mark Language: 超文本标记语言
web开发技术实现
要弄清楚如何进行web开发, 首先要先弄懂web服务器如何提供服务
web服务器如何提供服务?
从外部看
我们发送一个Http请求给服务器, 服务器返回我们想要的数据,数据可以分为2种:
- 静态资源: 服务器返回了一张图片, 一个视频,一个文档
- 动态资源: 服务器根据请求返回对应的数据, 数据一般来自数据库
从内部看
web服务器首先要完成这么几件事:
- 网络底层: 搞定TCP握手挥手等网络底层交互的事
- 解析请求: 对HTTP原始请求进行解析
- 准备响应数据: 根据请求, 加入响应状态码以及响应头
准备数据放在响应体中,数据包括:- HTML页面: 客户看到的页面
- JSON数据: 页面中最有价值的,来自数据库的数据
- 静态资源: 页面上展示的icon, 图片等
- 发送响应: 以HTTP要求格式发送响应,包含响应行,响应头,响应体
知道了需要做什么事,接下来就要考虑如何实现了
如何进行web开发?
其实对于业务来说,真正有意义的响应状态码, 响应头和响应体
我们真正想要做的是,是第2步拿到请求数据, 准备数据,返回响应数据
而网络底层的交互, HTTP层面的请求接受解析, 响应发送格式, 对于我们麻烦而且没有实际意义的事,
为了避免这种麻烦,我们就需要WSGI了
关于WSGI
即Web Server Gateway Interface, Web服务器通道接口
我们只需要:
- 定义一个符合WSGI的HTTP处理函数, 里面编写响应请求代码
- 参数environ: 直接拿去解析后的数据,
- 参数start_response用来发送响应头和状态码
- return: 响应体
- 起一个wsgi服务器, HTTP处理函数对象作为处理器配置, 开启服务器
运行过程:
- wsgi服务器在监听端口抓取到请求,建立TCP链接, 调用HTTP处理函数,
- 将请求信息解析为dict,作为environ传入HTTP处理函数,
- 自己生成start_response函数对象,传入HTTP处理函数,
- HTTP处理函数内部业务处理代码对请求进行处理, 生成状态码,响应头,响应体信息
- wsgi服务器将响应信息以HTTP报文格式发送
HTTP处理函数
from loguru import logger
# 定义一个wsgi函数,后续交给wsgi服务器调用
def application(environ, start_response):
logger.warning(environ['QUERY_STRING']or 'No QUERY_STRING')
start_response('200 OK', [('Content_Type', "text/html")])
return [b'<h1>Hello, web!<h1>']
启动服务器
from wsgiref.simple_server import make_server
from hello import application
# 使用定义好的wsgi HTTP处理函数,创建一个wsgiref服务器对象
http_server = make_server("", 8000, application)
print("Serving Http on port 8000...")
# 运行服务器
http_server.serve_forever()
wsgire是Python内置的对WSGI的参考实现,只能用来开发和测试
通过wsgi服务器,我们成功拿到了请求四要素, 而且知道怎么返回响应信息, 但是,一个服务器可能有上百个接口,Restful API还可能要对应4个请求方法, 如何将这些接口的业务实现代码组合起来的, 这个时候我们就需要web框架了
Web框架
web框架建立业务代码与 请求方法+请求路径 的映射, 而我们只要对根据请求实现对应的业务代码
以flask为例
我们只需要:
- 导入flask并初始化一个Flask应用对象,导入request对象
- 编写处理函数, 在业务函数下,拿取request中的请求数据,编写业务代码返回
- 在Flask对象的route方法填写对应的请求路径及请求方法,装饰业务处理函数,
运行过程:
- flask接受到WSGI服务器传递的请求, 根据请求中的请求方法和path,将请求交给对应处理函数
- 处理函数通过request对象拿取请求数据, 处理后返回响应数据
- flask将响应发送回WSGI服务器
from flask import Flask, request
from loguru import logger
app = Flask(__name__)
@app.route('/', methods=['GET'])
def home():
return '<h1>Welcom to BetterUs<h1>'
@app.route('/signin', methods=["GET"])
def signin_form():
return """
<form action="/signin" method='post'>
<p><input name="username"></p>
<p><input name="password"></p>
<p><button type="submit">Sign In</button></p>
</form>
"""
@app.route("/signin", methods=['POST'])
def signin():
logger.warning(request.form)
if request.form['username'] == "admin" and request.form['password']=='a1234':
return "Hello, admin"
return "Username or Password is not correct"
# flask自带一个小型web服务器
if __name__ == '__main__':
app.run()
有了web框架,让我们得以忽略 过多的接口url带来的复杂度,专业编写业务代码
json数据我们可以通过查询数据库返回, 而html页面我们要怎么处理返回?
MVC
按照MVC设计模式. 我们可以设置html模板(View), 而对其中一些需要变更的内容进行参数化,
根据请求解析的数据或者固定设置的数据, 形成参数池(Model),
在处理函数(Controller)中处理业务逻辑, 在model中取特定数据交给View生成html页面,返回给前段
以flask为例
我们需要:
- 安装Jinja2, tempaltes文件夹下编写html模板,使用Jinja2语法定义渲染效果(比如对需要变更的内容进行参数化)
- 处理函数中, 按照业务逻辑,得到需要返回的参数值
- render_template中传递html模板名称,以及参数值
一定要把模板放到正确的
templates
目录下,templates
和app.py
在同级目录下
运行过程:
- 运行到render_template函数时, 程序会自动到templates文件夹下寻找对应名称模板
- render_template将参数传递给Jinja
- Jinja根据参数对模板进行渲染,替换参数,生成html页面
app.py
from flask import Flask, request, render_template
from loguru import logger
app = Flask(__name__)
@app.route('/', methods=['GET'])
def home():
# return '<h1>Welcom to BetterUs<h1>'
return render_template("home.html")
@app.route('/signin', methods=["GET"])
def signin_form():
return render_template("form.html")
@app.route("/signin", methods=['POST'])
def signin():
logger.warning(request.form)
username, password = request.form['username'],request.form['password']
if username == "admin" and password == 'a1234':
return render_template("signin-ok.html", username=username)
return render_template("form.html", message="Bad username or password, username=username")
signin-ok.html
<html>
<head>
<title>Welcome, {{ username }}</title>
</head>
<body>
<p>Welcome, {{ username }}!</p>
</body>
</html>
总结
- 后端的实际作用, 就是接受到http请求,处理后返回响应
- wsgi帮我们解决TCP网络沟通问题, 并解析了HTTP原始请求,返回了我们想要的数据
- Flask帮我们做到了 请求url+请求方法 到处理函数的映射, 让我们可以根据请求编写对应处理函数
- MVC模式帮我们区分了Html代码和Python代码, 更灵活的返回html页面
graph LR browser--请求进入-->Nginx--转发-->WSGI服务器--解析请求-->Flask框架+MVC结构--查询数据-->数据库