web框架
是一个为web服务器提供服务的应用程序,负责处理用户的动态资源请求。
静态资源:不需要经常变换的资源,png/jpg/css/js等。
动态资源:根据不同的条件进行筛选,获取的数据也不同。
WSGI协议
web服务器和web框架之间进行协同工作的一个规则。
使用web框架搭建网站案例
要求:python搭建静态web服务器,使用web框架处理动态资源访问,使用路由列表和装饰器,使用模板返回页面结构,使用ajax处理局部页面数据刷新,使用logging处理日志信息。
目录结构如下:
静态资源
jquery官网下载
favicon.icon是网站的小图标,网站会自动发请求获取,没有会报错,找个jpg图片重命名一下
静态资源通过http://localhost:8080/静态文件名(如1.jpg)访问
动态资源通过http://localhost:8080/xxx.html(如index.html)访问
数据库备份:
链接:https://pan.baidu.com/s/1CqKG0YIez2vFyHOhXxtS2A
提取码:yy8s
数据库连接:
主机地址:localhost
user:root
password:root
端口:3306
代码如下
server.py
import logging
import socket
import threading
import dynamic.frame
def handle_client(client_socket, ip):
print(str(ip) + "访问")
client_request_data = client_socket.recv(1024).decode()
requests_data = client_request_data.split(" ")
if len(requests_data) == 1:
client_socket.close()
return
requests_path = requests_data[1]
print(requests_path)
if requests_path == "/":
requests_path = "/index.html"
if requests_path.endswith(".html"):
logging.info("动态资源"+requests_path)
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "content-type: text/html; charset=utf-8\r\n"
response_body = dynamic.frame.application(requests_path)
response_data = (response_line + response_header + "\r\n" + response_body).encode()
client_socket.send(response_data)
client_socket.close()
else:
logging.info("静态资源"+requests_path)
try:
with open("./static/" + requests_path, 'rb') as f:
file_data = f.read()
except Exception as e:
logging.error("访问静态资源错误路径:" + str(e))
reponse_line = "HTTP/1.1 404 NOT FOUND\r\n"
response_header = "Server:pwb\r\n"
reponse_body = "404 NOT FOUND"
response_data = (reponse_line + response_header + "\r\n" + reponse_body).encode()
client_socket.send(response_data)
else:
response_line = "HTTP/1.1 200 OK\r\n"
response_header = "Server:pwb\r\n"
response_body = file_data
response_data = (response_line + response_header + "\r\n").encode() + response_body
client_socket.send(response_data)
finally:
client_socket.close()
if __name__ == '__main__':
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("", 8080))
tcp_server_socket.listen(128)
while True:
client_socket, client_addr = tcp_server_socket.accept()
client_thread = threading.Thread(target=handle_client, args=(client_socket, client_addr,))
client_thread.start()
tcp_server_socket.close()
frame.py
import json
import logging
import pymysql
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s-%(filename)s[line:%(lineno)d]-%(levelname)s:%(message)s',
filename='log.txt',
filemode="a",
encoding="utf-8"
)
func_list = {}
def route(data):
def func_out(func):
func_list[data] = func
def func_inner():
pass
return func_inner
return func_out
@route("/index.html")
def index():
with open("./template/index.html", "rb") as f:
file_data = f.read()
conn = pymysql.connect(host="localhost",
port=3306,
database="gyq",
user="root",
password="root",
charset="utf8")
cursor = conn.cursor()
sql = "select * from students"
cursor.execute(sql)
studentinfo = cursor.fetchall()
# (1, 'gyq', 20, '女', '120', datetime.datetime(2022, 2, 4, 18, 16, 32), 1)
template = """<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>
"""
html = ''
for i in studentinfo:
html += template % (i[0], i[1], i[2], i[3], i[4], i[5], i[6],)
content = file_data.decode().replace("biaoji", html)
cursor.close()
conn.close()
return content
@route("/weather.html")
def weather():
with open("./template/weather.html", "rb") as f:
file_data = f.read()
content = file_data.decode()
return content
@route("/search.html")
def search():
with open("./template/search.html", "rb") as f:
file_data = f.read()
content = file_data.decode()
return content
@route("/search_data.html")
def search_data():
conn = pymysql.connect(host="localhost",
port=3306,
database="gyq",
user="root",
password="root",
charset="utf8"
)
cursor = conn.cursor()
sql = "SELECT " \
"students.stu_num,students.stu_name,students.stu_age,students.stu_gender," \
"students.stu_tel,students.cid,classes.`class_name`,classes.`class_size` " \
"FROM students INNER JOIN classes ON students.`cid`=classes.`class_id`;"
cursor.execute(sql)
data = cursor.fetchall()
# (1, 'gyq', 20, '女', '120', 1, '1912', 50)
data_list = [{
"code": row[0],
"name": str(row[1]),
"age": row[2],
"gender": str(row[3]),
"tel": str(row[4]),
"cid": row[5],
"cname": str(row[6]),
"csize": row[7],
} for row in data]
json_str = json.dumps(data_list)
return json_str
cursor.close()
conn.close()
def error():
return "404 error"
def application(requests_path):
try:
func = func_list[requests_path]
return func()
except Exception as e:
logging.error("访问动态资源错误路径:" + str(e))
return error()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GYQ的网站</title>
<style>
body{
text-align: center;
}
h1{
color: blue;
}
table{
margin: auto;
border: 1px solid black;
border-collapse: collapse;
width: 1400px;
}
th{
border: 1px dashed red;
width: 200px;
}
td{
border: 1px dashed red;
width: 200px;
}
#btn1{
float:left;
margin-left:500px;
}
#btn2{
float:right;
margin-right:500px;
}
</style>
<script>
function jump(){
window.location.href="http://localhost:8080/weather.html"
}
function jump2(){
window.location.href="http://localhost:8080/search.html"
}
</script>
</head>
<body>
<h1>学生信息汇总</h1>
<hr>
<table>
<tr>
<th>学生id</th>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>学生电话</th>
<th>入学日期</th>
<th>班级id</th>
</tr>
biaoji
</table>
<div>
<input type="button" value="查询天气" onclick="jump()" id="btn1">
<input type="button" value="分类查询" onclick="jump2()" id="btn2">
</div>
</body>
</html>
search.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GYQ的网站</title>
<style>
body{
text-align: center;
}
h1{
color: blue;
}
table{
margin: auto;
border: 1px solid black;
border-collapse: collapse;
width: 1400px;
}
th{
border: 1px dashed red;
width: 200px;
}
td{
border: 1px dashed red;
width: 200px;
}
</style>
<script src="./jquery.min.js"></script>
<script>
$(document).ready(function(){
$.get("/search_data.html",function(response){
var $table=$("table");
for(var i = 0;i<response.length;i++){
var oData=response[i];
var oTr='<tr>'+
'<td>'+oData.code+'</td>'+
'<td>'+oData.name+'</td>'+
'<td>'+oData.age+'</td>'+
'<td>'+oData.gender+'</td>'+
'<td>'+oData.tel+'</td>'+
'<td>'+oData.cid+'</td>'+
'<td>'+oData.cname+'</td>'+
'<td>'+oData.csize+'</td>'+
'</tr>';
$table.append(oTr);
}
},"json");
});
function jump(){
window.location.href="http://localhost:8080/index.html"
}
</script>
</head>
<body>
<h1>学生及班级信息查询</h1>
<hr>
<table>
<tr>
<th>学生id</th>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>学生电话</th>
<th>班级id</th>
<th>班级名</th>
<th>班级人数</th>
</tr>
</table>
<input type="button" value="返回首页" onclick="jump()" id="btn1">
</body>
</html>