• 自己动手写出静态网站与动态网站


    1.简介

    web框架的本质:socket服务端与浏览器的通信
    socket服务端功能划分:
    1.负责与浏览器收发消息(socket通信) --》wsgiref/uWsgi/gunicorn等web服务网关接口和服务器
    2.根据用户访问不同的路径执行不同的函数 --》路由系统(url与函数的对应关系)
    3.从HTML读取出内容并且完成字符串的替换 --》jinja2(模板语言)

    2.静态网站

    """
    这是一个静态的web网站,返回什么数据类型就是什么,而现在网站都是动态的。
    """
    import socket
    
    
    def f1(request):
        """
        处理用户请求,并返回相应的内容
        :param request: 用户请求的所有信息
        :return:
        """
        # 读取本地二进制文件并返回(在这里是自己写模板,可以任意后缀名文件并不一定需要html后缀)
        f = open('index.fsw','rb')
        data = f.read()
        f.close()
        return data
    
    def f2(request):
        f = open('aricle.tpl','rb')
        data = f.read()
        f.close()
        return data
    
    # 路由与函数的对应关系(路由系统)
    routers = [
        ('/xxx', f1),
        ('/ooo', f2),
    ]
    
    
    def run():
        # 获取socket对象
        sock = socket.socket()
        # 绑定ip地址和端口
        sock.bind(('127.0.0.1',8080))
        # 开始监听(设置最大监听数5个)
        sock.listen(5)
    
        while True:
            conn,addr = sock.accept() # 夯住,等待用户连接
            # 获取用户发送的数据
            data = conn.recv(8096)
            # 直接转换为字符串
            data = str(data,encoding='utf-8')
            print(data)
            # 根据http协议划分请求头和请求体
    
    
            headers,bodys = data.split('
    
    ')
            # 根据已有的http协议数据结构切分元素
            temp_list = headers.split('
    ')
            # 分别获取请求方法、请求url地址、请求协议类型
            method,url,protocal = temp_list[0].split(' ')
            conn.send(b"HTTP/1.1 200 OK
    
    ")
    
            func_name = None    # 设置标志位
            for item in routers:
                # 遍历url与函数对应关系表,并判断当前请求url是否相等
                if item[0] == url:
                    # 能对应就获取函数名并停止循环
                    func_name = item[1]
                    break
    
            if func_name:
                # 有这个函数就加括号调用并传入参数
                response = func_name(data)
            else:
                response = b"404"
            # 返回函数处理后的结果
            conn.send(response)
            conn.close()
    
    if __name__ == '__main__':
        run()
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>用户名</th>
                    <th>邮箱</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <th>1</th>
                    <th>root</th>
                    <th>root@qq.com</th>
                </tr>
            </tbody>
        </table>
    </body>
    </html>
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>用户登录</h1>
        <form>
            <p><input type="text" placeholder="用户名" /></p>
            <p><input type="password" placeholder="密码" /></p>
        </form>
    </body>
    </html>
    View Code

    3.动态网站

    """动态网站则是在静态网站的基础之上,进行字符串的替换,以完成网站页面的实时更新效果"""
    import socket
    
    def f1(request):
        """
        处理用户请求,并返回相应的内容
        :param request: 用户请求的所有信息
        :return:
        """
        f = open('index.fsw','rb')
        data = f.read()
        f.close()
        return data
    
    def f2(request):
        """
        运用时间戳的方式,初步实现动态网站
        :param request:
        :return:
        """
        f = open('aricle.tpl','r',encoding='utf-8')
        data = f.read()
        f.close()
        import time
        # 获取时间戳
        ctime = time.time()
        # 调用字符串的replace()替换方法换成时间戳,页面每次刷新显示的数据都不一样
        data = data.replace('@@sw@@',str(ctime))
        # 返回bytes()类型数据
        return bytes(data,encoding='utf-8')
    
    def f3(request):
        """
        获取数据库数据,只要数据库数据有更新,则页面刷新之后都会显示
        :param request: 用户请求的信息
        :return:
        """
        import pymysql
    
        # 创建连接对象
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='yang123', db='yangyu')
        # 获取游标
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 执行sql语句查询数据库数据
        cursor.execute("select id,username,password from userinfo")
        # 获取表中所有数据
        user_list = cursor.fetchall()
        # 关闭游标对象
        cursor.close()
        # 关闭连接对象
        conn.close()
    
        content_list = []
        for row in user_list:
            # 遍历数据库查询的数据,拼接字符串
            tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" %(row['id'],row['username'],row['password'])
            # 把拼接的字符串添加到列表
            content_list.append(tp)
        # 调用.join方法把列表转换为字符串
        content = "".join(content_list)
    
    
        f = open('userlist.html','r',encoding='utf-8')
        template = f.read()
        f.close()
    
        # 模板渲染(模板+数据)完成字符串的替换
        data = template.replace('@@sdfsdffd@@',content)
        return bytes(data,encoding='utf-8')
    
    def f4(request):
        """
        调用第三方模块,实现页面模板的渲染
        :param request:
        :return:
        """
        import pymysql
    
        # 创建连接对象
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='yang123', db='yangyu')
        # 获取游标
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 执行sql语句查询数据库数据
        cursor.execute("select id,username,password from userinfo")
        # 获取表中所有数据
        user_list = cursor.fetchall()
        # 关闭游标对象
        cursor.close()
        # 关闭连接对象
        conn.close()
    
        f = open('hostlist.html','r',encoding='utf-8')
        data = f.read()
        f.close()
    
        # 基于第三方工具实现的模板渲染
        from jinja2 import Template
        template = Template(data)
        # 调用render()方法完成字符串的替换,这里要注意,前后端特殊语法要相同
        data = template.render(user_list=user_list,user='sdfsdfsdf')
        return data.encode('utf-8')
    
    # 路由与函数的对应关系
    routers = [
        ('/xxx', f1),
        ('/ooo', f2),
        ('/userlist.htm', f3),
        ('/host.html', f4),
    ]
    
    
    def run():
        # 获取socket对象
        sock = socket.socket()
        # 绑定ip地址和端口
        sock.bind(('127.0.0.1',8080))
        # 开始监听(设置最大监听数5个)
        sock.listen(5)
    
        while True:
            conn,addr = sock.accept() # 夯住,等待用户连接
            # 获取用户发送的数据
            data = conn.recv(8096)
            # 直接转换为字符串
            data = str(data,encoding='utf-8')
            # 根据http协议划分请求头和请求体
    
    
            headers,bodys = data.split('
    
    ')
            # 根据已有的http协议数据结构切分元素
            temp_list = headers.split('
    ')
            # 分别获取请求方法、请求url地址、请求协议类型
            method,url,protocal = temp_list[0].split(' ')
            conn.send(b"HTTP/1.1 200 OK
    
    ")
    
            func_name = None    # 设置标志位
            for item in routers:
                # 遍历url与函数对应关系表,并判断当前请求url是否相等
                if item[0] == url:
                    # 能对应就获取函数名并停止循环
                    func_name = item[1]
                    break
    
            if func_name:
                # 有这个函数就加括号调用并传入参数
                response = func_name(data)
            else:
                response = b"404"
            # 返回函数处理后的结果
            conn.send(response)
            conn.close()
    
    if __name__ == '__main__':
        run()
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>用户名</th>
                    <th>邮箱</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <th>1</th>
                    <!-- 自定义字符串替换的特殊语法 -->
                    <th>@@sw@@</th>
                    <th>root@qq.com</th>
                </tr>
            </tbody>
        </table>
    </body>
    </html>
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>用户名</th>
                    <th>邮箱</th>
                </tr>
            </thead>
            <tbody>
                {% for row in user_list %}
                <!--使用第三方模板,就要遵循他的语法规则-->
                    <tr>
                        <td>{{row.id}}</td>
                        <td>{{row.username}}</td>
                        <td>{{row.password}}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
        {{user}}
    </body>
    </html>
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>用户登录</h1>
        <form>
            <p><input type="text" placeholder="用户名" /></p>
            <p><input type="password" placeholder="密码" /></p>
        </form>
    </body>
    </html>
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>用户名</th>
                    <th>邮箱</th>
                </tr>
            </thead>
            <tbody>
            <!--自定义模板特殊语法-->
                @@sdfsdffd@@
            </tbody>
        </table>
    </body>
    </html>
    View Code

    4.总结

    有以上我们模拟网站(socket服务端)和浏览器(socket客户端)的知识知道了:
    1.http是建立在tcp之上的,无状态的,短链接,一次请求一次响应。  而TCP是不断开的长连接。
    2.http协议是固定的键值对组合,每个键值对之间由
    分割,请求头和请求体之间则是由两个
    
    分割。而响应头和响应体也是这样的组合。
    3.自己写的网站必须具备以下要素:
        a.socket服务端
        b.根据url的不同,返回不同的内容(url与函数的对应关系)
        c.返回字符串给用户(模板引擎渲染:HTML充当模板和特殊字符,自己定义任意数据)
    
    而web框架的种类也是根据以上三点相结合:
        框架自带a,b,c              Tornado
        [第三方a],b,c              wsgiref服务网关接口、Django 
        [第三方a],b,[第三方c]   wsgiref服务网关接口、Flask、jinja2模板
    按照另一种维度划分:
         重量级:Django
         轻量级:Tornado、Flask
  • 相关阅读:
    如何用一句话激怒设计师
    Kubernetes1.3:POD生命周期管理
    从零学React Native之11 TextInput
    从零学React Native之10Text
    html+js 在页面同步服务器时间
    电信行业的容器化改造之道
    容器化ICT融合初体验
    Laravel 发送邮件(最简单的讲解!)
    jquery( 点击按钮出来文本框并限制文本框的个数)
    OpenStack宣布用Kubernetes重写底层编排引擎
  • 原文地址:https://www.cnblogs.com/Guishuzhe/p/9761105.html
Copyright © 2020-2023  润新知