zoukankan      html  css  js  c++  java
  • web框架基础

    HTTP协议(超文本协议)

    四大特性

    基于TCP/IP之上作用于应用层

    基于请求响应

      发是请求,给是响应

    无状态

      不保存用户状态,连一次就给忘了

    无连接

      eg:one night love

    数据格式

    请求格式

      请求首行(请求方式,协议版本等)

      请求头(一大堆K:V键值对)

      

      请求头(真正的数据 发post请求的时候才有 如果get请求不会有)

    响应格式

      响应首行

      响应头

      

      响应体

    响应状态码

    用特定的数字表示一些数据

    ​   1xx:服务端已经接收到了你的数据 正在处理 你可以提交其他数据

    ​   2xx:服务端成功响应(200请求成功)

    ​   3xx:重定向

    ​   4xx:请求错误(404 请求资源不存在 403 拒绝访问)

    ​   5xx:(服务器内部错误(500))

    请求方式

    get请求

    ​   朝别人要数据

    post请求

    ​   向别人提交数据(eg:用户登录)

    纯手撸web框架

    • 手动书写socket
    • 手动处理http格式数据

    简单c/s连接

    #服务端
    import socket
    server = socket.socket()
    server.bind(('127.0.0.1', 8081))
    server.listen(5)
    while True:
        conn,addr = server.accept()
        data = conn.recv(1024)
        conn.send(b'HTTP/1.1 200 OK
    
    ')
        print(data)
        conn.send(b'hello baby')
        conn.close()

    稍微复杂web框架

    客户端请求什么,就返回什么,eg:客户端发送http://127.0.0.1:8081/index则服务器返回给客户端index

    import socket
    server = socket.socket()
    server.bind(('127.0.0.1', 8081))
    server.listen(5)
    while True:
        conn,addr = server.accept()
        conn.send(b'HTTP/1.1 200 OK
    
    ')
        data = conn.recv(1024)
        print(data)
        data = data.decode('utf8')
        current_path = data.split('
    ')[0].split(' ')[1]
        print(current_path)
        if current_path == '/index':
            conn.send(b'index')
            #服务端还可以打开html文件,将文件中的东西显示给客户端
            # with open(r'index.html', 'rb') as f:   
            #     conn.send(f.read())
        else:
            conn.send(b'404 error')
        conn.close()

    基于wsgiref

    如果我不想写上面代码中的socket连接和里面的index等内容,客户端发送100个不同的请求,我也不能手撸100遍啊!那也太累了吧,所以我们就利用了wsgiref模块,帮我们操作起来更简单和方便,我们可以把在wsgiref.py中的必要代码写在相对应的文件内,以下是各个文件中要放的东西。

    ​ urls.py 路由与视图函数对象关系
    ​ views.py 放的是视图函数(处理业务逻辑的)
    ​ templates 模板文件夹(一堆html文件)

    wsgiref.py文件

    from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    
    
    def run(env,response):
        """
        :param env: 请求相关的所有数据
        :param response: 响应相关的所有数据
        :return:
        """
        response('200 OK',[])
        current_path = env.get('PATH_INFO')  #env里面有 很多数据,我们筛选有用的数据就行
        # 先定义一个变量名 用来存储后续匹配到的函数名
        func = None
        # for循环 匹配后缀
        for url in urls:
            if current_path == url[0]:
                func = url[1]  # 一旦匹配成功 就将匹配到的函数名赋值给func变量
                break  # 主动结束匹配
        # 判断func是否有值
        if func:
            res = func(env)
        else:
            res = error(env)
        return [res.encode('utf-8')]
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1',8080,run)
        # 实时监听该地址  只要有客户端来连接 统一交给run函数去处理
        server.serve_forever()  # 启动服务端,永远等着客户端来连接

    urls.py

    from views import *
    
    urls = [
        ('/index',index),  #第二个是函数,如果匹配成功,就去views.py中去找相应的函数去运行
        ('/login',login),
        ('/xxx',xxx),
    ]

    views.py

    from urls import urls
    
    def index(env):
        return 'index'
    
    
    def login(env):
        return 'login'
    
    def error(env):
        return '404 error'
    
    
    def xxx(env):
        return 'xxx'

    客户端通过访问服务器获取字典

    我们这里需要用到一个模块jinja2

    我们需要先去下载这个模块from jinja2 import Template

    具体了解jinja2请点击链接https://www.cnblogs.com/yanjiayi098-001/p/11701150.html

    wsgiref.py文件

    from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    
    
    def run(env,response):
        """
        :param env: 请求相关的所有数据
        :param response: 响应相关的所有数据
        :return:
        """
        response('200 OK',[])
        current_path = env.get('PATH_INFO')  #env里面有 很多数据,我们筛选有用的数据就行
        # 先定义一个变量名 用来存储后续匹配到的函数名
        func = None
        # for循环 匹配后缀
        for url in urls:
            if current_path == url[0]:
                func = url[1]  # 一旦匹配成功 就将匹配到的函数名赋值给func变量
                break  # 主动结束匹配
        # 判断func是否有值
        if func:
            res = func(env)
        else:
            res = error(env)
        return [res.encode('utf-8')]
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1',8080,run)
        # 实时监听该地址  只要有客户端来连接 统一交给run函数去处理
        server.serve_forever()  # 启动服务端,永远等着客户端来连接

    urls.py

    urls = [
        ('/get_user',get_user),  #第二个是函数,如果匹配成功,就去views.py中去找相应的函数去运行
        
    ]

    views.py

    def get_user(env):
        d = {'name':'jason','pwd':'123','hobby':['read','running','music']}
        with open(r'get_user.html','r',encoding='utf-8') as f:
            data = f.read()
        temp = Template(data)   #将data数据传给这个temp,做处理
        res = temp.render(user=d)  # 将字典d传递给前端页面 页面上通过变量名user就能够获取到该字典
        return res

    get_user.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    #jinja2模块,可以对字典 进行以下取值,同时这是jinja变量取值 {{ }}的语法
    <p>{{ user }}</p>
    <p>{{ user.name }}</p>
    <p>{{ user['pwd'] }}</p>
    <p>{{ user.get('hobby') }}</p>
    </body>
    </html>

    动静态页面

    静态页面:就是一个写死的页面

    动态页面:可以通过更改后端的数据,来反应到浏览器的页面上

    ​ eg:1.后端获取当前时间展示到前端

    ​ 2.后端获取数据库中的数据展示到前端

    客户端通过访问服务器获取当前时间

    那么如果用户访问服务端,则客户端页面就会显示当前时间,这样该怎么做呢?

    我们要知道,页面就是要用到html,如果时间写在HTML,那么通过编码格式,他已经不再是时间了,那么怎样将时间显示在页面呢?

    做法:我们要在wsgiref模块的基础上,先在html中写一串特定的字符,在后端将这串html和获取的时间作交换,具体看代码

    wsgiref.py文件

    from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    
    
    def run(env,response):
        """
        :param env: 请求相关的所有数据
        :param response: 响应相关的所有数据
        :return:
        """
        response('200 OK',[])
        current_path = env.get('PATH_INFO')  #env里面有 很多数据,我们筛选有用的数据就行
        # 先定义一个变量名 用来存储后续匹配到的函数名
        func = None
        # for循环 匹配后缀
        for url in urls:
            if current_path == url[0]:
                func = url[1]  # 一旦匹配成功 就将匹配到的函数名赋值给func变量
                break  # 主动结束匹配
        # 判断func是否有值
        if func:
            res = func(env)
        else:
            res = error(env)
        return [res.encode('utf-8')]
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1',8080,run)
        # 实时监听该地址  只要有客户端来连接 统一交给run函数去处理
        server.serve_forever()  # 启动服务端,永远等着客户端来连接

    urls.py

    from views import *
    
    urls = [
        ('/get_time',get_time),  #第二个是函数,如果匹配成功,就去views.py中去找相应的函数去运行
        
    ]

    views.py

    from urls import *
    from datetime import datetime
    
    
    def get_time():
        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('$$time$$',current_time)
        return data
    

    get_time.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    $$time$$
    </body>
    </html>

    客户端通过访问服务器获取数据库数据

    获取数据库数据现在就和获取字典的方法差不多像了,只不过我们需要建一个数据库,通过链接数据库,去数据库里面拿值

    wsgiref.py文件

    from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    
    
    def run(env,response):
        """
        :param env: 请求相关的所有数据
        :param response: 响应相关的所有数据
        :return:
        """
        response('200 OK',[])
        current_path = env.get('PATH_INFO')  #env里面有 很多数据,我们筛选有用的数据就行
        # 先定义一个变量名 用来存储后续匹配到的函数名
        func = None
        # for循环 匹配后缀
        for url in urls:
            if current_path == url[0]:
                func = url[1]  # 一旦匹配成功 就将匹配到的函数名赋值给func变量
                break  # 主动结束匹配
        # 判断func是否有值
        if func:
            res = func(env)
        else:
            res = error(env)
        return [res.encode('utf-8')]
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1',8080,run)
        # 实时监听该地址  只要有客户端来连接 统一交给run函数去处理
        server.serve_forever()  # 启动服务端,永远等着客户端来连接

    urls.py

    urls = [
        ('/get_db',get_db),  #第二个是函数,如果匹配成功,就去views.py中去找相应的函数去运行
        
    ]

    views.py

    import pymysql
    
    def get_db(env):
        conn = pymysql.connect(
            host = '127.0.0.1',
            port = 3306,
            user = 'root',
            password = 'root',
            database = 'day56',
            charset = 'utf8',
            autocommit = True
        )
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        sql = "select * from userinfo"
        cursor.execute(sql)  #提交sql语句,这个出发的是执行的对象并不是一个值
        res = cursor.fetchall()
        print(res)
        with open(r'get_db.html','r',encoding='utf-8') as f:
            data = f.read()
        temp = Template(data)
        ret = temp.render(user_list = res)  # 将字典d传递给前端页面 页面上通过变量名user就能够获取到该字典
        return ret

    get_db.html

    我们这里用到了bootstrap搭建页面,这就是一个典型的动态页面

    <!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-8 col-md-offset-2">
                <h1 class="text-center">用户列表</h1>
                <table class="table table-bordered table-striped table-hover">
                    <thead>
                        <tr>
                            <th>id</th>
                            <th>name</th>
                            <th>pwd</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for user_dict in user_list %}
                            <tr>
                                <td>{{ user_dict.id }}</td>
                                <td>{{ user_dict.name }}</td>
                                <td>{{ user_dict.pwd }}</td>
                            </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    
    </div>
    </body>
    </html>

    python三大主流web框架

    ​ A:socket部分
    ​ B:路由与视图函数对应关系
    ​ C:模板语法

    DjangoFlaskTornado
    大而全 自带的功能特别多 类似于航空母舰
    有时候过于笨重
    小而精 自带的功能特别少 类似于游骑兵
    第三方的模块特别多,如果将flask第三方模块全部加起来 完全可以超过django
    比较依赖于第三方模块
    异步非阻塞
    牛逼到可以开发游戏服务器
    A用的别人的 wsgiref
    B自己写的
    C自己写的
    A用的别人的 werkzeug(基于wsgiref)
    B自己写的
    C用的别人的 jinja2
    三者全是自己写的
     
     
  • 相关阅读:
    Runloop详解
    iOS高效裁剪图片圆角算法
    Runtime详解(下)
    Runtime详解(上)
    iOS UITextfield只允许输入数字和字母,长度限制
    iOS多线程(上)——GCD详解(上)
    @property、@sythesize以及Ivar和@dynamic讲解(下)
    iOS 循环引用讲解(中)
    @property详解,@property修饰符以及各个修饰符区别(上)
    PHP 使用 OSS 批量上传图片
  • 原文地址:https://www.cnblogs.com/lulingjie/p/11715845.html
Copyright © 2011-2022 走看看