博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python小白-day15 web框架
阅读量:5089 次
发布时间:2019-06-13

本文共 7787 字,大约阅读时间需要 25 分钟。

Web框架本质

众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python3
#coding:utf8
import
socket
def
handle_request(client):
    
#接收请求
    
buf
=
client.recv(
1024
)
    
print
(buf)
    
#返回信息
    
client.send(bytes(
'<h1>welcome liuyao webserver</h1>'
,
'utf8'
))
def
main():
    
#创建sock对象
    
sock
=
socket.socket()
    
#监听80端口
    
sock.bind((
'localhost'
,
8000
))
    
#最大连接数
    
sock.listen(
5
)
    
print
(
'welcome nginx'
)
    
#循环
    
while
True
:
        
#等待用户的连接,默认accept阻塞当有请求的时候往下执行
        
connection,address
=
sock.accept()
        
#把连接交给handle_request函数
        
handle_request(connection)
        
#关闭连接
        
connection.close()
if
__name__
=
=
'__main__'
:
    
main()

上述通过socket来实现了其本质,而对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。

python标准库提供的独立WSGI服务器称为wsgiref。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
#coding:utf-8
#导入wsgi模块
from
wsgiref.simple_server
import
make_server
 
def
RunServer(environ, start_response):
    
start_response(
'200 OK'
, [(
'Content-Type'
,
'text/html'
)])
    
return
[bytes(
"welcome webserver"
.encode(
'utf8'
))]
 
if
__name__
=
=
'__main__'
:
    
httpd
=
make_server('',
8000
, RunServer)
    
print
(
"Serving HTTP on port 8000..."
)
    
httpd.serve_forever()
    
#接收请求
    
#预处理请求(封装了很多http请求的东西)

请求过来后就执行RunServer这个函数。

原理图:

866894-20160506214500279-535873608.jpg

当用户发送请求,socket将请求交给函数处理,之后再返回给用户。

自定义Web框架

一、框架

python标准库提供的wsgiref模块开发一个自己的Web框架

之前的使用wsgiref只能访问一个url

下面这个可以根据你访问的不同url请求进行处理并且返回给用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
#coding:utf-8
from
wsgiref.simple_server
import
make_server
def
RunServer(environ, start_response):
    
start_response(
'200 OK'
, [(
'Content-Type'
,
'text/html'
)])
    
#根据url的不同,返回不同的字符串
    
#1 获取URL[URL从哪里获取?当请求过来之后执行RunServer,
    
#wsgi给咱们封装了这些请求,这些请求都封装到了,environ & start_response]
    
request_url
=
environ[
'PATH_INFO'
]
    
print
(request_url)
    
#2 根据URL做不同的相应
    
#print environ #这里可以通过断点来查看它都封装了什么数据
    
if
request_url
=
=
'/login'
:
        
return
[bytes(
"welcome login"
,
'utf8'
)]
    
elif
request_url
=
=
'/reg'
:
        
return
[bytes(
"welcome reg"
,
'utf8'
)]
    
else
:
        
return
[bytes(
'<h1>404! no found</h1>'
,
'utf8'
)]
 
if
__name__
=
=
'__main__'
:
    
httpd
=
make_server('',
8000
, RunServer)
    
print
(
"Serving HTTP on port 8000..."
)
    
httpd.serve_forever()

当然 以上虽然根据不同url来进行处理,但是如果大量url的话,那么代码写起来就很繁琐。
所以使用下面方法进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env python
#coding:utf-8
from
wsgiref.simple_server
import
make_server
def
index():
    
return
[bytes(
'<h1>index</h1>'
,
'utf8'
)]
def
login():
    
return
[bytes(
'<h1>login</h1>'
,
'utf8'
)]
def
reg():
    
return
[bytes(
'<h1>reg</h1>'
,
'utf8'
)]
def
layout():
    
return
[bytes(
'<h1>layout</h1>'
,
'utf8'
)]
#定义一个列表 把url和上面的函数做一个对应
urllist
=
[
    
(
'/index'
,index),
    
(
'/login'
,login),
    
(
'/reg'
,reg),
    
(
'/layout'
,layout),
]
def
RunServer(environ, start_response):
    
start_response(
'200 OK'
, [(
'Content-Type'
,
'text/html'
)])
    
#根据url的不同,返回不同的字符串
    
#1 获取URL[URL从哪里获取?当请求过来之后执行RunServer,wsgi给咱们封装了这些请求,这些请求都封装到了,environ & start_response]
    
request_url
=
environ[
'PATH_INFO'
]
    
print
(request_url)
    
#2 根据URL做不同的相应
    
#print environ #这里可以通过断点来查看它都封装了什么数据
    
#循环这个列表 找到你打开的url 返回url对应的函数
    
for
url
in
urllist:
        
if
request_url
=
=
url[
0
]:
            
return
url[
1
]()
    
else
:
        
#url_list列表里都没有返回404
        
return
[bytes(
'<h1>404 not found</h1>'
,
'utf8'
)]
if
__name__
=
=
'__main__'
:
    
httpd
=
make_server('',
8000
, RunServer)
    
print
(
"Serving HTTP on port 8000..."
)
    
httpd.serve_forever()

2、模板引擎

在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以我们一般将要返回给用户的HTML写在指定文件中,然后再返回。如:

index:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<
html
>
<
head
lang
=
"en"
>
    
<
meta
charset
=
"UTF-8"
>
    
<
title
></
title
>
</
head
>
<
body
>
    
<
h1
>Index</
h1
>
 
</
body
>
</
html
>

login:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<
html
>
<
head
lang
=
"en"
>
    
<
meta
charset
=
"UTF-8"
>
    
<
title
></
title
>
</
head
>
<
body
>
    
<
form
>
        
<
input
type
=
"text"
/>
        
<
input
type
=
"text"
/>
        
<
input
type
=
"submit"
/>
    
</
form
>
</
body
>
</
html
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python  
#coding:utf-8
from
wsgiref.simple_server
import
make_server
def
index():
    
#把index页面读进来返回给用户
    
indexfile
=
open
(
'index.html'
,
'r+'
).read()
    
return
[bytes(indexfile,
'utf8'
)]
def
login():
    
loginfile
=
open
(
'login.html'
,
'r+'
).read()
    
return
[bytes(loginfile,
'utf8'
)]
urllist
=
[
    
(
'/login'
,login),
    
(
'/index'
,index),
]
def
RunServer(environ, start_response):
    
start_response(
'200 OK'
, [(
'Content-Type'
,
'text/html'
)])
    
#根据url的不同,返回不同的字符串
    
#1 获取URL[URL从哪里获取?当请求过来之后执行RunServer,wsgi给咱们封装了这些请求,这些请求都封装到了,environ & start_response]
    
request_url
=
environ[
'PATH_INFO'
]
    
print
(request_url)
    
#2 根据URL做不同的相应
    
#print environ #这里可以通过断点来查看它都封装了什么数据
    
for
url
in
urllist:
        
#如果用户请求的url和咱们定义的rul匹配
        
if
request_url
=
=
url[
0
]:
            
#执行
            
return
url[
1
]()
    
else
:
        
#url_list列表里都没有返回404
        
return
[bytes(
'<h1>404 not found</h1>'
,
'utf8'
)]
if
__name__
=
=
'__main__'
:
    
httpd
=
make_server('',
8000
, RunServer)
    
print
(
"Serving HTTP on port 8000..."
)
    
httpd.serve_forever()

对于上述代码,虽然可以返回给用户HTML的内容以现实复杂的页面,但是还是存在问题:如何给用户返回动态内容?

  • 自定义一套特殊的语法,进行替换

  • 使用开源工具jinja2,遵循其指定语法

index:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
    
<
meta
charset
=
"UTF-8"
>
    
<
title
>Title</
title
>
</
head
>
<
body
>
    
<!--general replace-->
    
<
h1
>{
{ name }}</
h1
>
    
<
h1
>{
{ age }}</
h1
>
    
<
h1
>{
{ time }}</
h1
>
 
    
<!--for circular replace-->
    
<
ul
>
        
{% for item in user_list %}
            
<
li
>{
{ item }}</
li
>
        
{% endfor %}
    
</
ul
>
    
<!--if else judge-->
    
{% if num == 1 %}
        
<
h1
>num == 1</
h1
>
    
{% else %}
        
<
h1
>num == 2</
h1
>
    
{% endif %}
</
body
>
</
html
>

python:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import
time
#导入wsgi模块
from
wsgiref.simple_server
import
make_server
#导入jinja模块
from
jinja2
import
Template
def
index():
    
#打开index.html
    
data
=
open
(
'index.html'
).read()
    
#使用jinja2渲染
    
template
=
Template(data)
    
result
=
template.render(
        
name
=
'yaoyao'
,
        
age
=
'18'
,
        
time
=
str
(time.time()),
        
user_list
=
[
'linux'
,
'python'
,
'bootstarp'
],
        
num
=
1
    
)
    
#同样是替换为什么用jinja,因为他不仅仅是文本的他还支持if判断 & for循环 操作
    
#这里需要注意因为默认是的unicode的编码所以设置为utf-8
    
return
[bytes(result,
'utf8'
)]
urllist
=
[
    
(
'/index'
,index),
]
def
RunServer(environ, start_response):
    
start_response(
'200 OK'
, [(
'Content-Type'
,
'text/html'
)])
    
#根据url的不同,返回不同的字符串
    
#1 获取URL[URL从哪里获取?当请求过来之后执行RunServer,
    
# wsgi给咱们封装了这些请求,这些请求都封装到了,environ & start_response]
    
request_url
=
environ[
'PATH_INFO'
]
    
print
(request_url)
    
#2 根据URL做不同的相应
    
#循环这个列表
    
for
url
in
urllist:
        
#如果用户请求的url和咱们定义的rul匹配
        
if
request_url
=
=
url[
0
]:
            
print
(url)
            
return
url[
1
]()
    
else
:
        
#urllist列表里都没有返回404
        
return
[bytes(
'<h1>404 not found</h1>'
,
'utf8'
)]
if
__name__
=
=
'__main__'
:
    
httpd
=
make_server('',
8000
, RunServer)
    
print
(
"Serving HTTP on port 8000..."
)
    
httpd.serve_forever()

MVC和MTV

1.MVC

全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

866894-20160506214502904-634958096.jpg

将路由规则放入urls.py

操作urls的放入controller里的func函数

将数据库操作党风model里的db.py里

将html页面等放入views里

原理图:

866894-20160506214503701-1778915599.jpg

2.MTV

Models 处理DB操作

Templates html模板

Views 处理函数请求

866894-20160506214504763-1804154090.jpg

原理图:

866894-20160506214505451-702125766.jpg

转载于:https://www.cnblogs.com/hetan/p/5467207.html

你可能感兴趣的文章
Spring
查看>>
CMU Deep Learning 2018 by Bhiksha Raj 学习记录(5)
查看>>
myeclipse部署项目到tomcat-custom_location 方式
查看>>
移植kernel-3.10.79 (1)
查看>>
github上关于iOS的各种开源项目集合(转)
查看>>
小程序初试云函数
查看>>
JMS
查看>>
Java中读取某个目录下的所有文件和文件夹
查看>>
SpringBoot配置属性之Server
查看>>
用typescript写mpvue
查看>>
硬盘压力测试工具
查看>>
html5之拖放简单效果
查看>>
创建用于编译和运行Java程序的批处理文件
查看>>
技术性问题 – 您需要多少个PHP/Python/Ruby 应用服务器工作线程?
查看>>
MySQL system variable 'max_allowed_packet' is set to (1MB).
查看>>
hdu 1358(kmp)
查看>>
c# 6位16进制数转换为Color
查看>>
swoole 创建tcp服务器
查看>>
ELK 安装部署小计
查看>>
windows环境按照dcm4chee
查看>>