一.Web框架
1.框架(framework):特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,简单地说,就是用别人搭建好的舞台来表演;使用框架可以帮你快速开发特定的系统
2.对所有Web应用来说,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端
import socket
def handle_request(client):
buf=client.recv(1024)
client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))
def main():
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind(('localhost',8001))
sock.listen(5)
while True:
connection,address=sock.accept()
handle_request(connection)
connection.close()
if __name__ == '__main__':
main()
3.为何需要Web框架:将常用功能(HTTP请求,解析HTTP请求,发送HTTP响应)封装,简化工作,无需每次都自己去实现底层代码
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回
如果要动态生成HTML,就需要自己实现上述步骤;不过,接受HTTP请求,解析HTTP请求,发送HTTP响应都是苦力活;如果自己来写这些底层代码,过于复杂
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档;因为我们不希望接触TCP连接/HTTP原始请求/响应格式,所以需要1个统一接口,让我们专心用Python编写Web业务
这个接口就是WSGI(Web Server Gateway Interface,Web服务器网关接口),该协议指定了Web服务器和Python Web应用/Web框架之间的标准接口,以提高Web应用在一系列Web服务器间的移植性
- WSGI是一套接口标准协议/规范
- 通信(作用)区间是Web服务器和Python Web应用程序之间
- 目的是制定标准,以保证不同Web服务器可以和不同的Python程序之间相互通信
二.1个最简单的Web框架
from wsgiref.simple_server import make_server
#wsgiref是python内置的服务器模块,进行HTTP解析
import time
def f1(req):#视图函数
print(req)
print(req["QUERY_STRING"])
f1=open("index1.html","rb")
data1=f1.read()
return [data1]
def f2(req):
f2=open("轮播图.html", "rb")
data2=f2.read()
return [data2]
def f3(req):#模版以及数据库
f3=open("index3.html","rb")
data3=f3.read()
times=time.strftime("%Y-%m-%d %X",time.localtime())
data3=str(data3,"utf8").replace("!time!",str(times))
return [data3.encode("utf8")]
def login(req):
print(req[QUERY_STRING])#结果为提交的用户名/密码的键值对
return b"welcome"
def show_time(req):
times=time.ctime()
#return ("<h1>%s</h1>"%str(times)).encode("utf-8")
f=open("show_time.html","rb")
data=f.read()
data=data.decode("utf-8")
data=data.replace("{{time}}",str(times))#将文件数据中的{{time}}替换为times
#相当于自定义了一种语法,{{..}}部分均被替换
return data.encode("utf-8")
def routers():
urlpatterns=(
('/yuan',f1),
('/alex',f2),
("/cur_time",f3),
("/login",login),
("show_time",show_time)
)
return urlpatterns
def application(environ,start_response):
#environ就是服务器打包好的请求对象,是1个dict
print(environ['PATH_INFO'])
#PATH_INFO是URL中不存在的部分(IP与端口之后的部分;非请求体)
#如URL为127.0.0.1:8080/G/programm,PATH_INFO为/G/programm
path=environ['PATH_INFO']
start_response('200 OK',[('Content-Type','text/html')])
#200 OK为状态码;list为请求头,每个键值对构成1个tuple
urlpatterns=routers()
func=None
for item in urlpatterns:
if item[0]==path:
func=item[1]
break
if func:
return [func(environ)]#返回值作为响应体被发送给浏览器
else:
return ["<h1>404</h1>".encode("utf8")]
httpd = make_server('',8080,application)
#参数依次为IP地址,端口,处理请求的函数
print('Serving HTTP on port 8084...')
# 开始监听HTTP请求:
httpd.serve_forever()
#卡住,直到有客户端进行连接,执行application()
- login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8080/login" method="get">
<!--GET方式可以访问不同源(协议+域名(IP+端口))数据;(访问)该文件使用的是另1个端口,非8080,不同源-->
<!--提交到服务端,服务端environ参数为login(),服务端调用login(),浏览器获得返回值并显示-->
<p>用户名<input type="text" name="user"></p>
<p>密码<input type="password" name="pwd"></p>
<p><input type="submit">提交</p>
</form>
</body>
</html>
- show_time.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>时间:{{time}}</h1>
<!--相当于自定义了一种语法,{{..}}部分均被替换-->
</body>
</html>
- 注意:
整个application()没有涉及任何解析HTTP的部分
也就是说,底层代码不需要自己编写,我们只负责在更高层次上考虑如何响应请求
application()必须由WSGI服务器来调用
有很多符合WSGI规范的服务器,可以挑选一个来用
Python内置了一个WSGI服务器,这个模块叫wsgiref
application()就是符合WSGI标准的一个HTTP处理函数,接收两个参数:
environ:1个包含所有HTTP请求信息的dict对象
start_response:1个发送HTTP响应的函数
在application()函数中,调用:
start_response('200 OK', [('Content-Type', 'text/html')])
就发送了HTTP响应的Header
注意Header只能发送一次,也就是只能调用1次start_response()
start_response()函数接收两个参数:
1个是HTTP状态码
1个是1组list表示的HTTP Header,每个Header用1个包含2个str的tuple表示
通常情况下,都应该把Content-Type头发送给浏览器
其他很多常用的HTTP Header也应该发送
然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器
有了WSGI,我们关心的就是如何从environ拿到HTTP请求信息
然后构造HTML,通过start_response()发送Header,最后返回Body
三.MVC和MTV模式
1.MVC模式
- 把Web应用分为模型(Model),控制器(Controller),视图(View)三层
- 他们之间以一种插件似的,松耦合的方式连接在一起
- Model负责业务对象与数据库的对象(ORM);View负责与用户的交互(页面;HTML文件);Controller接受用户的输入调用模型和视图,完成用户的请求(视图函数)
2.MTV模式(Django的模式)
- 本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同;把Web应用分为模型(Model),模版(Template),视图(View)三层
- Model负责业务对象与数据库的对象(ORM);Template负责如何把页面展示给用户(HTML文件);View负责业务逻辑,并在适当的时候调用Model和Template(视图函数)
- Django还有一个URL分发器,作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template