一、初识web框架

一、手写简易web框架

1. 获取输入网址后缀

conn, addr = server.accept()
data = conn.recv(1024)

data = data.decode('utf-8')
current_path = data.split('\r\n')[0].split(' ')[1]
print(current_path)

conn.send(b'HTTP/1.1 200 ok\r\n\r\nhello world')
conn.close()


2. 根据不同后缀返回不同结果

conn, addr = server.accept()
data = conn.recv(1024)

data = data.decode('utf-8')
current_path = data.split('\r\n')[0].split(' ')[1]

conn.send(b'HTTP/1.1 200 OK\r\n\r\n')

if current_path == '/index':
    conn.send(b'index')

elif current_path == '/login':
    conn.send(b'login')

else:
    conn.send(b'hello world')

conn.close()
  1. 根据不同后缀返回不同HTML页面

    conn, addr = server.accept()
    data = conn.recv(1024)

    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')

    data = data.decode('utf-8')
    current_path = data.split('\r\n')[0].split(' ')[1]

    if current_path == '/index':

     with open(r'a.html', 'rb') as f:
         conn.send(f.read())

    elif current_path == '/login':
    with open(r'b.html', 'rb') as f:
    conn.send(f.read())

    else:
    conn.send(b'hello world')
    conn.close()

二、wsgiref实现简易web框架

1. 往浏览器窗口返回固定值

from wsgiref.simple_server import make_server


def run(env, response):
    print(env)

    response('200 ok', [])

    return [b'hello world']

if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()


2. 获取输入后缀

from wsgiref.simple_server import make_server


def run(env, response):

    response('200 ok', [])

    current_path = env.get('PATH_INFO')

    print(current_path)

    return [b'hello world']

if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()


3. 根据不同后缀返回不同结果

from wsgiref.simple_server import make_server


def run(env, response):

    response('200 ok', [])

    current_path = env.get('PATH_INFO')

    if current_path == '/index':
        return [b'index']

    elif current_path == '/login':
        return [b'login']
    
    return [b'404 error']

if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()


4. 根据不同后缀调用不同函数处理

from wsgiref.simple_server import make_server


def index(env):
    return 'index'

def login(env):
    return 'login'

def errors(env):
    return '404'

urls = [
    ('/index', index),
    ('/login', login)
]

def run(env, response):

    response('200 ok', [])

    current_path = env.get('PATH_INFO')

    func = None

    for url in urls:

        if url[0] == current_path:
            func = url[1]
            break

    if func:
        res = func(env)

    else:
        res = errors(env)

    return [res.encode('utf_8')]

if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run)
    server.serve_forever()


5. 将不同功能封装在不同模块中

    a. main
    
    from views import *
    from urls import urls
    from wsgiref.simple_server import make_server
    
    
    def run(env, response):
    
        response('200 ok', [])
    
        current_path = env.get('PATH_INFO')
    
        func = None
    
        for url in urls:
    
            if url[0] == current_path:
                func = url[1]
                break
    
        if func:
            res = func(env)
    
        else:
            res = errors(env)
    
        return [res.encode('utf_8')]
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1', 8080, run)
        server.serve_forever()
    
    
    b. views(视图函数)
    
    def index(env):
        return 'index'
    
    def login(env):
        return 'login'
    
    def errors(env):
        return '404'
    
    
    c. urls(路由与视图函数的对应关系)
    
    from views import *
    
    
    urls = [
        ('/index', index),
        ('/login', login)
    ]

三、让页面展示当前时间

1. 在urls中添加对应关系

urls = [
    ('/index', index),
    ('/login', login),
    ('/get_time', get_time),
]


2. 在templates中编写名为get_time的HTML模板

<!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>
</head>
<body>
$$time$$
</body>
</html>


3. 在view中添加获取时间功能,将结果替换掉HTML页面中的字段。

def get_time(env):

    current_time = datetime.now().strftime('%Y-%m-%d %X')
    with open(r'templates/get_time.html', 'r', encoding='utf-8') as f:
        data = f.read()
    data = data.replace("$$time$$", current_time)
    return data

四、让页面展示字典

1. 在urls中添加对应关系

urls = [
    ('/index', index),
    ('/login', login),
    ('/get_time', get_time),
    ('/get_user', get_user),
]


2. 在templates中编写名为get_time的HTML模板

<!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>
</head>
<body>
<p>{{data}}</p>
<p>{{data['username']}}</p>
<p>{{data.password}}</p>
<p>{{data.get('hobby')}}</p>
</body>
</html>


3. 在views中导入jinja2模块,添加获取字典功能

from jinja2 import Template
def get_user(env):
    user_dict = {'username': 'byx', 'password': '123', 'hobby': ['read', 'game', 'running']}

    with open(r'templates/get_user.html', 'r', encoding='utf-8') as f:
        data = f.read()

    temp = Template(data)
    res = temp.render(data=user_dict)

    return res

五、动态展示数据库

1. 在urls中添加对应关系

urls = [
    ('/index', index),
    ('/login', login),
    ('/get_time', get_time),
    ('/get_user', get_user),
    ('/get_db', get_db)
]


2. 在templates中编写名为get_db的HTML模板

<!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>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">

</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h2 class="text-center">用户数据展示</h2>
            <table class="table table-hover table-bordered table-striped">
                <thead>
                    <tr>
                        <th>id</th>
                        <th>username</th>
                        <th>password</th>
                    </tr>
                </thead>
                <tbody>
                    {%for user_dict in user_list%}
                        <tr>
                            <td>{{user_dict.id}}</td>
                            <td>{{user_dict.name}}</td>
                            <td>{{user_dict.password}</td>
                        </tr>
                    {%endfor%}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>


3. 在views中导入pymysql模块,连接数据库。通过jinja2模块导入get_db模板。

import pymysql
def get_db(env):

    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        password = '123',
        database = 'test',
        charset = 'utf8',
        autocommit = True
    )

    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = 'select * from userinfo'
    affect_rows = cursor.execute(sql)
    data = cursor.fetchall()

    with open(r'templates/get_db.html', 'r', encoding='utf-8') as f:
        data1 = f.read()

    temp = Template(data1)
    res = temp.render(user_list=data)

    return res

六、总结

1. 手写web框架

    1. 手动书写socket代码
    
    2. 手动处理HTTP数据
    
2. 基于wsgiref模块帮助我们处理socket以及HTTP数据

    wsgiref模块

        1. 请求来的时候,解析HTTP数据,打包成字典传输过来,便于操作各项数据。
        
        2. 响应走的时候,自动将数据打包成符合HTTP协议格式的样子,返回给前端。
        
3. 封装路由与视图函数的对应关系,以及视图函数文件

    1. urls.py

        路由与视图函数对应关系
    
    2. views.py
    
        视图函数(视图函数不单单指函数,也可以是类)
        
    3. templates
    
        模板文件夹
    
4. 基于jinja2实现模板的渲染

    后端生成好数据,通过某种方式传递给前端页面使用(前端页面可以基于模板语法更加快捷简便使用后端传过来的数据
    
5. 动静态网页

    1. 静态网页

        数据是写死的,万年不变

    2. 动态网页

        数据动态获取
    
        比如:
    
            1. 后端实时获取当前时间给前端页面渲染
    
            2. 后端从数据库获取数据给前端页面渲染

猜你喜欢

转载自www.cnblogs.com/binyuanxiang/p/11992816.html
今日推荐