一、初识web框架
一、手写简易web框架
1. 获取输入网址后缀
conn, addr = server.accept()
data = conn.recv(1024)
data = data.decode('utf-8')
current_path = data.split('\r\n')[0].split(' ')[1]
print(current_path)
conn.send(b'HTTP/1.1 200 ok\r\n\r\nhello world')
conn.close()
2. 根据不同后缀返回不同结果
conn, addr = server.accept()
data = conn.recv(1024)
data = data.decode('utf-8')
current_path = data.split('\r\n')[0].split(' ')[1]
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
if current_path == '/index':
conn.send(b'index')
elif current_path == '/login':
conn.send(b'login')
else:
conn.send(b'hello world')
conn.close()
-
根据不同后缀返回不同HTML页面
conn, addr = server.accept()
data = conn.recv(1024)conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
data = data.decode('utf-8')
current_path = data.split('\r\n')[0].split(' ')[1]if current_path == '/index':
with open(r'a.html', 'rb') as f: conn.send(f.read())
elif current_path == '/login':
with open(r'b.html', 'rb') as f:
conn.send(f.read())else:
conn.send(b'hello world')
conn.close()
二、wsgiref实现简易web框架
1. 往浏览器窗口返回固定值
from wsgiref.simple_server import make_server
def run(env, response):
print(env)
response('200 ok', [])
return [b'hello world']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever()
2. 获取输入后缀
from wsgiref.simple_server import make_server
def run(env, response):
response('200 ok', [])
current_path = env.get('PATH_INFO')
print(current_path)
return [b'hello world']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever()
3. 根据不同后缀返回不同结果
from wsgiref.simple_server import make_server
def run(env, response):
response('200 ok', [])
current_path = env.get('PATH_INFO')
if current_path == '/index':
return [b'index']
elif current_path == '/login':
return [b'login']
return [b'404 error']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever()
4. 根据不同后缀调用不同函数处理
from wsgiref.simple_server import make_server
def index(env):
return 'index'
def login(env):
return 'login'
def errors(env):
return '404'
urls = [
('/index', index),
('/login', login)
]
def run(env, response):
response('200 ok', [])
current_path = env.get('PATH_INFO')
func = None
for url in urls:
if url[0] == current_path:
func = url[1]
break
if func:
res = func(env)
else:
res = errors(env)
return [res.encode('utf_8')]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever()
5. 将不同功能封装在不同模块中
a. main
from views import *
from urls import urls
from wsgiref.simple_server import make_server
def run(env, response):
response('200 ok', [])
current_path = env.get('PATH_INFO')
func = None
for url in urls:
if url[0] == current_path:
func = url[1]
break
if func:
res = func(env)
else:
res = errors(env)
return [res.encode('utf_8')]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever()
b. views(视图函数)
def index(env):
return 'index'
def login(env):
return 'login'
def errors(env):
return '404'
c. urls(路由与视图函数的对应关系)
from views import *
urls = [
('/index', index),
('/login', login)
]
三、让页面展示当前时间
1. 在urls中添加对应关系
urls = [
('/index', index),
('/login', login),
('/get_time', get_time),
]
2. 在templates中编写名为get_time的HTML模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
$$time$$
</body>
</html>
3. 在view中添加获取时间功能,将结果替换掉HTML页面中的字段。
def get_time(env):
current_time = datetime.now().strftime('%Y-%m-%d %X')
with open(r'templates/get_time.html', 'r', encoding='utf-8') as f:
data = f.read()
data = data.replace("$$time$$", current_time)
return data
四、让页面展示字典
1. 在urls中添加对应关系
urls = [
('/index', index),
('/login', login),
('/get_time', get_time),
('/get_user', get_user),
]
2. 在templates中编写名为get_time的HTML模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<p>{{data}}</p>
<p>{{data['username']}}</p>
<p>{{data.password}}</p>
<p>{{data.get('hobby')}}</p>
</body>
</html>
3. 在views中导入jinja2模块,添加获取字典功能
from jinja2 import Template
def get_user(env):
user_dict = {'username': 'byx', 'password': '123', 'hobby': ['read', 'game', 'running']}
with open(r'templates/get_user.html', 'r', encoding='utf-8') as f:
data = f.read()
temp = Template(data)
res = temp.render(data=user_dict)
return res
五、动态展示数据库
1. 在urls中添加对应关系
urls = [
('/index', index),
('/login', login),
('/get_time', get_time),
('/get_user', get_user),
('/get_db', get_db)
]
2. 在templates中编写名为get_db的HTML模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">用户数据展示</h2>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>id</th>
<th>username</th>
<th>password</th>
</tr>
</thead>
<tbody>
{%for user_dict in user_list%}
<tr>
<td>{{user_dict.id}}</td>
<td>{{user_dict.name}}</td>
<td>{{user_dict.password}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
3. 在views中导入pymysql模块,连接数据库。通过jinja2模块导入get_db模板。
import pymysql
def get_db(env):
conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
password = '123',
database = 'test',
charset = 'utf8',
autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql = 'select * from userinfo'
affect_rows = cursor.execute(sql)
data = cursor.fetchall()
with open(r'templates/get_db.html', 'r', encoding='utf-8') as f:
data1 = f.read()
temp = Template(data1)
res = temp.render(user_list=data)
return res
六、总结
1. 手写web框架
1. 手动书写socket代码
2. 手动处理HTTP数据
2. 基于wsgiref模块帮助我们处理socket以及HTTP数据
wsgiref模块
1. 请求来的时候,解析HTTP数据,打包成字典传输过来,便于操作各项数据。
2. 响应走的时候,自动将数据打包成符合HTTP协议格式的样子,返回给前端。
3. 封装路由与视图函数的对应关系,以及视图函数文件
1. urls.py
路由与视图函数对应关系
2. views.py
视图函数(视图函数不单单指函数,也可以是类)
3. templates
模板文件夹
4. 基于jinja2实现模板的渲染
后端生成好数据,通过某种方式传递给前端页面使用(前端页面可以基于模板语法更加快捷简便使用后端传过来的数据
5. 动静态网页
1. 静态网页
数据是写死的,万年不变
2. 动态网页
数据动态获取
比如:
1. 后端实时获取当前时间给前端页面渲染
2. 后端从数据库获取数据给前端页面渲染