Python——web服务器前后端衔接(mysql、接口、ajax连接)学习笔记

web服务器前后端衔接(mysql、接口、ajax连接)学习笔记

准备工作

网页:index.html和center.html
数据库: 随便网上找个
一个web服务器:web.py

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>首页 - 个人选股系统 V5.87</title>
  <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
  <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
    <script>
        $(document).ready(function(){

                $("input[name='toAdd']").each(function(){  
                    var currentAdd = $(this);  
                    currentAdd.click(function(){  
                        code = $(this).attr("systemIdValue");
                        alert("/add/" + code + ".html"); 
                        $.get("/add/" + code + ".html", function(data, status){
                            alert("数据: " + data + "\n状态: " + status);
                        });
                    });  
                });  
        });
    </script>
</head>

<body>
<div class="navbar navbar-inverse navbar-static-top ">
        <div class="container">
        <div class="navbar-header">
                <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                 </button>
                 <a href="#" class="navbar-brand">选股系统</a>
        </div>
        <div class="collapse navbar-collapse" id="mymenu">
                <ul class="nav navbar-nav">
                        <li class="active"><a href="">股票信息</a></li>
                        <li><a href="./center.html">个人中心</a></li>
                </ul>
        </div>
        </div>
</div>
<div class="container">

    <div class="container-fluid">

        <table class="table table-hover">
            <tr>
                    <th>序号</th>
                    <th>股票代码</th>
                    <th>股票简称</th>
                    <th>涨跌幅</th>
                    <th>换手率</th>
                    <th>最新价(元)</th>
                    <th>前期高点</th>
                    <th>前期高点日期</th>
                    <th>添加自选</th>
            </tr>
            {%content%}
        </table>
    </div>
</div>
</body>
</html>            

center.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>个人中心 - 个人选股系统 V5.87</title>
  <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
  <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
    <script>
        $(document).ready(function(){
            // 发送ajax请求,获取个人中心数据
            $.get("center_data.html",function (data) {
                // ajax 成功回调函数
                console.log(data)
                // 获取table标签
                var $table = $(".table");
                // 如果指定了返回数据的解析方式是json,那么data就是一个js对象
                for(var i = 0; i < data.length; i++){
                    // 根据下标获取每一个个人中心数据js对象
                    var oCenterData = data[i];

                    // 封装后的每一个tr标签
                    var oTr = '<tr>' +
                                '<td>'+ oCenterData.code +'</td>' +
                                '<td>'+ oCenterData.short +'</td>' +
                                '<td>'+ oCenterData.chg +'</td>' +
                                '<td>'+ oCenterData.turnover +'</td>' +
                                '<td>'+ oCenterData.price +'</td>' +
                                '<td>'+ oCenterData.highs +'</td>' +
                                '<td>'+ oCenterData.note_info +'</td>' +
                                '<td><a type="button" class="btn btn-default btn-xs" href="/update/000007.html"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a></td>' +
                                '<td><input type="button" value="删除" id="toDel" name="toDel" systemidvaule="000007"></td>' +
                                '</tr>'
                    // 给table标签追加每一行tr标签
                    $table.append(oTr)

                }

            }, "json");
            $("input[name='toDel']").each(function(){
                var currentAdd = $(this);
                currentAdd.click(function(){
                    code = $(this).attr("systemIdValue");
                    alert("/del/" + code + ".html");
                    $.get("/del/" + code + ".html", function(data, status){
                        alert("数据: " + data + "\n状态: " + status);
                    });
                    window.location.reload()
                });
            });
        });
    </script>
</head>

<body>
<div class="navbar navbar-inverse navbar-static-top ">
        <div class="container">
        <div class="navbar-header">
                <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                 </button>
                 <a href="#" class="navbar-brand">选股系统</a>
        </div>
        <div class="collapse navbar-collapse" id="mymenu">
                <ul class="nav navbar-nav">
                        <li ><a href="./index.html">股票信息</a></li>
                        <li class="active"><a href="">个人中心</a></li>
                </ul>

        </div>
        </div>
</div>
<div class="container">

    <div class="container-fluid">

        <table class="table table-hover">
            <tr>
                    <th>股票代码</th>
                    <th>股票简称</th>
                    <th>涨跌幅</th>
                    <th>换手率</th>
                    <th>最新价(元)</th>
                    <th>前期高点</th>
                    <th style="color:red">备注信息</th>
                    <th>修改备注</th>
                    <th>del</th>
            </tr>
            {%content%}
        </table>
    </div>
</div>
</body>
</html>            

web.py

import socket
import threading
import exercise_03_framework_decorator


class HttpWebServer(object):
    def __init__(self):
        # 创建tcp服务端套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置端口号复用,程序退出端口号立即释放
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 绑定端口号
        tcp_server_socket.bind(("", 8000))
        # 设置监听
        tcp_server_socket.listen(128)
        # 把tcp服务器的套接字作为web服务器对象的属性
        self.tcp_server_socket = tcp_server_socket

    # 启动服务器的方法
    def start(self):
        # 循环等待接收客户端的连接请求
        while True:
            # 等待接收客户端的请求
            new_socket, ip_port = self.tcp_server_socket.accept()
            # 代码执行到此,说明链接建立成功
            sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))
            # 设置成为守护主线程
            sub_thread.setDaemon(True)
            # 启动子线程执行对应任务
            sub_thread.start()

    # 处理客户请求
    @staticmethod
    def handle_client_request(new_socket):
        # 接收客户端的请求信息
        recv_data = new_socket.recv(4906)
        # 判断接受的数据长度是否为0
        if recv_data == 0:
            new_socket.close()
            return
        # 对二进制数据进行编码
        recv_content = recv_data.decode("utf-8")
        print(recv_content)

        # 对数据按照空格进行分割 (maxsplit 分割次数)
        request_list = recv_content.split(" ", maxsplit=2)
        # 获取请求的资源路径
        request_path = request_list[1]
        print(request_path)

        # 判断请求的是否是根目录,如果是返回设定信息
        if request_path == "/":
            request_path = "/index.html"

        # 判断是否是动态资源请求,将后缀是.html的请求任务定为动态资源请求
        if request_path.endswith(".html"):
            """动态资源请求"""
            # 动态资源请求找web框架进行处理,需要补请求参数给web框架
            # 准备给web框架的参数信息,都要放到字典中
            env = {
                "request_path": request_path,
                # 传入请求头信息,额外的参数可以再字典里面再进行添加

            }
            # 使用框架处理动态资源请求
            # 1. web框架需要把处理器结果返回web服务器
            # 2. web服务器负责把返回的结果封装成响应报文发送给浏览器
            status, headers, response_body = exercise_03_framework_decorator.handle_request(env)
            # 响应行
            response_line = f"HTTP/1.1 {status}\r\n"
            # 响应头
            response_header = ""
            for header in headers:
                response_header += "%s: %s\r\n" % header

            # 响应报文
            response_data = (
                    response_line +
                    response_header +
                    "\r\n" +
                    response_body).encode("utf-8")
            # 发送响应报文数据给浏览器
            new_socket.send(response_data)
            # 关闭连接
            new_socket.close()

        else:
            """静态资源请求"""
            '''判断文件是否存在,方法一
            os.path.exits("static/"  + request_path)
            '''
            # 判断文件是否存在,方法二
            try:
                # 打开文件读取文件信息   rb兼容打开图片文件
                with open("static" + request_path, "rb") as file:  # 这里的file表示打开文件的对象
                    file_data = file.read()
                # with open 省去open中的close关闭步骤
            except Exception as c:
                # 相应行
                response_line = "HTTP/1.1 404 Not Found\r\n"
                # 响应头
                response_header = "Server: PWS/1.0\r\n"
                # 读取404页面数据
                with open("static/error.html", "rb") as file:
                    file_data = file.read()
                # 响应体
                response_body = file_data

                # 把数据封装成http 响应报文格式的数据
                response = (response_line + response_header + "\r\n").encode("utf-8") + response_body
                # 发送给浏览器的响应报文数据
                new_socket.send(response)
            else:
                # 相应行
                response_line = "HTTP/1.1 200 OK\r\n"
                # 响应头
                response_header = "Server: PWS/1.0\r\n"
                # 读取404页面数据
                with open("static/error.html", "rb") as file:
                    file_data = file.read()
                # 响应体
                response_body = file_data

                # 把数据封装成http 响应报文格式的数据
                response = (response_line + response_header + "\r\n").encode("utf-8") + response_body
                # 发送给浏览器的响应报文数据
                new_socket.send(response)
            finally:
                # 关闭服务于客户端的套接字
                new_socket.close()


def main():
    # 创建web服务器
    web_server = HttpWebServer()
    # 启动服务器
    web_server.start()


if __name__ == '__main__':
    main()

搭建框架

framework.py

"""web框架的职责专门负责处理动态资源请求"""
import pymysql
import json

route_list = [
    # ("/index.html", index),
    # ("/center.html", center),
]


# 定义一个带参数的路由装饰器
def route_decorator(path):
    def decorator(func):
        # 当执行装饰器的时候向路由列表添加路由
        # 但装饰函数的时候添加一次即可
        route_list.append((path, func))

        def inner():
            result = func()
            return result
        return inner
    return decorator


# 个人中心数据接口
@route_decorator("/center_data.html")
def center_data():
    # 从数据库把数据查询出来,然后把查询处理的数据转成json数据
    # 创建连接对象
    conn = pymysql.connect(host="192.168.137.138",
                           port=3306,
                           user="root",
                           password="root",
                           database="stock_db",
                           charset="utf8")
    # 获取游标
    cursor = conn.cursor()
    # 获取sql,并执行sql
    cursor.execute('''select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info
                   from info i inner join focus f 
                   on f.info_id = i.id;
                   ''')
    # 获取结果集
    result = cursor.fetchall()
    print(result)
    # 把元组转成列表字典
    center_data_list = [{"code": row[0],
                         "short": row[1],
                         "chg": row[2],
                         "turnover": row[3],
                         "price": str(row[4]),
                         "highs": str(row[5]),
                         "note_info": row[6]
                         } for row in result]
    print(center_data_list)
    # 把列表转成json字符串数据
    # ensure_ascii=False 表示再控制台能够显示中文
    json_str = json.dumps(center_data_list, ensure_ascii=False)
    print(json_str)
    print(type(json_str))
    cursor.close()
    conn.close()
    # 状态信息
    status = "200 OK"
    # 响应头信息
    response_header = [
        ("Server", "PWS/1.1"),
        # 指定编码格式,因为没有模板文件,可以通过响应头指定编码格式
        ("Content-Type", "text/html;charset=utf-8")
    ]
    return status, response_header, json_str


# 获取个人中心信息
@route_decorator("/center.html")    # @route_decorator => @decorator => index = decorator(index)
def center():
    # 状态信息
    status = "200 OK"
    # 响应头信息
    response_header = [("Server", "PWS/1.1")]
    # 1. 打开指定模拟文件,读取模拟文件的数据
    with open("template/center.html", "r", encoding="UTF-8") as file:
        file_data = file.read()
    # 2. 查询数据库,模板里面的模板变量{%content%} 替换成以后数据库里面查询的数据
    # web处理后的数据

    response_body = file_data.replace("{%content%}", "")
    # 返回数据,返回的是元组
    return status, response_header, response_body


# 获取主页信息
@route_decorator("/index.html")
def index():
    # 状态信息
    status = "200 OK"
    # 响应头信息
    response_header = [("Server", "PWS/1.1")]
    # 1. 打开指定模拟文件,读取模拟文件的数据
    with open("template/index.html", "r", encoding="UTF-8") as file:
        file_data = file.read()
    # 2. 查询数据库,模板里面的模板变量{%content%} 替换成以后数据库里面查询的数据
    # web处理后的数据,从数据库查询
    conn = pymysql.connect(host="192.168.137.138",
                           user="root",
                           password="root",
                           port=3306,
                           database="stock_db",
                           charset="utf8")
    # 获取游标
    cursor = conn.cursor()
    # 查询sql语句
    sql = "select * from info;"
    # 执行sql
    cursor.execute(sql)
    # 获取结果集
    result = cursor.fetchall()
    print(result)
    cursor.close()
    conn.close()

    # 遍历每一条数据,完成数据的tr标签封装
    data = ""
    for row in result:
        data += """<tr>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="000007"></td>
               </tr>""" % row
    response_body = file_data.replace("{%content%}", data)
    # 返回数据,返回的是元组
    return status, response_header, response_body


def not_found():
    # 状态信息
    status = "404 Not Found"
    # 响应头信息
    response_header = [("Server", "PWS/1.1")]
    # web处理后的数据
    data = "Not Found"

    # 返回数据,返回的是元组
    return status, response_header, data


# 处理动态资源请求
def handle_request(env):
    # 获取动态资源请求的路径
    request_path = env["request_path"]
    print("动态资源请求的地址", request_path)
    # 判断请求的动态资源路径,选择知道那个的函数处理对应的动态资源请求
    for path, func in route_list:
        if request_path == path:
            # 获取首页数据
            result = func()
            # 把处理后的结果返回给web服务器使用,让web服务器拼接响应报文使用
            return result
    else:
        # 没有动态资源数据,返回404状态信息
        result = not_found()
        # 把处理后的结果返回给web服务器使用,让web服务器拼接响应报文使用
        return result



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值