zoukankan      html  css  js  c++  java
  • 自定义web框架(django)

    Django基础了解知识

    HTTP协议(超文本传输协议)

    HTTP协议

    1. 四大特性

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

      2. 基于请求响应

      3. 无状态 引申出cookie session token……

      4. 无连接

        长连接 websocket (HTTP协议的大补丁)

    2. 数据格式:

      1. 请求格式
        1. 请求首行(请求方式,协议版本等等)
        2. 请求头(一大堆K:V键值对)
        3. 或者是 总之就是加一个空行
        4. 请求体(真正的数据 发post请求的时候才有 如果是get请求不会有)
      2. 响应格式
        1. 响应首行
        2. 响应头
        3. 或者是 总之就是加一个空行
        4. 响应体(真正的数据 发post请求的时候才有 如果是get请求不会有)
      3. 响应状态码
        • 用特定的数字表示一些意思
          • 1XX:服务端已经成功接收到了你的数据 表示数据正在处理 你可以继续提交其他数据
          • 2XX:服务端成功响应(200请求成功)
          • 3XX:重定向(没登录淘宝,点击搜索商品,会跳转到登录页面,这就是重定向)
          • 4XX:请求错误(404 请求资源不存在 403 拒绝访问)
          • 5XX:服务器内部错误(500等)
    3. 请求方式

      • get方式:朝别人要数据
    • post请求:向别人提交数据(eg:用户登录)
      • url:统一资源定位符

    自定义web框架

    主要是以下两个过程:

    1. 手动书写socket
    2. 手动处理http格式数据
    ## 说明
    '''
    我的理解是:
    	web框架本质就是一个基于socket的客户端和服务端进行通信,交互的过程,也就是C/S架构,其实由于是通过浏览器向服务端发送请求和响应,所以应该是B/S架构,但是浏览器(Browser)本质也是一个客户端。
    	如果按照一般的网络编程套路来,会报错,这是因为浏览器端走的是HTTP协议,但是服务端发过来的数据是基于TCP/UDP协议的,所以就不能识别数据而报错。
    	所以我们需要在发消息的时候加一个HTTP的格式标准,这样就可以在浏览器端实现正常打印,     这是由于HTTP和TCP是不同层的协议,首先传输层的是TCP,只负责传输数据,发过去就进行接收打印二进制,但是在服务端发送的是支持TCP协议的,这样在浏览器端就会报错而无法正常显示(因为浏览器支持的是HTTP协议)
    '''
    
    
    
    
    ## 代码
    import socket
    
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    
    """
    请求首行
    b'GET /index HTTP/1.1
    
    请求头
    Host: 127.0.0.1:8080
    
    Connection: keep-alive
    
    Cache-Control: max-age=0
    
    DNT: 1
    
    Upgrade-Insecure-Requests: 1
    
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36
    
    Sec-Fetch-Mode: navigate
    
    Sec-Fetch-User: ?1
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    
    Sec-Fetch-Site: none
    
    Accept-Encoding: gzip, deflate, br
    
    Accept-Language: zh-CN,zh;q=0.9
    
    
    
    请求体
    '
    
    #请求体是空的,因为浏览器发送的是get请求,请求体只在post请求时才会有。
    """
    
    while True:
        conn, addr = server.accept()
        data = conn.recv(1024)
        # print(data)  #打印出来的是浏览器发送过来的HTTP请求数据
        conn.send(b'HTTP/1.1 200 OK
    
    ')
        # conn.send(b'hello')
        data = data.decode('utf-8')
        current_path = data.split('
    ')[0].split(' ')[1]
        # print(current_path)
        if current_path == '/index': # 如果浏览器上输入的后缀是/index, 那么将.html文件读出来发送过去
            # conn.send(b'index')
            with open(r'index.html','rb') as f:# # 这里面用document.charset看一下网页的编码格式,不然的话可能会乱码。
                conn.send(f.read())
        elif current_path == '/login': 
            conn.send(b'login')
        else:
            conn.send(b'404 error')
        conn.close()
    

    类型转换

    data = b'hello s11'
    
    # 二进制转字符串
    data = str(data, encoding='utf-8')
    print(data,type(data))
    
    # 字符串转二进制
    data = bytes(data, encoding='utf-8')
    print(data,type(data))
    

    基于wsgiref模块

    什么是wsgi

    ​ 该模块实现了自定义web框架的两个过程

    ​ 根据功能不同拆分成了不同的py文件

    ​ 拆分完成之后 如果想要添加功,仅仅只需要在urls.py以及views.py中修改就可以了

    1. urls.py 路由与视图函数对象关系
    2. views.py 放的是视图函数 (处理业务逻辑的,函数或者类)
    3. templates 模板文件夹 (一堆html文件)
    ## 基于wsgiref.py
    
    '''
    (主要作用就是初始化服务端,然后接受浏览器端发过来的请求,把请求分门别类,传给urls找到对应的视图函数,然后在views中执行相应的视图函数并把结果返回到前端页面)
    '''
    
    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',[])
        print(env)
        current_path = env.get('PATH_INFO')
        # if current_path == '/index':
        #     # 很多业务逻辑代码
        #     return [b'index']
        # elif current_path == '/login':
        #     return [b'login']
        # else:
        #     return [b'404 error']
        # 先定义一个变量名 用来存储后续匹配到的函数名
        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',8081,run)
        # 实时监听该地址  只要有客户端来连接 统一交给run函数去处理
        server.serve_forever()  # 启动服务端
    
        
    ## urls.py
    '''
    主要作用就是用一个存有元组的列表,实现将前端接收到的后缀名与view中的函数进行对应,其实就相当于一个路由分发器,中转驿站
    '''
    
    from views import *
    
    urls = [
        ('/index',index),
        ('/login',login),
        ('/xxx',xxx),
        ('/get_time',get_time),
        ('/get_user',get_user),
        ('/get_db',get_db),
    ]
    
    # views.py
    '''
    用于处理业务逻辑,其实就相当于之前写的项目中的interface接口,主要根据前端接收过来的数据 然后执行相应的函数,实现相应的功能,并将结果返回给前端展现出来。
    '''
    
    def index(env):
        return 'index'
    
    
    def login(env):
        return 'login'
    
    def error(env):
        return '404 error'
    
    
    def xxx(env):
        return 'xxx'
    
    from datetime import datetime
    
    
    def get_time(env):
        current_time = datetime.now().strftime('%Y-%m-%d %X')
        with open(r'E:Python1110月1018代码web框架推导	emplatesget_time.html','r',encoding='utf-8') as f:
            data = f.read()
        data = data.replace('$$time$$',current_time)
        return data
    
    from jinja2 import Template
    
    def get_user(env):
        d = {'name':'jason','pwd':'123','hobby':['read','running','music']}
        with open(r'E:Python1110月1018代码web框架推导	emplatesget_user.html','r',encoding='utf-8') as f:
            data = f.read()
        temp = Template(data)
        res = temp.render(user=d)  # 将字典d传递给前端页面
        # 页面上通过变量名user就能够获取到该字典
        return res
    
    import pymysql
    
    def get_db(env):
        conn = pymysql.connect(
            host = '127.0.0.1',
            port = 3306,
            user = 'root',
            password = 'root',
            database = 'hupu',
            charset = 'utf8',
            autocommit = True
        )
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        sql = "select * from user_info1"
        cursor.execute(sql)
        res = cursor.fetchall()
        print(res)
        with open(r'E:Python1110月1018代码web框架推导	emplatesget_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
    
    <!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>
    
    
    ## 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>
        <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>
    $$time$$
    </body>
    </html>
    
    
    ## get_user.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>
        <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>
    <p>{{ user }}</p>
    <p>{{ user.name }}</p>
    <p>{{ user['pwd'] }}</p>
    <p>{{ user.get('hobby') }}</p>
    </body>
    </html>
    
    
    

    注意1:

    上面代码也实现了动静态网页的功能,那么什么是动态网页什么是静态网页呢?

    静态网页:简单来说就是写死的网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了——除非你修改页面代码。

    动态网页:页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。主要体现在两种情况:1. 后端获取当前时间展示到前端;2.后端获取数据库中的数据展示到前端

    注意2:

    如何将后端获取的数据 传递给html页面?

    后端获取的数据 传递给html页面 专用名词>>>: 模板的渲染

    import jinja2就可以实现上述功能:

    pip3 install jinja2
    	
    	模板语法(极其贴近python后端语法)
    		<p>{{ user }}</p>
    		<p>{{ user.name }}</p>
    		<p>{{ user['pwd'] }}</p>
    		<p>{{ user.get('hobby') }}</p>
    		
    		
    		{% for user_dict in user_list %}  ##在前端页面中使用后端的循环语法
    			<tr>
    				<td>{{ user_dict.id }}</td>
    				<td>{{ user_dict.name }}</td>
    				<td>{{ user_dict.pwd }}</td>
    			</tr>
    		{% endfor %}
    
  • 相关阅读:
    员工管理,这么做就对了
    学会自我管理的好处及自我管理包括的内容
    职场人必看的5本书推荐,首推《情商必读12篇》
    企业管理方面的经典著作推荐
    这6本精心挑选的团队管理类好书助你做好团队管理
    战略规划,你的企业真的做对了吗?
    如何提高说服力?说服的技巧有哪些?这本书能给你答案
    读书使人进步,这本营销书籍让你真正读懂市场营销
    P1228 地毯填补问题题解
    P1010 幂次方题解
  • 原文地址:https://www.cnblogs.com/michealjy/p/11703439.html
Copyright © 2011-2022 走看看