初识Web框架

Posted 摘星者的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识Web框架相关的知识,希望对你有一定的参考价值。

一、Web框架本质

Python的Web框架分为两类:

  • 通过socket自己写程序,自己处理请求;

  • 基于Wsgi(Web Server Gateway Interface:Web服务网关接口),处理请求。

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

1、Socket实现Web框架的本质

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
#!/usr/bin/env python
#coding:utf-8
  
importsocket
  
def handle_request(client):
    #接收请求
    buf =client.recv(1024)
    #返回信息
    client.send("HTTP/1.1 200 OK\\r\\n\\r\\n")
    client.send("Hello, Tim")
  
def main():
    #创建sock对象
    sock =socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #监听80端口
    sock.bind((\'localhost\',8000))
    #最大允许排队的客户端
    sock.listen(5)
  
    #循环
    whileTrue:
        #等待用户的连接,默认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 等。

    不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

2、WSGI

    WSGI是一种规范,它定义了使用Python编写web app与web server之间接口格式,实现web app与web server 间的解耦。

Python标准库提供的独立WSGI服务器为wsgiref,下来例子为Python3版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
#-*- coding:utf-8 -*-
 
from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server
 
 
def simple_app(environ, start_response):
    setup_testing_defaults(environ)
 
    status = \'200 OK\'
    headers = [(\'Content-type\', \'text/plain\')]
 
    start_response(status, headers)
 
    ret = ["%s: %s\\n" % (key, value)
           for key, value in environ.iteritems()]
    return ret
 
 
if __name__ == \'__main__\':
    httpd = make_server(\'\', 8000, simple_app)
    print "Serving on port 8000..."
    httpd.serve_forever()

下面看WEB框架图:

基于Python的Web框架有以下常用几种:

  • Tornado:使用自己的异步非阻塞的WSGI;

  • Flask:只提供了最精简和基本的框架,轻量级的;

  • Django:直接使用了WSGI,并实现了大部分功能。

二、自定义Web框架​

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

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/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\')])
    return \'<h1>Hello, World!</h1>\'
 
if __name__ == \'__main__\':
    httpd = make_server(\'\', 8000, RunServer)
    print "Serving HTTP on port 8000..."
    httpd.serve_forever()

    上面的代码,当我们访问时,访问任何的URL都会显示"Hello,World",这显然不是我们先要的结果。下面我们可以根据用户输入的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
#!/usr/bin/env python
# coding:utf-8
from wsgiref.simple_server import make_server
 
 
def RunServer(environ, start_response):
    """
    根据url的不同,返回不同的字符串
    :param environ: 当请求过来之后执行RunServer,wsgi给咱们封装了这些请求,这些请求都封装到了environ和start_response里
    :param start_response:
    :return:
    """
    start_response(\'200 OK\', [(\'Content-Type\', \'text/html\')])
     
    request_url = environ[\'PATH_INFO\']
    print request_url
     
    #根据URL做不同的响应
    # print environ 这里可以通过Pycharm断点来查看environ封装的数据
     
    if request_url == \'/index\':
        return "Hello Home"
    elif request_url == \'/admin\':
        return "Hello admin"
    else:
        return \'<h1>404!</h1>\'
 
 
if __name__ == \'__main__\':
    httpd = make_server(\'\', 8000, RunServer)
    print "Serving HTTP on port 8000..."
    httpd.serve_forever()

    看上面的操作,如果别人使用上面定义的框架,当用户来访问的时候,如果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
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/env python
#-*- coding:utf-8 -*-
 
from wsgiref.simple_server import make_server
 
\'\'\'可以进行拆分---这一部分可以给框架使用者,按照定义的格式来操作\'\'\'
 
def index():
    return \'index\'
 
def login():
    return \'login\'
 
 
#1 定义一个列表,上面定义函数
url_list = [
    #这里吧URL和函数做一个对应
    (\'/index/\',index),
    (\'/login/\',login),
]
 
########################################################################
 
\'\'\'这一部分可以单独拿出来,作为框架开发者,框架使用\'\'\'
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\']
    #2 根据URL做不同的相应
    #print environ #这里可以通过断点来查看它都封装了什么数据
 
    #循环这个列表
    for url in url_list:
        #如果用户请求的url和咱们定义的rul匹配
        if request_url == url[0]:
            print url
            return url[1]()
            #执行里面的方法
    else:
        #url_list列表里都没有返回404
        return \'404\'
 
if __name__ == \'__main__\':
    httpd = make_server(\'\', 8000, RunServer)
    print "Serving HTTP on port 8000..."
    httpd.serve_forever()

2、使用模板引擎

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

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