Web框架
web框架
- http协议&TCP协议
- web框架
- Django请求的生命周期
- MVC 和 MTV 模式
http协议&TCP协议
http协议
每一次 请求-响应 后都会断开连接,不记录状态
- HTTP 协议基于请求-响应模式
- HTTP /1.0默认使用的是短链接 (浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接)
- HTTP是无状态协议 (协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系)
TCP协议
- TCP协议使用的是长连接 (当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接)
- TCP协议的封装产物是socket (socket是长连接,理论上客户端和服务器端一旦建立连接将不会主动断开此连接)
web框架
web框架的本质
我们可以通过socket模拟http协议,模拟过程如下:
-
浏览器请求:发送请求头、请求体给服务端
-
请求头:中可以是GET请求\POST请求
-
请求体:POST请求内容
-
-
服务端响应:发送响应头、响应体给浏览器
-
响应头:200 OK
-
响应体:浏览器可解析的"字符串"数据
-
-
断开连接
-
请求体中,请求内容:
- 要访问的url
-
响应体中,"字符串"形成过程:
- 获取请求的url
- 调取数据库数据
- 使用html模版
- html模版嵌套数据库中的数据形成"字符串"
根据模拟过程,得出结论Web应用的本质就是:
socket服务+socket客户端(浏览器)
web框架组成
根据分析web框架的本质,可以得知实现web框架需要满足以下几个条件:
【1】. socket:作为服务端提供socket服务
【2】. 路由系统:根据URL返回不同的内容 (ULR对应函数)
【3】. 前端模版引擎:HTML模版+数据=‘字符串’(视图函数用于模版拼接数据过程)
web框架分类
框架分类可以根据框架功能分类:
- 包括【1】、【2】、【3】的框架有Tornado
- 包括【2】、【3】的框架有Django,可以配合wsgiref替代【1】(WSGI是Web Server Gateway Interface,python标准库提供的独立WSGI服务器称为wsgiref)
- 包括【2】的框架有flask,【1】【3】使用三方工具
web框架介绍
Django
- 路由系统(url与函数对应)
- 视图(业务逻辑views)
- html模版
- ORM(类对应表,对象对应行)或pymql
Torando
- 路由系统
- 视图(业务逻辑views)
- html模版
- pymql 或 SqlAchemy
Flask
- 路由系统
- 视图(业务逻辑views)
- html模版(三方组件)
- pymql 或 SqlAchemy
自定义web框架
首先,安装基于第三方工具实现的模板渲染
pip3 install jinja2
服务端py代码
import socket
import pymysql
from jinja2 import Template
def host(request):
# 利用pymysql创建数据库连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='sqlexam')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select id,name,email,user_type_id from users")
user_list = cursor.fetchall()
cursor.close()
f = open('hostlist.html', 'r', encoding='utf8')
data = f.read()
f.close()
# 基于第三方工具实现的模板渲染
template = Template(data)
data = template.render(userList=user_list, msg='this is msg')
return data.encode('utf8')
# 模拟路由系统
routers = [
('/host.html', host),
]
# socket服务
def run():
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 8085))
sock.listen(5)
while True:
conn, addr = sock.accept()
data = conn.recv(8096)
# 处理请求头,请求体
data = str(data, encoding='utf8')
headers, bodys = data.split('\r\n\r\n') # 分隔请求头和请求体
temp_list = headers.split('\r\n') # 分隔第一行
method, url, protocal = temp_list[0].split(' ') # 分隔请求method,url等
# 发送响应头
conn.send(b"HTTP/1.1 200 OK \r\n\r\n")
func_name = None
for item in routers:
if item[0] == url:
func_name = item[1]
break
if func_name:# 调用路由系统
response = func_name(data)
else:
response = b'404'
# 发送响应体
conn.send(response)
sock.close()
if __name__ == '__main__':
run()
hostlist.html
<body>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>用户类型</th>
</tr>
</thead>
<tbody>
{% for row in userList %}
<tr>
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.email}}</td>
<td>{{row.user_type_id}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{msg}}
</body>
Django请求的生命周期
WSGI(Web Server Common Interface)是专门为Python语言制定的web服务器与应用程序之间的网关接口规范
web框架的本质是socket,在socket的基础之上实现一系列的功能
,Django也是如此。
Django本身并没有socket,需要应用别人的socket,默认使用wsgiref模块,所以当前的web框架是swgiref+django
为了效率更高,生产环境使用的是uwsgi+django
wsgiref+Django请求的生命周期
from wsgiref.simple_server import make_server
def RunServer(environ, start_response): # environ请求相关参数,start_response响应相关参数(容器)
# 以上都是wsgiref的工作,wsgiref将请求信息处理过后,以下才是django的工作内容
# 1中间件
# 2路由系统
# 3视图函数
# 4数据库模版引擎渲染
# 5返回渲染好的‘字符串’给中间件
# 6返回给wsgiref
# 到此Django一次生命周期结束
start_response('200 OK', [('Content-Type', 'text/html')]) # 拿到响应头
return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ] # 拿到响应体,返回用户
if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8000, RunServer)
httpd.serve_forever() # 循环监听端口
MVC 和 MTV 模式
MVC
models(数据库,模型)
views(html模板)
controllers(业务逻辑处理)
MTV
models(数据库,模型)
templates(html模板)
views(业务逻辑处理)
Django属于MTV模式