目录
Web框架本质
所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端,基于请求做出响应,客户都先请求,服务端做出对应的响应,按照http协议的请求协议发送请求,服务端按照http协议的响应协议来响应请求,这样的网络通信,我们就可以自己实现Web框架了。
请求(网址访问,提交数据等等) request
响应(回复页面,回复数据等等) response
1. 简单版web框架
socket服务端:
# -*- coding:utf-8 -*-
"""
@file : 1.py
@Author : Python
@Date : 2019/9/23 8:21
"""
import socket
server = socket.socket()
server.bind(('127.0.0.1', 9000))
server.listen()
while 1:
conn, addr = server.accept()
from_data = conn.recv(1024)
path = from_data.decode('utf-8').split(' ')[1]
print(path)
conn.send(b'HTTP/1.1 200 ok
')
if path == '/':
with open('1test.html', 'rb') as f:
data = f.read()
elif path == '/csstest.css':
with open('csstest.css', 'rb') as f:
data = f.read()
elif path == '/test.js':
with open('test.js', 'rb') as f:
data = f.read()
elif path == '/ts.jpg':
with open('ts.jpg', 'rb') as f:
data = f.read()
elif path == '/facivon.ico':
# 图标
with open('favicon.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
html文件:1test.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<link rel="stylesheet" href="csstest.css">
<link rel="icon" href="favicon.ico">
</head>
<body>
<div class="d1" style="color: red">欢迎来到24期</div>
<img src="ts.jpg" alt="">
</body>
<script src="test.js"></script>
</html>
css文件: csstest.css
.d1{
background-color: yellow;
}
js文件:test.js
alert("Hello!");
2. 函数式多线程web框架
import socket
from threading import Thread
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen()
def home(conn):
with open('1test.html', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def css(conn):
with open('csstest.css', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def js(conn):
with open('test.js', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def pic(conn):
with open('ts.jpg', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def favicon(conn):
with open('favicon.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
urlpatterns = [('/', home),
('/csstest.css',css),
('/test.js',js),
('/ts.jpg',pic),
('/favicon.ico',favicon)]
while 1:
conn, addr = server.accept()
from_data = conn.recv(1024)
path = from_data.decode('utf-8').split(' ')[1]
print(path)
conn.send(b'HTTP/1.1 200 ok
')
for url in urlpatterns:
if path == url[0]:
t = Thread(target=url[1], args=(conn,))
t.start()
break
3. 分文件web框架
主文件:3test.py
import socket
from threading import Thread
from urls import urlpatterns
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen()
while 1:
conn, addr = server.accept()
from_data = conn.recv(1024)
path = from_data.decode('utf-8').split(' ')[1]
print(path)
conn.send(b'HTTP/1.1 200 ok
')
for url in urlpatterns:
if path == url[0]:
t = Thread(target=url[1], args=(conn,))
t.start()
break
urls.py 文件:
import views
urlpatterns = [('/', views.home),
('/csstest.css', views.css),
('/test.js', views.js),
('/ts.jpg', views.pic),
('/favicon.ico', views.favicon)]
views.py 逻辑文件
def home(conn):
with open('1test.html', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def css(conn):
with open('csstest.css', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def js(conn):
with open('test.js', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def pic(conn):
with open('ts.jpg', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
def favicon(conn):
with open('favicon.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
4. 动态页面web框架
动态网站的意思是里面有动态变化的数据,而不是页面里面有动态效果。(字符串替换)
dongtai.html 文件:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<h1>欢迎%xx%来到xx网站</h1>
</body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</html>
主文件 4test.py
import socket
from threading import Thread
from urls import urlpatterns
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen()
while 1:
conn, addr = server.accept()
from_data = conn.recv(1024)
path = from_data.decode('utf-8').split(' ')[1]
print(path)
conn.send(b'HTTP/1.1 200 ok
')
for url in urlpatterns:
if path == url[0]:
t = Thread(target=url[1], args=(conn,))
t.start()
break
urls.py :
import views
urlpatterns = [('/', views.home),]
views.py : 字符串替换
def home(conn):
username = "alex"
with open('dongtai.html', 'r',encoding='utf-8') as f:
data = f.read()
data = data.replace("%xx%",username)
conn.send(data.encode('utf-8'))
conn.close()
5. 不同html页面(路径)的web框架
主文件同上, 略。
center.html :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<h2>欢迎xx来到个人中心</h2>
</body>
</html>
dongtai.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<h1>欢迎%xx%来到xx网站</h1>
<a href="/center">个人中心</a>
</body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</html>
views.py :
def home(conn):
username = "alex"
with open('dongtai.html', 'r',encoding='utf-8') as f:
data = f.read()
data = data.replace("%xx%",username)
conn.send(data.encode('utf-8'))
conn.close()
def person_center(conn):
with open('center.html', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
urls.py :
import views
urlpatterns = [('/', views.home),
('/center',views.person_center)]
6. wsgiref 模块web框架
wsgiref模块是将整个请求信息给封装起。
主py文件:
from wsgiref.simple_server import make_server
from urls import urlpatterns
def application(environ, start_response):
# environ 所有请求相关的信息
# start_response 封装响应数据格式
print('当前请求路径',environ['PATH_INFO'])
path = environ['PATH_INFO'] #输入地址127.0.0.1:8080,这个打印的是'/',输入的是127.0.0.1:8080/index,打印结果是'/index'
start_response('200 ok', [('Content-Type', 'text/html'),('k1','v1')]) # conn.send(b'HTTP/1.1 200 ok
')
for url in urlpatterns:
if path == url[0]:
ret = url[1]()
return [ret]
if __name__ == '__main__':
h = make_server('127.0.0.1',8080,application)
h.serve_forever()
views.py :
def home():
username = "alex"
with open('4dongtai.html', 'r',encoding='utf-8') as f:
data = f.read()
data = data.replace("%xx%",username).encode('utf-8')
return data
def person_center():
with open('center.html', 'rb') as f:
data = f.read()
return data
def favicon():
with open('favicon.ico', 'rb') as f:
data = f.read()
return data
urls.py :
import views
urlpatterns = [('/', views.home),
('/center',views.person_center),
('/favicon.ico', views.favicon)]
7.jinja2 模板渲染
模板的原理就是字符串替换,只要在HTML页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容。
本质上是HTML内容中利用一些特殊的符号来替换要展示的数据。
下载:
pip install jinja2
主py文件:
import socket
from threading import Thread
from urls import urlpatterns
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen()
while 1:
conn, addr = server.accept()
from_data = conn.recv(1024)
path = from_data.decode('utf-8').split(' ')[1]
print(path)
conn.send(b'HTTP/1.1 200 ok
')
for url in urlpatterns:
if path == url[0]:
t = Thread(target=url[1], args=(conn,))
t.start()
break
views.py :
from jinja2 import Template
def home(conn):
with open('jinja2test.html','r',encoding='utf-8') as f:
data = f.read()
t = Template(data)
ret = t.render({'hobby':['喝酒', '抽烟','女人']})
conn.send(ret.encode('utf-8'))
conn.close()
def favicon(conn):
with open('favicon.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
urls.py 文件:
import views
urlpatterns = [('/', views.home),
('/favicon.ico', views.favicon)]
jinja2test.html 文件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<h1>个人爱好</h1>
<ul>
{% for i in hobby %}
<li>{{ i }}</li>
{% endfor %}
</ul>
</body>
</html>