zoukankan      html  css  js  c++  java
  • python小白-day15 web框架

    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这个函数。

    原理图:


    当用户发送请求,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被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。


    将路由规则放入urls.py

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

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

    将html页面等放入views里

    原理图:


    2.MTV

    Models 处理DB操作

    Templates html模板

    Views 处理函数请求


    原理图:







  • 相关阅读:
    创建类以及引用一个类
    修改hosts文件
    微信第三方登录接口开发
    Android定位
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 725. Split Linked List in Parts
    Leetcode 445. Add Two Numbers II
    Leetcode 328. Odd Even Linked List
    Leetcode 237. Delete Node in a Linked List
    Leetcode 234. Palindrome Linked List
  • 原文地址:https://www.cnblogs.com/hetan/p/5467207.html
Copyright © 2011-2022 走看看