zoukankan      html  css  js  c++  java
  • 在学习Django框架之前所需要了解的知识点

    Web框架本质

    我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了

    用户的浏览器一输入网址,会给服务端发送数据,那浏览器会发送什么数据?怎么发?这个谁来定? 你这个网站是这个规定,他那个网站按照他那个规定,这互联网还能玩么?

    所以,必须有一个统一的规则,让大家发送消息、接收消息的时候有个格式依据,不能随便写。

    这个规则就是HTTP协议,以后浏览器发送请求信息也好,服务器回复响应信息也罢,都要按照这个规则来。

    HTTP协议主要规定了客户端和服务器之间的通信格式,那HTTP协议是怎么规定消息格式的呢?

    让我们首先打印下我们在服务端接收到的消息是什么。

    我们发现收发的消息需要按照一定的格式来,这里就需要了解一下HTTP协议了。

    网络协议:

    HTTP协议---------------数据传输是明文
    
    HTTPS协议-------------数据传输是密文
    
    websocket协议---------数据传输是密文

    HTTP协议

    超文本传输协议:规定了浏览器与服务端之间数据交互的格式

     1. HTTP协议的四大特性

    1.基于TCP、IP协议作用于应用层之上的协议
    2.基于请求响应
    -- 浏览器给服务端发起请求,服务端收到后做出回应
    3.无状态 -- 不保存用户端的登录状态,见你千百遍我都当你如初见   ps:cookie、session、token...
    4.无(短)连接 -- 一次请求响应后即断开连接           ps:长连接:websocket

     2. HTTP协议的数据传输格式

    请求数据格式:
           请求首行(请求方法...)
           请求头(一大堆K:V键值对)
           
      ---换行
           请求体(并不是所有的请求方法都有  主要用来携带敏感性数据)
    响应数据格式: 响应首行(响应状态码...) 响应头(一大堆K:V键值对) ---换行 响应体(展示给用户的数据)

     3. 响应状态码

    用简单的数字来表示一串中文意思
      1XX:服务端已经接受到你的数据正在处理,你可以继续提交
      2XX:200 OK >>>:请求成功
      3XX:重定向 --原本想访问A,但是内部跳到B
      4XX:403当前请求不符合条件 404请求资源不存在
      5XX:服务器内部错误
       ps:除了上述统一的响应状态码之外,公司还可以自定义自己的状态码

    请求方法:

    1.get请求
        朝别人索要数据
    2.post请求
        朝别人提交数据
    >>>上述两种请求都可以携带额外的参数<<< get请求携带数据的方式: url?username=jason&hobby=mn post请求携带数据的方式:
       数据是放在请求体里面的

     请求数据格式示例:

    # 请求首行--
    是换行符
    b'GET / HTTP/1.1
      
    # 请求头(都是一大堆K:V键值对)
    Host: 127.0.0.1:8080
    
    Connection: keep-alive
    
    sec-ch-ua: "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"
    
    sec-ch-ua-mobile: ?0
    
    Upgrade-Insecure-Requests: 1
    
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    
    Sec-Fetch-Site: none
    
    Sec-Fetch-Mode: navigate
    
    Sec-Fetch-User: ?1
    
    Sec-Fetch-Dest: document
    
    Accept-Encoding: gzip, deflate, br
    
    Accept-Language: zh-CN,zh;q=0.9
    

    # 请求体 (下面是空的:因为发出的是get请求,get请求不需要请求体)
    '

    纯手写web框架(无需掌握,了解即可)

    # 采用此类方式实现类型转换可以不需要用encode 和 decode
    # 只需要认识str和bytes就行了
    data = b'hello world'
    
    # 转字符串
    data1 = str(data,encoding='utf8') 
    print(data1)
    
    # 转bytes类型
    data2 = bytes(data1,encoding='utf8')
    print(data2)
    类型转换小常识
    import socket
    
    server = socket.socket()  # 默认就是TCP协议
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    
    
    while True:
        conn, addr = server.accept()  # 三次四次挥手
        data = conn.recv(1024)
        res = data.decode('utf8')
        conn.send(b'HTTP/1.1 200 OK
    
    ')
        # 字符串切割获取地址
        path = res.split(' ')[1]
        # 判断地址
        if path == '/index':
            # conn.send(b'index')
            with open(r'fh.html','rb') as f:
                data = f.read()
                conn.send(data)
        elif path == '/login':
            conn.send(b'login')
        conn.close()
    纯手撸web框架
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
        <h1 class="text-center">这是一个非常牛逼的页面</h1>
    </body>
    </html>
    fh.html

     问题:

        ---  服务端代码重复

        ---  手动处理http数据格式过于繁琐

    基于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']
        return [b'404 error']
    
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1',8080,run)  # 一旦被访问会全部交给run函数处理
        server.serve_forever()  # 启动服务端

     问题

      ---  网址很多的情况下如何匹配

      ---  网址多匹配如何解决

      ---  功能复杂代码块如何解决

    封装处理

    1.定义一个网址与功能函数的对应关系
        # 地址与功能的对应关系
        urls = [
            ('/index',index_func),
            ('/login',login_func),
            ('/reg',reg_func),
        ]
    2.按照功能的不同划分成不同的py文件
        urls.py views.py 服务端.py
    3.书写服务端代码
         func = None
        # for循环判断
        for url_tuple in urls:  # (),()
            if current_path == url_tuple[0]:
                # 将匹配到的函数名赋值给func变量
                func = url_tuple[1]
                break
        # 判断func是否有值
        if func:
            # 执行对应的函数
            res = func(request)
        else:
            res = errors(request)
        return [bytes(res,encoding='utf8')]

    动静态网页

    静态网页:
      页面上的数据全部都是写死的,万年不变
    动态网页:
      页面上的数据来源于后端(代码、数据库)

    1.访问网址展示当前时间(由后端模块生成并展示到html页面)

    def get_time_func(request):
        from datetime import datetime
        current_time = datetime.now().strftime('%Y-%m-%d %X')
        with open(r'get_time.html','r',encoding='utf8') as f:
            data = f.read()  # 字符串
        data = data.replace('sadadadad',current_time)
        return data

    2.后端有一个字典,将该字段传递给html页面,并且在该页面上还可以使用字典取值的各种操作
     python强大而优秀的三方库为我们解决了这个问题
     实现模板渲染 模板语法的第三方模块:jinja2模块
      安装方式:pip3 install jinja2
    ps:该模块是flask框架必备的模块 所以下载flask也会自动下载该模块

    def get_dict_func(request):
            user_dict = {"username":'jason','password':123,'hobby':'study'}
            from jinja2 import Template
            with open(r'templates/get_dict.html','r',encoding='utf8') as f:
                data = f.read()  # 字符串
            temp = Template(data)
            # 将user_dict传递给get_dict.html页面 在该页面上使用变量名user_data调用
            res = temp.render(user_data=user_dict)
            return res

    模板语法(用近似于python的语法在html文件上操作数据) 红色标记为固定语法,jinja2支持字典、列表等数据类型,在前端页面文件中的使用方式也和python中如出一辙。

    {{user_data}}
    {{user_data['username']}}
    {{user_data.get('password')}}
    {{user_data.hobby}}
            
    {%for user_dict in data_list%}
           <tr>
               <td>{{user_dict.id}}</td>
               <td>{{user_dict.name}}</td>
               <td>{{user_dict.age}}</td>
          </tr>
    {%endfor%}

    3.获取MySQL数据库数据展示到页面上

    def get_db_func(request):
        import pymysql
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='123',
            db='db666',
            charset='utf8',
            autocommit=True
        )
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        sql = 'select * from userinfo'
        affect_rows = cursor.execute(sql)
        res1 = cursor.fetchall()  # [{},{},{}]
        with open(r'templates/get_db.html','r',encoding='utf8') as f:
            data = f.read()  # 字符串
        temp = Template(data)
        # 将user_dict传递给get_dict.html页面 在该页面上使用变量名user_data调用
        res = temp.render(data_list=res1)
        return res

    总结

    1.纯手撸web框架

    • 1.socket代码需要我们自己写
    • 2.http格式的数据自己处理(只能拿到用户输入的路由)

    2.基于wsgiref模块

    • 1.封装了socket代码
    • 2.处理了http数据格式

      web服务网关接口

    • 1.请求来的时候解析http格式的数据,封装成了大字典
    • 2.响应走的时候把数据打包成符合http格式,在返回给浏览器

    3.根据功能的不同拆分成不同的文件夹

      urls.py 路由与视图函数对应关系:主要是匹配浏览器请求的视图页面并交由对应视图函数处理

      views.py 视图函数:得到浏览器的页面请求及浏览器携带的请求数据,进行html页面提取、数据处理、模板渲染并返回

      templates 模板文件夹:放有所有前端html页面文件夹

    • 1.第一步添加路由与视图函数的对应关系
    • 2.去views中书写功能代码
    • 3.如果需要使用到html则去模板文件夹中操作

    4.jinja2模板语法

      {{···}}
      {%···%}

    5.简易版本web框架流程图
      

    Python三大主流web框架

    1.django框架:
    特点:大而全,自带的功能组件非常非常非常的多!类似于航空母舰
    不足之处: 有时候过于笨重


    2.flask框架:
    特点:小而精,自身的功能组件非常非常非常的少!类似于游骑兵

    但是第三方模块非常之多,如果把第三方模块全部叠加起来完全可以盖过django并且也越来越像django
    不足之处: 比较依赖于第三方的开发者,有时候也会受限于第三方模块

      ps:三行代码就可以启动一个flask后端服务

    3.tornado框架:
    特点:异步非阻塞,支持高并发

    速度非常的快 快到可以开发游戏服务器
      ps:Sanic、FastAPI...

     A : socket部分B: 路由与视图匹配C: 模版语法
    django 别人的, wsgiref模块 自己写的 自己的(没有jinja2模块好用 但是也很方便)
    flask 别人的,wsgiref模块封装之后werkzeug 自己写的 别人的,jinja2模块
    tornado 自己写的 自己写的 自己写的
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    注册事件为何无效,没有触发? AUTOPOSTBACK已经设置为TRUE
    不使用web服务实现文本框自动完成扩展
    实现一个搜索功能思路
    QT练习3:QT数字和滚动条关联
    Qt 显示图片 放大 缩小 移动
    QT 的信号与槽机制介绍
    一个有很多QT免费应用例程的网站
    yafeilinux.com的开源项目非常好的东西
    vector的用法
    C语言实现获取LINUX当前时间
  • 原文地址:https://www.cnblogs.com/gfeng/p/14526273.html
Copyright © 2011-2022 走看看