美文网首页Web
Python web框架开发 - 模板功能 - 添加数据

Python web框架开发 - 模板功能 - 添加数据

作者: Devops海洋的渔夫 | 来源:发表于2019-01-06 19:42 被阅读230次

    原创仅供学习,转载请注明出处

    前情回顾

    前一篇写了Python web框架开发 - 模板功能 - 肥仔们的爱好关于模板功能。

    功能需求 - 添加数据

    那么下面继续深入,考虑一下如何添加数据到table中呢?

    要做这个交互效果的话,就要改改原始的HTML页面了。

    修改如下:

    增加两个添加按钮,方便后续点击发送添加的请求。代码如下:

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <body>
        <table border="1px">
            <thead>
                <th>肥仔id</th>      
                <th>肥仔名称</th>      
                <th>肥仔爱好</th>      
                <th>肥仔职业</th>      
                <th>肥仔居住地</th>      
            </thead>
            <tbody>
                <tr>
                    <td>1</td>
                    <td>胖子老板</td>
                    <td>斗地主</td>
                    <td>小卖部老板</td>
                    <td>西九龙</td>
                    <td><button type="submit"><a href="fat_boy_add/1.html">添加</a></button></td>
                </tr>
                <tr>
                    <td>2</td>
                    <td>肥仔白</td>
                    <td>吃槟榔、打dota</td>
                    <td>挨踢男</td>
                    <td>铜锣湾</td>
                    <td><button type="submit"><a href="fat_boy_add/2.html">添加</a></button></td>
                </tr>
            </tbody>
        </table>
    </body>
    </html>
    

    点击添加会发送GET请求如下:

    fat_boy_add/1.html 其中这里的 1 代表的就是这条数据的 id ,用于后续查询数据后,进行数据插入的条件。

    那么先把该页面放入项目中,尝试访问看看。

    编写fat_boy_add路由,提供页面访问

    # fat_boy_add
    @route("fat_boy_add")
    def fat_boy_add(file_path):
        print("file_path=",file_path)
    
        # 创建Connection连接
        conn = connect(host='localhost', port=3306, user='root', password='', database='test_db', charset='utf8')
        # 获得Cursor对象
        cs1 = conn.cursor()
        # 执行select语句,并返回受影响的行数:查询一条数据
        count = cs1.execute('select * from fatboy_hobby;')
        # 打印受影响的行数
        print("查询到%d条数据:" % count)
    
        # 需要拼接的HTML内容
        """
         <tr>
            <td>1</td>
            <td>胖子老板</td>
            <td>斗地主</td>
            <td>小卖部老板</td>
            <td>西九龙</td>
            <td><button type="submit"><a href="fat_boy_add/1.html">添加</a></button></td>
        </tr>
        """
        content = ""
    
        for i in range(count):
            # 获取查询的结果
            result = cs1.fetchone()
            # 打印查询的结果
            print(result)
            # 获取查询的结果
            print("肥仔名称=%s" % result[0])
            print("肥仔爱好=%s" % result[1])
            print("肥仔职业=%s" % result[2])
            print("肥仔居住地=%s" % result[3])
            content += """
                 <tr>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td><button type="submit"><a href="fat_boy_add/%s.html">添加</a></button></td>
                </tr>
            """ % (result[0],result[1],result[2],result[3],result[4],result[0])
            # print("content",content.encode("utf-8"))
    
        # 关闭Cursor对象
        cs1.close()
        conn.close()
    
        file_path = re.sub(r".py", ".html", file_path)
        with open(file_path,"rb") as f:
            # html_content = f.read()
            html_content = str(f.read().decode("utf-8"))
    
        # 使用正则匹配替换<{content}>
    
        ret = re.sub(r"<{content}>", content, html_content)
    
        # print("html_content=",ret)
    
        # 返回html内容
        return ret.encode("utf-8")
    

    测试运行看看:

    好了,这里是可以正常访问的,但是有个问题,尝试能否访问添加按钮的页面。

    这里由于超链接访问的是 fat_boy_add/1.py 的路径,这个路径在原来的匹配规则是不无法对应出函数的。

    修改匹配函数的规则

    那么按照现在的请求url来看,主要是要匹配这几种url路径,如下:

    • ./html/index.py
    • ./html/fat_boy_add/1.py

    要求都只要匹配出 indexfat_boy_add 的函数名即可。

    下面来测试编写一下正则规则:

    In [1]: import re
    
    In [2]: index_path = "./html/index.py"
    
    In [3]: fat_boy_add_path = "./html/fat_boy_add/1.py"
    
    ## 首先按照原来的匹配一次
    In [34]: ret = re.match(r"./html/[^.]+",index_path).group()
    
    In [35]: ret
    Out[35]: './html/index'
    
    ## 使用二次正则匹配到 / 为止的分组内容,就是index函数名了。
    In [41]: re.match(r"./html/([^/]+)",ret).group(1)
    Out[41]: 'index'
    
    ## 可以看到,匹配到 点 之前的数据,那么下面要对该结果进行二次正则,匹配到 / 之前的就是函数名了。
    In [42]: ret =  re.match(r"./html/[^.]+",fat_boy_add_path).group()
    
    ## 使用二次匹配到 / 为止的分组内容
    In [43]: re.match(r"./html/([^/]+)",ret).group()
    Out[43]: './html/fat_boy_add'
    
    ## 查看分组就是 fat_boy_add的函数名了。
    In [44]: re.match(r"./html/([^/]+)",ret).group(1)
    Out[44]: 'fat_boy_add'
    
    In [45]:
    

    将正则匹配应用到代码中看看。

    那么下面来测试一下:

    访问index.py路径是正常的,再来试试其他的路径:

    访问fat_boy_add.py也是正常的,尝试点击添加再来访问一下:

    修正fat_boy_add/1.py请求的打开页面

    再次测试访问看看:

    好了,到了这里这个添加的请求也是能够正常返回页面了。那么下一步要实现的功能就是根据发过来路径中的id,插入一条同样内容的数据。

    获取id如下路径: ./html/fat_boy_add/1.py 那么这个 id 就是 1

    根据路径传递过来的id,进行数据插入

    首先使用正则匹配出id出来先,测试如下:

    In [45]: import re
    
    In [46]: file_path = "./html/fat_boy_add/1.py"
    
    In [47]: re.match(r"./html/fat_boy_add/\d.py",file_path).group()
    Out[47]: './html/fat_boy_add/1.py'
    
    In [48]: re.match(r"./html/fat_boy_add/(\d).py",file_path).group(1)
    Out[48]: '1'
    
    In [49]: 
    

    好了,有了id的值之后,就可以首先写个插入的SQL语句。

    查询当前表里的数据:

    insert into fatboy_hobby
    select null,name,hobby,professional,address from fatboy_hobby where id=1;
    

    执行之后的表数据如下:

    那么下面添加数据的功能实现就基本清楚了,实现思路大致如下:

    • 使用正则匹配出id的数值
    • 根据id查询出来的结果,插入表中即可

    代码实现如下:

    实现效果如下:

    好了,写到这里已经实现了添加数据的功能了。

    相信写到这里,应该也清楚如何去写删除了,也是根据获取的id,来执行删除即可。

    完整代码如下:

    fat_boy_add.html

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <body>
        <table border="1px">
            <thead>
                <th>肥仔id</th>      
                <th>肥仔名称</th>      
                <th>肥仔爱好</th>      
                <th>肥仔职业</th>      
                <th>肥仔居住地</th>      
            </thead>
            <tbody>
                <tr>
                    <{content}>
            </tbody>
        </table>
    </body>
    </html>
    

    framwork.py

    import re
    from pymysql import *
    
    # 设置路由对应的字典
    route_dict = dict()
    """
    route_dict = {
        "index" : index,
        "page_about" : page_about,
    }
    """
    def route(url):
        def set_route(func):
            # 设置字典映射
            route_dict[url] = func
            def call_func(file_path):
                return func(file_path)
            return call_func
        return set_route
    
    # index页面
    @route("index")
    def index(file_path):
        file_path = re.sub(r".py", ".html", file_path)
        with open(file_path,"rb") as f:
            return f.read()
    
    # page_about页面
    @route("page_about")
    def page_about(file_path):
        file_path = re.sub(r".py", ".html", file_path)
        with open(file_path,"rb") as f:
            return f.read()
    
    # fat_boy页面
    @route("fat_boy")
    def fat_boy(file_path):
        # 创建Connection连接
        conn = connect(host='localhost', port=3306, user='root', password='', database='test_db', charset='utf8')
        # 获得Cursor对象
        cs1 = conn.cursor()
        # 执行select语句,并返回受影响的行数:查询一条数据
        count = cs1.execute('select * from fatboy_hobby;')
        # 打印受影响的行数
        print("查询到%d条数据:" % count)
    
        # 需要拼接的HTML内容
        """
         <tr>
            <td>1</td>
            <td>胖子老板</td>
            <td>斗地主</td>
            <td>小卖部老板</td>
            <td>西九龙</td>
        </tr>
        <tr>
            <td>2</td>
            <td>肥仔白</td>
            <td>吃槟榔、打dota</td>
            <td>挨踢男</td>
            <td>铜锣湾</td>
        </tr>
        """
        content = ""
    
        for i in range(count):
            # 获取查询的结果
            result = cs1.fetchone()
            # 打印查询的结果
            print(result)
            # 获取查询的结果
            print("肥仔名称=%s" % result[0])
            print("肥仔爱好=%s" % result[1])
            print("肥仔职业=%s" % result[2])
            print("肥仔居住地=%s" % result[3])
            content += """
                 <tr>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                </tr>
            """ % (result[0],result[1],result[2],result[3],result[4])
            print("content",content.encode("utf-8"))
    
        # 关闭Cursor对象
        cs1.close()
        conn.close()
    
        file_path = re.sub(r".py", ".html", file_path)
        with open(file_path,"rb") as f:
            # html_content = f.read()
            html_content = str(f.read().decode("utf-8"))
    
        # 使用正则匹配替换<{content}>
    
        ret = re.sub(r"<{content}>", content, html_content)
    
        print("html_content=",ret)
    
        # 返回html内容
        return ret.encode("utf-8")
    
    # fat_boy_add
    @route("fat_boy_add")
    def fat_boy_add(file_path):
        print("file_path=",file_path)
    
        # 获取插入数据的选择 id
        id = re.match(r"./html/fat_boy_add/(\d).py", file_path).group(1)
    
        # 创建Connection连接
        conn = connect(host='localhost', port=3306, user='root', password='', database='test_db', charset='utf8')
        # 获得Cursor对象
        cs1 = conn.cursor()
    
        # 插入数据
        insert_sql = """
            insert into fatboy_hobby
            select null,name,hobby,professional,address from fatboy_hobby where id=%s;
        """ % id
        count = cs1.execute(insert_sql)
    
        #打印受影响的行数
        print(count)
    
        # 提交之前的操作,如果之前已经之执行过多次的execute,那么就都进行提交
        conn.commit()
    
        # 执行select语句,并返回受影响的行数:查询一条数据
        count = cs1.execute('select * from fatboy_hobby;')
        # 打印受影响的行数
        print("查询到%d条数据:" % count)
    
        # 需要拼接的HTML内容
        """
         <tr>
            <td>1</td>
            <td>胖子老板</td>
            <td>斗地主</td>
            <td>小卖部老板</td>
            <td>西九龙</td>
            <td><button type="submit"><a href="fat_boy_add/1.html">添加</a></button></td>
        </tr>
        """
        content = ""
    
        for i in range(count):
            # 获取查询的结果
            result = cs1.fetchone()
            # 打印查询的结果
            print(result)
            # 获取查询的结果
            print("肥仔名称=%s" % result[0])
            print("肥仔爱好=%s" % result[1])
            print("肥仔职业=%s" % result[2])
            print("肥仔居住地=%s" % result[3])
            content += """
                 <tr>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td><button type="submit"><a href="%s.py">添加</a></button></td>
                </tr>
            """ % (result[0],result[1],result[2],result[3],result[4],result[0])
            # print("content",content.encode("utf-8"))
    
    
        # 关闭Cursor对象
        cs1.close()
        conn.close()
    
        # file_path = re.sub(r".py", ".html", file_path)
        file_path = "./html/fat_boy_add.html"
        with open(file_path,"rb") as f:
            # html_content = f.read()
            html_content = str(f.read().decode("utf-8"))
    
        # 使用正则匹配替换<{content}>
    
        ret = re.sub(r"<{content}>", content, html_content)
    
        # print("html_content=",ret)
    
        # 返回html内容
        return ret.encode("utf-8")
    
    # 支撑WGSI协议
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html;charset=UTF-8')])
        # 接受需要打开的文件路径
        print("动态file_path= ", environ['REQUEST_URI'])
    
        # 使用正则匹配路径中的函数方法
        try:
            # func_name = re.match(r"\./html/([^.]+)",environ['REQUEST_URI']).group(1)
            ## 第一次正则匹配到 小数点 . 的为止
            ret = re.match(r"\./html/([^.]+)",environ['REQUEST_URI']).group()
            ## 第二次正则匹配到 斜杠 / 为止
            func_name = re.match(r"./html/([^/]+)",ret).group(1)
        except Exception as e:
            print("匹配不上,%s" % e)
        else:
            response_body = route_dict[func_name](environ['REQUEST_URI'])
    
        return response_body
    

    webserver.py

    #coding=utf-8
    from socket import *
    import re
    import multiprocessing
    import time
    import framework
    import sys
    
    class WebServer:
    
       def __init__(self,server_port):
    
           # 创建套接字
           self.server_socket = socket(AF_INET, SOCK_STREAM)
           # 设置当服务器先close 即服务器端4次挥手之后资源能够立即释放,这样就保证了,下次运行程序时 可以立即绑定7788端口
           self.server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
           # 设置服务端提供服务的端口号
           self.server_socket.bind(('', server_port))
           # 使用socket创建的套接字默认的属性是主动的,使用listen将其改为被动,用来监听连接
           self.server_socket.listen(128) #最多可以监听128个连接
    
       def start_http_service(self):
           # 开启while循环处理访问过来的请求
           while True:
               # 如果有新的客户端来链接服务端,那么就产生一个新的套接字专门为这个客户端服务
               # client_socket用来为这个客户端服务
               # self.server_socket就可以省下来专门等待其他新的客户端连接while True:
               client_socket, clientAddr = self.server_socket.accept()
               # handle_client(client_socket)
               # 设置子进程
               new_process = multiprocessing.Process(target=self.handle_client,args=(client_socket,))
               new_process.start() # 开启子进程
               # 因为子进程已经复制了父进程的套接字等资源,所以父进程调用close不会将他们对应的这个链接关闭的
               client_socket.close()
    
       def handle_client(self,client_socket):
           """为一个客户端服务"""
           # 接收对方发送的数据
           recv_data = client_socket.recv(1024).decode("utf-8") #  1024表示本次接收的最大字节数
           # 打印从客户端发送过来的数据内容
           #print("client_recv:",recv_data)
           request_header_lines = recv_data.splitlines()
           for line in request_header_lines:
               print(line)
    
           # 返回浏览器数据
           # 设置内容body
           # 使用正则匹配出文件路径
           print("------>",request_header_lines[0])
           print("file_path---->","./html/" + re.match(r"[^/]+/([^\s]*)",request_header_lines[0]).group(1))
           ret = re.match(r"[^/]+/([^\s]*)",request_header_lines[0])
           if ret:
              file_path = "./html/" + ret.group(1)
              if file_path == "./html/":
                 file_path = "./html/index.html"
              print("file_path *******",file_path)
    
           # 判断file_path是否py文件后缀,如果是则请求动态资源,否则请求静态资源
           if file_path.endswith(".py"):
    
               # framework.application(client_socket)
               # 支撑WGSI协议的调用方式
               environ = {}
               environ['REQUEST_URI'] = file_path # 设置需要打开的文件路径
               response_body = framework.application(environ, self.start_response)
               # 设置返回的头信息header
               # 1.拼接第一行HTTP/1.1 200 OK + 换行符内容
               response_headers = "HTTP/1.1 " + self.application_header[0] + "\r\n"
               # 2.循环拼接第二行或者多行元组内容:Content-Type:text/html
               for var in self.application_header[1]:
                   response_headers += var[0]+":"+var[1] + "\r\n"
               # 3.空一行与body隔开
               response_headers += "\r\n"
               # 4.打印看看header的内容信息
               print("response_header=")
               print(response_headers)
    
               # 设置返回的浏览器的内容
               client_socket.send(response_headers.encode("utf-8"))
               client_socket.send(response_body)
    
           else:
               # 请求静态资源
               try:
                  # 设置返回的头信息 header
                  response_headers = "HTTP/1.1 200 OK\r\n" # 200 表示找到这个资源
                  response_headers += "\r\n" # 空一行与body隔开
                  # 读取html文件内容
                  file_name = file_path # 设置读取的文件路径
                  f = open(file_name,"rb") # 以二进制读取文件内容
                  response_body = f.read()
                  f.close()
                  # 返回数据给浏览器
                  client_socket.send(response_headers.encode("utf-8"))   #转码utf-8并send数据到浏览器
                  client_socket.send(response_body)   #转码utf-8并send数据到浏览器
               except:
                  # 如果没有找到文件,那么就打印404 not found
                  # 设置返回的头信息 header
                  response_headers = "HTTP/1.1 404 not found\r\n" # 200 表示找到这个资源
                  response_headers += "\r\n" # 空一行与body隔开
                  response_body = "<h1>sorry,file not found</h1>"
                  response = response_headers + response_body
                  client_socket.send(response.encode("utf-8"))
    
       def start_response(self,status,header):
           self.application_header = [status,header]
           print("application_header=",self.application_header)
    
    def main():
        # 通过sys.argv来获取服务端的端口号
        # server_port = int(sys.argv[1])
        server_port = 7788
    
        webserver = WebServer(server_port)
        webserver.start_http_service()
    
    if __name__ == "__main__":
        main()
    

    关注微信公众号,回复【资料】、Python、PHP、JAVA、web,则可获得Python、PHP、JAVA、前端等视频资料。

    相关文章

      网友评论

        本文标题:Python web框架开发 - 模板功能 - 添加数据

        本文链接:https://www.haomeiwen.com/subject/pjbsrqtx.html