zoukankan      html  css  js  c++  java
  • 纯手撸web框架

    纯手撸web框架

    一、Web应用的组成

    接下来我们学习的目的是为了开发一个Web应用程序,而Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览器,需要强调的一点是:S端由server和application两大部分构成,如图所示:

    上图:Web应用组成

    img

    二、手鲁web应用

    2.1 基本版

    import socket
    
    """
    @author RansySun
    @create 2019-10-18-11:59
    """
    
    # 创建服务端
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(5)
    
    while True:
        # 等待连接
        conn, addr = server.accept()
        
        # 接收浏览器发送的消息
        data = conn.recv(1024)
        print(data)
        # 请求行 请求头  空行 请求体, 返回响应首行
        conn.send(b'HTTP/1.1 200 OK 
    
     Hello web')
        conn.close()
    

    img

    2.2 根据请求地址,返回请求内容

    import socket
    
    """
    @author RansySun
    @create 2019-10-18-11:59
    """
    
    # 创建服务端
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(5)
    
    while True:
    
        # 等待连接
        conn, addr = server.accept()
    
        # 接收服务端发送消息
        data = conn.recv(1024)
        
        # 获取请求内容
        data = str(data, encoding="utf8").split(" ")[1]
        
        # 发送请求头
        conn.send(b'HTTP/1.1 200 OK 
    
     ')
        print(data)
    
        data = bytes(data, encoding="utf8")
        # 响应客户端
        conn.send(data)
    

    img

    img

    2.3 根据请求地址返回响应html

    <!-- index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>首页</h1>
    </body>
    </html>
    
    <!-- index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎来到鸡公煲, baby</h1>
    </body>
    </html>
    
    import socket
    
    """
    @author RansySun
    @create 2019-10-19-9:54
    """
    
    # 创建连接对象
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(4)
    
    while True:
    
        # 等待连接
        conn, addr = server.accept()
        data = conn.recv(1024)
    
        # 接收客户端请求
        data = str(data, encoding="utf8").split(" ")[1]
    
        print(data)
    
        # 发送请求头
        conn.send(b"HTTP//1.1 200 OK 
    
    ")
    
        # 判断请求对象
        if data == '/index':
    
            # 返回页面请求
            with open("index.html", "rb") as fr:
                conn.send(fr.read())
        elif data == '/login':
            with open("login.html", "rb") as fr:
                conn.send(fr.read())
        else:
            conn.send(b"<h1 style='color:red'>404 error</h1>")
    
    

    img

    img

    img

    到此为止.....

    img

    三、Web框架的由来

    综上案例我们可以发现一个规律,在开发S端时,server的功能是复杂且固定的(处理socket消息的收发和http协议的处理),而业务逻辑却各不相同(不同的软件就应该有不同的业务逻辑),重复开发复杂且固定的server是毫无意义的,有一个wsgiref模块帮我们写好了server的功能,这样我们便只需要专注于功能的编写

    3.1 简易版

    from wsgiref.simple_server import make_server
    
    """
    @author RansySun
    @create 2019-10-19-10:20
    """
    
    
    def run(env, response):
        """
    
        :param env: 请求相关的所有数据
        :param response: 对页面做出相关响应
        :return:
        """
    
        # 发送请求
        response("200 OK 
    
    ", [])
    
        # 响应页面
        res = 'hello web'
        print(env.get("PATH_INFO"))
        return [res.encode('utf8')]
    
    if __name__ == '__main__':
        server = make_server("127.0.0.1", 8080, run)
    
        # 实时监听地址,只要有客户端来连接, 统一交给run函数处理
        server.serve_forever()
    
    

    img

    3.2 根据请求做出响应

    <!-- index -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>首页</h1>
    </body>
    </html>
    
    
    <!-- login -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎来到鸡公煲, baby</h1>
    </body>
    </html>
    
    <!-- get_time -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    time
    <body>
    
    </body>
    </html>
    
    <!-- get_user -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <p>{{ user }}</p>
    <p>{{ user.name }}</p>
    <p>{{ user['pwd'] }}</p>
    <p>{{ user.get('hobby') }}</p>
    <h1></h1>
    <h1></h1>
    </body>
    </html>
    
    <!-- get_db -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-2">
                <h1 class="text-center"></h1>
                <table class="table table-bordered table-striped table-hover">
                   <thead>
                        <tr>
                            <th>id</th>
                            <th>x</th>
                            <th>y</th>
                        </tr>
                    </thead>
                    <tbody>
                    <tbody>
                        {% for user_dict in user %}
                            <tr>
                                <td>{{ user_dict.id }}</td>
                                <td>{{ user_dict.x }}</td>
                                <td>{{ user_dict.y }}</td>
                            </tr>
                        {% endfor %}
                    </tbody>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    # url.py
    from views import *
    """
    @author RansySun
    @create 2019-10-19-10:49
    """
    urls = [
        ('/index', index),
        ('/login', login),
        ('/xxx', xxx),
        ('/get_time', get_time),
        ('/get_user', get_user),
        ('/get_db', get_db),
    ]
    
    
    # views.py
    from datetime import datetime
    
    """
    @author RansySun
    @create 2019-10-19-10:49
    """
    
    
    def index():
        return "index"
    
    
    def login():
        return "login"
    
    
    def xxx():
        return "xxx"
    
    
    def error(env):
        return '404 error'
    
    
    def get_time():
        """
        获取时间
        :return:
        """
        data_time = datetime.now().strftime('%Y-%m-%d %X')
        with open(r"templates	ime.html", 'r', encoding='utf8') as fr:
            data = fr.read()
        data = data.replace("time", data_time)
        return data
    
    
    from jinja2 import Template
    
    
    def get_user():
        """
        前端通过字典获取用户信息
        :return:
        """
        dic = {'name': 'randy', 'pwd': '123123', 'hobby': ['read', 'running', 'music']}
        with open(r'templates/user.html', 'r', encoding="utf-8") as fr:
            data = fr.read()
        temp = Template(data)
        # 将字典dic传递给前端页面 页面上通过变量名user就能够获取到该字典
        res = temp.render(user=dic)
        return res
    
    
    import pymysql
    
    
    def get_db():
        mysql = pymysql.connect(
            host="127.0.0.1",
            user="root",
            password="root",
            charset="utf8",
            db="db1",
            autocommit=True
        )
    
        sql = "select * from a1"
    
        cursor = mysql.cursor(pymysql.cursors.DictCursor)
        cursor.execute(sql)
    
        res = cursor.fetchall()
        with open("templates/get_db.html", "r", encoding='utf8') as fr:
            data = fr.read()
        # print(res)
    
        temp = Template(data)
        data = temp.render(user=res)
        return data
    
    # wsgiref.py
    
    from wsgiref.simple_server import make_server
    from url import *
    from views import *
    
    """
    @author RansySun
    @create 2019-10-19-10:20
    """
    
    
    def run(env, response):
        """
    
        :param env: 请求相关的所有数据
        :param response: 对页面做出相关响应
        :return:
        """
    
        # 发送请求
        response("200 OK", [])
    
        # 获取连接请求后缀
        resp = env.get("PATH_INFO")
    
        # 用来存储后续匹配到的函数名
        func = None
    
        # 查找匹配的后缀函数
        for url in urls:
            if resp == url[0]:
                func = url[1]
                break
    
        # 判断func是否有值
        if func:
            res = func()
        else:
            res = error(env)
    
        return [res.encode('utf8')]
    
    
    if __name__ == '__main__':
        server = make_server("127.0.0.1", 8080, run)
    
        # 实时监听地址,只要有客户端来连接, 统一交给run函数处理
        server.serve_forever()
    
    

    至此,我们就针对web开发的开发自定义了一个框架,所以说框架的本质就是一系列功能的集合体、不同的功能放到不同的文件中。有了该框架,可以让我们专注于业务逻辑的编写,极大的提高了开发web应用的效率(开发web应用的框架可以简称为web框架),比如我们新增一个业务逻辑,要求为:浏览器输入http://127.0.0.1:8011/home 就能访问到home.html页面,在框架的基础上具体开发步骤如下:

    步骤一:在templates文件夹下新增home.html

    步骤二:在url.py的urls中新增一条映射关系

    urls = [
        ('/index', index),
        ('/timer', timer),
        ('/home', home), # 新增的映射关系
    ]
    

    步骤三:在views.py中新增一个名为home的函数

    def home(environ):
        with open('templates/home.html', 'r',encoding='utf-8') as f: 
            data = f.read()
        return data.encode('utf-8')
    

    我们自定义的框架功能有限,在Python中我们可以使用别人开发的、功能更强大的Django框架

    img

    img

    img

    img

    在当下的阶段,必将由程序员来主导,甚至比以往更甚。
  • 相关阅读:
    数据库表结构变动发邮件脚本
    .net程序打包部署
    无法登陆GitHub解决方法
    netbeans 打包生成 jar
    第一次值班
    RHEL6 纯命令行文本界面下安装桌面
    C语言中格式化输出,四舍五入类型问题
    I'm up to my ears
    How to boot ubuntu in text mode instead of graphical(X) mode
    the IP routing table under linux@school
  • 原文地址:https://www.cnblogs.com/randysun/p/11708708.html
Copyright © 2011-2022 走看看