第二百五十六节,Web框架

Web框架

 

Web框架本质

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

举例:

#!/usr/bin/env python
#coding:utf-8
import socket #导入单线程通讯模块

def handle_request(client): #发送内容函数
    buf = client.recv(1024)  #设置最大传输字节
    client.sendall(bytes("HTTP/1.1 200 OK\r\n\r\n", encoding='utf-8'))  #向客户端发送内容,以字节形式发送
    client.sendall(bytes("Hello, World欢迎访问", encoding='utf-8'))         #向客户端发送内容

def main(): #创建通讯函数
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #创建服务端通讯对象
    sock.bind(('localhost',8082))                               #在服务端设置服务端ip和端口
    sock.listen(5)                                              #监听IP和端口,设置一个参数,表示最多连接排队数量

    while True: #循环
        connection, address = sock.accept() #等待接收客户端的请求,一旦有客户端请求连接,就会返回两个值,一个是连接对象,一个是客户端的地址信息,所以需要两个变量来接收
        handle_request(connection)          #执行handle_request函数,将客户端请求连接传入handle_request函数
        connection.close()                  #关闭连接

if __name__ == '__main__':                  #wds系统下if __name__ == "__main__"才能创建进程,我们调试没关系,以后在Linux系统没这个问题
    main()                                  #执行main函数

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

 

所以,对于Web框架来说分为两类,一类是即包含了socket服务端,有包含了逻辑处理,一类是只包含逻辑处理需要另外做socket服务端

 

 

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

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

wsgiref模块,python标准库提供的独立WSGI服务器称为wsgiref,就是Web框架逻辑处理包含了socket服务端

注意:wsgiref模块在python3以上版本有问题,在2.7上可以使用,所以下面的列子在2.7上运行的

#!/usr/bin/env python
#coding:utf-8
from wsgiref.simple_server import make_server  #引入wsgiref的make_server


def RunServer(environ, start_response):  #创建通讯内容函数
    start_response('200 OK', [('Content-Type', 'text/html')]) #HTML方式返回内容
    return '<h1>Hello, web!</h1>' #返回内容


if __name__ == '__main__':
    httpd = make_server('', 8082, RunServer)    #设置访问端口,和通讯内容函数
    httpd.serve_forever()   #执行通讯函数

RunServer(environ, start_response)创建通讯内容函数,里面有两个参数
environ里面包含用户的请求信息如ip等
start_response里面包含返回信息

查看方式:

 

自定义Web框架

一、框架

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

根据用户访问的路径,给出相应的内容

#!/usr/bin/env python
#coding:utf-8
from wsgiref.simple_server import make_server

def index():            #函数返回字符串index
    return 'index'

def login():            #login
    return 'login'

URLS = {                #设置一个字典,键为路径名称,值为函数名称
    "/index":index,
    "/login":login,
}

def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    url = environ['PATH_INFO']  #接收用户访问的路径名称
    if url in URLS.keys():      #判断用户访问路径在URLS字典里是否存在
        furl = URLS[url]        #如果存在通过下标拿到字典里的函数名称
        ret = furl()            #执行函数赋值给ret变量,相当于ret等于函数返回字符串
    else:
        ret = "404"             #如果不存在ret变量等于404
    return ret                  #最后将ret变量返回给浏览器

if __name__ == '__main__':
    httpd = make_server('', 8082, RunServer)
    httpd.serve_forever()

 

 

二、模板引擎,和MVC

MVC框架,就是归类后根据文件夹定义的名字

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

模板引擎归类,归类就是为了以后方便管理

urls.py将映射文件信息写在这个文件里,以后要添加映射就在这里写

#!/usr/bin/env python
#coding:utf-8
import controller
# 映射文件
URLS = {                #设置一个字典,键为路径名称,值为函数名称
    "/index":controller.index,
    "/login":controller.login,
}

controller.py逻辑处理文件,根据用户访问路径,给出对应的处理,以后要添加逻辑处理函数就写在这里

 

#!/usr/bin/env python
#coding:utf-8
import os                                                 #引入os模块

# 映射文件对应的函数
def index():                                              #函数返HTML文件内容
    f = open(os.path.join('views','index.html'),'r')      #拼接路径,打开index.html
    data = f.read()                                       #读出html文件内容
    f.close()                                             #关闭打开的文件
    return data

def login():
    f = open(os.path.join('views', 'login.html'),'r')
    data = f.read()
    f.close()
    return data

 

start.py模板引擎启动文件,用于启动模板引擎,一般不做修改

#!/usr/bin/env python
#coding:utf-8
from wsgiref.simple_server import make_server   #导入wsgiref模块里的make_server方法
from urls import  URLS                          #导入映射文件变量

def RunServer(environ, start_response):         #定义RunServer函数,接收请求信息,和发送内容
    start_response('200 OK', [('Content-Type', 'text/html')])
    url = environ['PATH_INFO']                  #接收用户访问的路径名称
    if url in URLS.keys():                      #判断用户访问路径在URLS字典里是否存在
        furl = URLS[url]                        #如果存在通过下标拿到字典里的函数名称
        ret = furl()                            #执行函数赋值给ret变量,相当于ret等于函数返回字符串
    else:
        ret = "404"                             #如果不存在ret变量等于404
    return ret                                  #最后将ret变量返回给浏览器

if __name__ == '__main__':
    httpd = make_server('', 8082, RunServer)
    httpd.serve_forever()

views文件夹用于专门存放html文件

models文件夹用于专门存放数据库处理文件

整理后的结构

Web框架,一般根据存放数据库处理文件夹的首字母M,存放html文件夹首字母V,逻辑处理文件首字母C,来命名的,这就是mvc框架

Web框架运行图

 

 

Web框架请求动态内容

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

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

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--{{item}}设置一个表示-->
<h1>{{item}}</h1>
</body>
</html>

 

逻辑处理文件controller.py

#!/usr/bin/env python
#coding:utf-8
import os                                                 #引入os模块
import time                                               #引入事件模块
# 映射文件对应的函数
def index():                                              #函数返HTML文件内容
    f = open(os.path.join('views','index.html'),'r')      #拼接路径,打开index.html
    data = f.read()                                       #读出html文件内容
    f.close()                                             #关闭打开的文件
    new_data = data.replace("{{item}}",str(time.time()))  #获取系统时间转换成字符串,替换html里的{{item}}
    return new_data

def login():
    f = open(os.path.join('views', 'login.html'),'r')
    data = f.read()
    f.close()
    return data

 

 


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

jinja2模块Web框架模块
Template()方法逻辑处理Web框架
render()方法设置html可调用python变量
encode()返回逻辑处理后的网页字符串给浏览器

 

 首先需要安装jinja2第三方模块

 逻辑处理文件controller.py

#!/usr/bin/env python
#coding:utf-8
import os                                                 #引入os模块
from jinja2 import Template                               #引入jinja2模块
# 映射文件对应的函数
def index():                                              #函数返HTML文件内容
    f = open(os.path.join('views','index.html'),'r')      #拼接路径,打开index.html
    result = f.read()                                     #读出html文件内容
    f.close()                                             # 关闭打开的文件
    template = Template(result)                           #将读出的字符串传入jinja2模块的Template方法逻辑处理网页字符串
    data = template.render(name='John Doe', user_list=['alex', 'eric'])     #render方法向网页字符串添加python可以变量
    return data.encode('utf-8')                           #返回逻辑处理后的字符串给浏览器

def login():
    f = open(os.path.join('views', 'login.html'),'r')
    data = f.read()
    f.close()
    return data

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{{name}}</h1>  <!--{{引用框架逻辑处理设置变量}}-->

    <ul>
        {% for item in user_list %} <!--{%可以远行代码块%}-->
        <li>{{item}}</li>
        {% endfor %}
    </ul>
</body>
</html>

 

posted @ 2017-05-12 16:32  林贵秀  阅读(485)  评论(0编辑  收藏  举报