web框架
web应用本质
在我们之前的网络编程中,有学过三种架构,单机架构,C/S架构和B/S架构
- socket网络编程:
- 架构:C/S架构
- 协议:TCP/UDP协议
- OSI七层:传输层
- web应用:
- 架构:B/S架构
- 协议:Http协议
- OSI七层:应用层
web框架的分类
web框架包含了三部分
a. socket服务端,进行网络通讯
b. 路由系统,进行url映射到具体的功能
c. 模板引擎渲染
1. 自己定义的规则
2. 使用第三方的工具
web框架分类
第一种维度的分类:
- socket服务端,路由系统,模板引擎全部是自己完成,如tornado
- socket服务端调用第三方,路由系统和模板引擎自己完成,如django(wsgiref/uwsgi)
- socket服务端和模板引擎引入第三方,路由系统自己完成,如flask
第二种维度的分类:
- Django,功能强大,适合做大批量前端网页开发,里面包含了ORM框架,session,form表单验证等功能
- 其他类型,适合用于前端页面较少的开发,比如一些轻量级框架,flask、tornado
Http协议
Http协议也是遵循请求响应模型的,在发出请求时包含了请求头,请求体,客户端响应时也包含了响应头,响应体
- 请求头:主要包含了请求的方式(get/post),http协议版本,网络地址……,这里面最主要的就是下面的
**
的内容GET /** HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
- 请求体:请求的内容,如
jdkvgfb
- 响应头:主要包含了http协议版本,状态码(200表示请求成功),OK,如
HTTP/1.1 200 OK
- 响应体:就是展现给用户的内容,如
"hello world"
路由系统
将客户端请求的url映射到相应的函数,然后调用函数就可以获取内容
自定制的web框架案例
import socket
import time
import pymysql
from jinja2 import Template
# 建立数据库连接
def mysql(sql):
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='t2'
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute(sql)
data = cursor.fetchall()
return data
# 读取html文件内容
def read_html(filepath):
with open(filepath, 'r', encoding='utf-8') as fr:
data = fr.read()
return data
# 直接返回内容
def f1():
return 'xxxxxx'
# 返回一个html页面,但不对html页面进行操作
def index():
filepath = 'time.html'
return read_html(filepath)
# 通过占位符将动态内容添加到html页面中
def times():
filepath = 'time.html'
data = read_html(filepath)
ctime = time.strftime('%Y-%m-%d %X')
data = data.replace('@@content@@', ctime)
return data
# 从数据库中取出数据返回到页面中
def user():
sql = 'select * from user'
users = mysql(sql)
user_list = []
for user in users:
user_list.append(f"<tr><td>{user['id']}</td><td>{user['name']}</td><td>{user['age']}</td></tr>")
user_str = ''.join(user_list)
res = read_html("user.html")
data = res.replace("@@content@@", user_str)
return data
# 通过jinja2第三方库操作
def user1():
sql = 'select * from user'
users = mysql(sql)
res = read_html("user1.html")
template = Template(res)
data = template.render(users=users)
return data
# 路由系统
routes = [
('/index', index),
('/xxx', f1),
('/time', times),
('/user', user),
('/user1', user1),
]
# 建立通信
def run():
server = socket.socket()
server.bind(('127.0.0.1', 9504))
server.listen(5)
print('strat...')
while True:
# 建立连接
conn, _ = server.accept()
# 获取请求数据
req = conn.recv(1024)
# print(req)
data = str(req, encoding='utf-8')
# print(data)
url = data.split(' ')[1]
# print(url)
# 获取功能名字,实现不同请求返回不同内容
for item in routes:
if item[0] == url:
func_name = item[1]
break
else:
func_name = None
# 获取响应内容
if func_name:
resp = func_name()
else:
resp = '<h1 style="text-align: center; color: red;">404 not found</h1><hr>'
# 发送响应数据
conn.send(bytes("HTTP/1.1 200 OK\r\n\r\n", encoding="utf-8"))
conn.send(bytes(resp, encoding="utf-8"))
conn.close()
if __name__ == '__main__':
run()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>静态HTML页面</title>
<style>
/*h1 {*/
/*text-align: center;*/
/*color: red;*/
/*}*/
</style>
</head>
<body>
<h1>这个页面不需要进行修改</h1>
</body>
</html>
time.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>实时显示时间</title>
</head>
<body>
现在时间为:@@content@@
</body>
</html>
user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手撸HTML</title>
<style>
h1 {
text-align: center;
}
table {
height: 200px;
width: 300px;
font-size: 20px;
text-align: center;
}
</style>
</head>
<body>
<h1>不借助第三方库进行表格显示</h1>
<table border="1" cellspacing="0">
<tbody>
<tr style="background: #73a4cc; font-size: 30px;">
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
@@content@@
</tbody>
</table>
</body>
</html>
user1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非手撸</title>
<style>
h1 {
text-align: center;
}
table {
height: 100px;
width: 150px;
font-size: 14px;
text-align: center;
}
</style>
</head>
<body>
<h1>借助jinja2库进行内容输入</h1>
<table border="1" cellspacing="0">
<tbody>
<tr style="background: #73a4cc; font-size: 20px;">
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
{% for item in users %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>