Loading

自创Web框架之过渡Django框架

自创Web框架之过渡Django框架

Web框架,其实就是web应用的建立;比如网页版的QQ、b站等等
web应用又是什么呢?可以理解为基于游览器的一些应用程序,用户只需要有游览器即可,不需要再安装其他软件;
比如你打开一个url,web服务器返回一个html页面,那么你在搜索或者url拼接路径搜索的时候web服务器是怎么知道要返回什么给你呢?下面介绍一下:


  • 软件开发架构
    C/S架构:客户端与服务端
    B/S架构:游览器与服务端
    ps:b/s本质就是c/s架构
  • http协议

四大特性
基于TCP、IP作用于应用层之上的协议
基于请求响应
无状态
无连接(短连接)>>>长连接:websocket

数据格式

请求首行(http协议版本,网络请求的方法)
    请求头(一大堆的kv键值对)
    /r/n  # 换行符不能省略
    请求体(存放的是一些数据,并不是每种请求方式都有请求体,get没有请求体,post有请求体)
# 请求方式
get:朝服务器索要数据,比如输入网址获得相应的数据
post:朝服务器提交数据,刺入用户登录输入用户名和密码后,提交到后端做身份效验

image

相应格式

响应首行(http协议版本,网络请求的方法)
  响应头(一大堆k,v键值对)
  /r/n   # 换行符不能省略
  响应体(交给给浏览器展示给用户看的数据)

image

响应状态码
http状态码由三个十进制数组成,第一个十进制数定义了状态码的类型,响应分为五种:信息响应(100-199),成功响应(200-299),重定向响应(300-399),客户端错误(400-499)和服务端错误(500-599)
ps: 公司还会定义状态码,一般是以10000开头的

请求方式

get请求: 向别人(服务器)索要数据
post请求: 向别人提交数据(比如表单)

“撸起袖Web框架之“撸起袖子加油干”

为了方便理解请求网页并且返回数据的过程,写下一套下面的程序帮助理解

import socket

server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn,addr = server.accept()
    data = conn.recv(1024)
    data = data.decode('utf-8')
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    current_path = data.split(' ')[1]
    if current_path == '/index':
        with open(r'01.html','rb') as f:
            conn.send(f.read())
    elif current_path == '/login':
        conn.send(b'hello')
    else:
        conn.send(b'nothing')
    conn.close()

通过上述例子,能够简单的理解通过get请求方式得到的页面是如何返回,但是我们个人手写服务端存在很多的问题,如果客户请求不同页面那么我们就待写很多的if/else,数据处理起来也比较繁琐...通过一个模块久能解决这些问题

过wsgWeb框架之通过wsgiref加油干

# wsgiref模块解决上述两个问题
from wsgiref.simple_server import make_server

def run(request, response):
    '''
    :param request:请求相关的所有数据
    :param response: 响应相关的所有数据
    :return: 返回游览器的数据
    '''
    response('200 OK',[])
    current_path = request.get('PATH_INFO')
    if current_path == '/index':
        return [b'index']
    elif current_path == '/login':
        return [b'login']
    else:
        return [b'404 error']

if __name__ == '__main__':
    server = make_server('127.0.0.1',8000,run)
    server.serve_forever()  # 启动服务端

优化封装优化处理

'''
封装的过程主要解决:
网址的匹配问题
网址多匹配如何解决
功能复杂代码如何解决,放在一个结构不清晰
'''
'''服务端'''
from wsgiref.simple_server import make_server
from views import *
from urls import *
'''
urls.py 路由与视图函数的对应关系
views.py主要存视图函数
templates文件夹主要存放HTML文件
拆分功能只需要在urls.py中书写对应关系,views.py中书写后端业务逻辑即可

'''

def run(env,response):
    '''
    :param env:请求相关的所有数据
    :param response: 相应相关的所有数据
    :return: 返回给游览器的数据
    '''
    response('200 ok',[])
    # 从env返回的大字典中拿出用户输入内容--->key
    current_path = env.get('PATH_INFO')
    # if current_path == '...':
    #     ...
    # ...
    func = None
    for url in urls:
        if current_path == url[0]:
            # 匹配成功,将url对应的函数名,赋值给func
            func = url[1]
            break
    if func:
        res = func()
    else:
        res = error()
    return [res.encode('utf-8')]
if __name__ == '__main__':
    server = make_server('127.0.0.1',8005,run)
    server.serve_forever()
	
	
	
'''
urls.py 路由与视图函数的对应关系

'''

from views import  *
urls = [
    ('/index',index),
    ('/login',login)
]


'''
views.py主要存视图函数
下面统称为函数

'''
def index():
    return 'index'
def login():
    return 'login'
def error():
    return '404 error'

动静网页

  • 静态网页: 数据不变的,不需要实时变化的,数据写死的
  • 动态网页: 数据来源与后端代码(代码、数据库),数据实时变化等特点

示例:将时间同步到html页面上

'''服务端'''
from wsgiref.simple_server import make_server
from urls import *
'''
urls.py 路由与视图函数的对应关系
views.py主要存视图函数
templates文件夹主要存放HTML文件
拆分功能只需要在urls.py中书写对应关系,views.py中书写后端业务逻辑即可

'''

def run(env,response):
    '''
    :param env:请求相关的所有数据
    :param response: 相应相关的所有数据
    :return: 返回给游览器的数据
    '''
    response('200 ok',[])
    # 从env返回的大字典中拿出用户输入内容--->key
    current_path = env.get('PATH_INFO')

    # if current_path == '...':
    #     ...
    # ...
    func = None
    for url in urls:
        if current_path == url[0]:
            # 匹配成功,将url对应的函数名,赋值给func
            func = url[1]
            break
    if func:
        res = func()
    else:
        res = error()
    return [res.encode('utf-8')]
if __name__ == '__main__':
    server = make_server('127.0.0.1',8001,run)
    server.serve_forever()
	
	
'''
urls.py 路由与视图函数的对应关系

'''

from views import  *
urls = [
    ('/index',index),
    ('/login',login),
    ('/get_time',get_time)
]

'''
views.py主要存视图函数
下面统称为函数

'''
def index():
    return 'index'
def login():
    return 'login'
def error():
    return '404 error'
def get_time():
    from datetime import datetime
    current_time = datetime.now().strftime('%Y-%m-%d %X')
    with open(r'get_time.html','r',encoding='utf-8') as f:
        data = f.read()
    data = data.replace('AAA',current_time)
    return data
	
	
	
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<style>
    #d1{
        font-size: 48px;
        color: rebeccapurple;
    }
</style>
<body>
<div class="select2-container">
    <div class="add-row">
        <div id="d1" class="col-md-8 col-lg-offset-2">
            AAA
        </div>
    </div>
</div>
</body>
</html>

jinjia2模块

该模块是flask框架必备的模块,这里只使用jinjia2模块来写模板语法
需求: 将后端字典展示在HTML页面上

数据库

需求: 操作MySQL数据并且展示到html页面上
注意: 数据是在后端处理完之后发送到前端的

'''服务端'''
from wsgiref.simple_server import make_server
from urls import *
'''
urls.py 路由与视图函数的对应关系
views.py主要存视图函数
templates文件夹主要存放HTML文件
拆分功能只需要在urls.py中书写对应关系,views.py中书写后端业务逻辑即可

'''

def run(env,response):
    '''
    :param env:请求相关的所有数据
    :param response: 相应相关的所有数据
    :return: 返回给游览器的数据
    '''
    response('200 ok',[])
    # 从env返回的大字典中拿出用户输入内容--->key
    current_path = env.get('PATH_INFO')

    # if current_path == '...':
    #     ...
    # ...
    func = None
    for url in urls:
        if current_path == url[0]:
            # 匹配成功,将url对应的函数名,赋值给func
            func = url[1]
            break
    if func:
        res = func(env)
    else:
        res = error(env)
    return [res.encode('utf-8')]
if __name__ == '__main__':
    server = make_server('127.0.0.1',8001,run)
    server.serve_forever()


'''
urls.py 路由与视图函数的对应关系

'''

from views import *
urls = [
    ('/index',index),
    ('/login',login),
    ('/get_time',get_time),
    ('/get_dict',get_dict),
    ('/get_db',get_db)
]


def get_db(env):
    import pymysql
    from jinja2 import Template
    conn = pymysql.connect(
        user='root',
        password='123456',
        port=3306,
        host='127.0.0.1',
        database='info',
        charset='utf8',
        autocommit=True
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from emp;'
    rows = cursor.execute(sql)
    res = cursor.fetchall()
    print(res)  # [{'id': 1, 'username': 'alan', 'password': '123'}, {'id': 2, 'username': 'alearn', 'password': '456'}]
    with open(r'get_db.html','r',encoding='utf8') as f3:
        data = f3.read()
    temp = Template(data)
    total_res = temp.render(data_list=res)
    return total_res





<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <h1 style="text-align: center">用户数据</h1>
        <div class="col-md-8 col-lg-offset-2">
            <table class="table table-striped table-hover">
                <thead>
                    <tr class="success" style="text-align: center">
                        <td>id</td>
                        <td>username</td>
                        <td>password</td>
                    </tr>
                </thead>
                <tbody>
                    {%for user_dict in data_list%}
                    <tr class="info" style="text-align: center">
                        <td>{{ user_dict.id }}</td>
                        <td>{{ user_dict.username }}</td>
                        <td>{{ user_dict.password }}</td>
                    </tr>
                    {%endfor%}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

image
image

自写框架梳理

  • wsgiref模块
    • 封装了socket代码
    • 处理了http数据格式
  • 根据功能的不同拆分成不同的文件夹
    • urls.py 路由与视图函数对应的关系
    • views.py 视图函数
    • templates 模板文件夹
  • 步骤
    • 第一步添加路由与视图函数的对应关系
    • 去views书写功能代码
    • 如果需要使用到html则取模板文件夹中书写操作
posted @ 2022-03-19 01:57  木子乐乐  阅读(26)  评论(0)    收藏  举报