web框架

1. 今日目标

2.【了解】WEB框架概念

  • 静态资源:可以提前准备的,不经常改变的资源。(png,jpg,css,js等)

  • 动态资源:不能提前准备的,经常改变的资源。(html)

  • Web框架:为web服务器提供动态请求服务的程序

  • WSGI协议(了解): web服务器和web框架通信规则.

3.【应用】miniWeb框架开发

  • 框架职责:

    接收web服务器的动态资源请求,给web服务器提供处理动态资源请求的服务。

  • 判断动态资源

    • 根据请求资源路径的后缀名进行判断

      • 如果请求资源路径的后缀名是.html则是动态资源请求, 让web框架程序进行处理。

      • 否则是静态资源请求,让web服务器程序进行处理。

  • 处理客户端的动态资源请求

    1. 创建web框架程序

    2. 接收web服务器的动态资源请求

    3. 处理web服务器的动态资源请求并把处理结果返回给web服务器

    4. web服务器把处理结果组装成响应报文发送给浏览器

  • 核心代码:

  • Web.py

            # 1.根据请求资源路径的后缀判断是否动态资源(.html的资源是动态资源)
           if request_path.endswith(".html"):
               """动态资源请求"""
               # 1.1 准备请求资源信息
               request_info = {
                   "request_path": request_path
                   # ....
              }

               #   2.如果是动态请求,把动态请求交给web框架处理。
               #   3.WEB框架处理动态请求,把处理结果返回给web服务器
               data = framework.handler_request(request_info)
               status, headers, body = data

               #   4.web服务器把处理结果拼接成响应报文返回给web浏览器
               #   响应行
               #       协议版本 状态码 状态描述
               #   响应头
               #   空行
               #   响应体

               #   响应行
               #       协议版本 状态码 状态描述

               response_line = "HTTP/1.1 %s " % status

               response_head = ""
               for header in headers:
                   # response_head += f"{header[0]}: {header[1]}"
                   response_head += "%s: %s " % header

               response_body = body

               response_data = (response_line + response_head + " " + response_body).encode("utf-8")

               new_socket.send(response_data)

           else:
               """静态资源请求"""
    • framework.py



    import time


    # 返回/index.html的响应数据
    def index():
       # 响应状态信息
       status = "200 OK"
       # 响应头信息
       headers = [("Server", "NBW/2.0")]
       # 响应体信息 = 模板 + 数据库数据
       body = time.ctime()

       return status, headers, body


    # 返回404页面的响应数据
    def not_found():
       # 响应状态信息
       status = "404 Not Found"
       # 响应头信息
       headers = [("Server", "NBW/2.0")]
       # 响应体信息 = 模板 + 数据库数据
       body = "Not Found"

       return status, headers, body



    def handler_request(request_info):
       # 2.接收web服务器的动态资源请求
       request_path = request_info['request_path']
       print("web服务器发送的动态请求路径: ", request_path)

       # 3.处理web服务器的动态资源请求并把处理结果返回给web服务器
       if request_path == "/index.html":
           data = index()
           return data

       else:
           data = not_found()
           return data

4.【应用】模板替换

  • 思路

    • 拷贝资源(templates)到工程下

    • 在函数中读取对应的模板文件

      with open("template/index.html", "r") as file:
      file_data = file.read()
    • 使用正则替换网页中的内容 {%content%}

      body = file_data.replace("{%content%}", time.ctime())
    • 返回替换后的内容

      return status, headers, body

5.【应用】路由列表功能开发(django)

  • 路由是请求的URL到处理函数的映射

  • 路由列表是用来保存每一个设置好的路由

    • 在路由列表中添加路由

      route_list = [
      ("/index.html", index),
      ("/center.html", center)
      ]
  • 用户的动态资源请求通过遍历路由列表找到对应的处理函数来完成。

    • 根据用户请求遍历路由列表处理用户请求

      for path, func in route_list:
      if request_path == path:
      data = func()
      return data

      else:
      data = not_found()
      return data

6.【应用】路由装饰器(flask)

  • 使用带有参数的装饰器对处理函数进行装饰,并完成路由的添加功能。

    • 定义路由列表

      route_list = []
    • 定义带有参数的装饰器

      def route(path):

      def decorator(func):
      route_list.append((path, func))
         
          def inner():
              return func()
          return inner

      return decorator
    • 装饰处理函数

      @route("/index.html")
      def index():
      ...

      @route("/center.html")
      def center():
      ...

7.【应用】显示股票信息页面的开发

  • 创建并导入数据到数据库

    • 创建数据库  create database stock_db charset=utf8

    • 使用数据库 use stock_db

    • 导入数据库(先客户端登录)

      • 准备脚本文件

      • 导入脚本   source stock_db.sql

  • 修改index函数

    • 连接数据库,获取数据

      • 导入模块

      • 建立连接

      • 创建游标

      • 使用游标执行sql

      • 获取查询的结果

        info_list = cs.fetchall()   # ((),(),(),...)
      • 关闭资源

        先关闭游标,在关闭连接

    • 替换为查询的数据

      • 思路:

        • 把查询的数据进行遍历,并且拼接html格式的文本

           body = ""
          # info : 就是元组类型, 直接实现字符串拼接
          for info in info_list:
              body += """<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>""" % info
        • 替换为拼接后的字符串

           # 3.3.替换模板中的变量为数据
          # replace: 字符串替换函数
          body = file_data.replace("{%content%}", body)
        • 注意:

          %s %s %s   ---> row        # row 是一个元组

    • 核心代码

      # 返回/index.html的响应数据
      @route("/index.html") # 1.route("/index.html") 2.@decorator -> index=decorator(index)
      def index():    # 0x11
      # 响应状态信息
      status = "200 OK"
      # 响应头信息
      headers = [("Server", "NBW/2.0")]
      # 响应体信息 = 模板 + 数据库数据
      body = time.ctime()

      # 2.1.打开模板文件
      with open("template/index.html", "r") as file:
          file_data = file.read()

      # 3.1.1.根据sql语句查询股票信息
      # 1)创建链接对象
      # 2)获取游标
      # 3)执行sql语句
      #   3.1) 提交
      # 4)获取查询的结果
      # 5)关闭游标
      # 6)关闭链接
      conn = pymysql.connect(host='127.0.0.1', port=3306,
                             user="root", password="mysql",
                             database="stock_db", charset="utf8")
      cs = conn.cursor()
      sql = "select * from info;"
      count = cs.execute(sql)
      print("查询到%d行数据" % count)
      info_list = cs.fetchall()
      # ((1, '000007', '全新好', '10.01%', '4.40%', Decimal('16.05'), Decimal('14.60'), datetime.date(2017, 7, 18)), ...)
      print(info_list)      # ((一行数据),(),(),(),...)
      cs.close()
      conn.close()

      # 3.2.替换模板中的变量为数据
      # 3.2.1 使用查询数据转换成前端需要的html代码

      body = ""
      # info : 就是元组类型, 直接实现字符串拼接
      for info in info_list:
          body += """<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>""" % info

      # 3.3.替换模板中的变量为数据
      # replace: 字符串替换函数
      body = file_data.replace("{%content%}", body)

      return status, headers, body

8.【应用】个人中心数据接口的开发

  • 接口开发目的:前后端分离

  • 根据sql语句查询个人中心数据

    • 拼接两张表,显示个人中心数据

       sql = "select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info from info i inner join focus f on i.id=f.info_id;"
  • 将个人中心数据转成json字符串并返回

    • 创建个人中心列表

      center_data_list = []
    • 遍历每行数据转换成字典

    • 添加字典到列表中

      for row in center_list:
      center_dict = {}
      center_dict['code'] = row[0]
      center_dict['short'] = row[1]
      center_dict['chg'] = row[2]
      center_dict['turnover'] = row[3]
      center_dict['price'] = str(row[4])
      center_dict['highs'] = str(row[5])
      center_dict['note_info'] = row[6]
      center_data_list.append(center_dict)
    • 把列表字典转成json字符串, 并在控制台显示

      json_str = json.dumps(center_data_list, ensure_ascii=False)
      print( type(json_str), json_str)
  • 浏览器通过指定接口地址获取web框架提供的数据。

    • 127.0.0.1:9090/center_data.html

9.【应用】ajax请求数据渲染个人中心页面

  • 根据用户请求返回个人中心空模板文件数据

    • 打开模板文件,读取数据

      # 2.1.打开模板文件
      with open("template/center.html", "r") as file:
      file_data = file.read()
    • 替换模板文件中的%{content}%

    body = ""
    # 2.2.替换模板中的变量为数据
    # replace: 字符串替换函数
    body = file_data.replace("{%content%}", body)
  • 在个人中心模板文件添加ajax请求获取个人中心数据

    • 发送ajax请求获取个人中心页面数据: $.get()

      $.get("center_data.html", function (response) {
      console.log(response);
      },"JSON").error(function () {
      alert("链接失败,请重新链接.")
      });
  • 将个人中心数据在页面完成展示

    • 获取table标签元素对象

      var $table = $(".table");
    • 遍历数据列表获取每一个对象

    • 拼接html格式的文本

    • 拼接的html数据加入table标签中

      for(var i = 0; i < response.length; i++){
      // 获取数组对象
      var oBj = response[i];
      // 拼接成html展示的效果.
      var sTr = '<tr> ' +
          '           <td>'+oBj.code+'</td> ' +
          '           <td>'+oBj.short+'</td> ' +
          '           <td>'+oBj.chg+'</td> ' +
          '           <td>'+oBj.turnover+'</td> ' +
          '           <td>'+oBj.price+'</td> ' +
          '           <td>'+oBj.highs+'</td> ' +
          '           <td>'+oBj.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.append(sTr);
      }

10.【了解】logging日志

  • 介绍:记录程序运行状态信息

  • 作用:

    • 记录程序运行状态信息

    • 收集用户的行为和喜好

    • 调bug

  • 级别:

    1. DEBUG

    2. INFO

    3. WARNING

    4. ERROR

    5. CRITICAL

  • 使用:

    • 导入模块

      import logging
    • 输入到控制台

      logging.debug("这是一个debug级别信息")
      logging.info("这是一个info级别信息")
      logging.warning("这是一个warning级别信息")
      logging.error("这是一个error级别信息")
      logging.critical("这是一个cirtical级别信息")
    • 设置输出级别和格式

      logging.basicConfig(level=logging.DEBUG,
                      format="%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'",
                      filename="log.txt",
                      filemode="w")
  • logging日志在mini-web项目中应用:

    • INFO级别:静态请求或者动态请求

    • WARNING级别:参数传递错误

    • ERROR级别:404 异常

11. 总结

原文地址:https://www.cnblogs.com/zhangwei112/p/13586898.html