• 浅谈 Web框架


    一、Web框架本质

    • 所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端

    二、Web框架功能

    • socket收发消息 —— wsgiref(测试)、uwsgi(线上)

    • 根据不同的路径返回不同的字符串

    • 返回动态页面(字符串的替换)—— jinja2

    三、Web框架种类

    • django

      • 根据不同的路径返回不同的字符串

      • 返回动态页面(字符串的替换)

    • flask

      • 根据不同的路径返回不同的字符串

    • tornado

      • socket收发消息

      • 根据不同的路径返回不同的字符串

      • 返回动态页面(字符串的替换)

    四、自定义web框架

    • 简单示例:socket服务端

      import socket
      # 创建一个socket对象
      sk = socket.socket()
      # 绑定IP和端口
      sk.bind(('127.0.0.1', 8000))
      # 监听
      sk.listen(5)
      # 等待连接
      while True:
          conn, addr = sk.accept()
          # 接收数据
          data= conn.recv(1024)
          print(data)
          # 返回数据
          conn.send(b'HTTP/1.1 200 OK
      
      <h1>ok!</h1>')
          # 断开连接
          conn.close()
    • 根据不同路径返回不同的内容(普通版)

      import socket
      # 创建一个socket对象
      sk = socket.socket()
      # 绑定IP和端口
      sk.bind(('127.0.0.1', 8000))
      # 监听
      sk.listen(5)
      # 等待连接
      while True:
          conn, addr = sk.accept()
          # 接收数据
          data = conn.recv(1024)
          data = data.decode('utf-8')
          url = data.split()[1]
          conn.send(b'HTTP/1.1 200 OK
      
      ')
          if url == '/index/':
              # 返回数据
              conn.send(b'<h1>index!</h1>')
          elif url == '/home/':
              conn.send(b'<h1>home!</h1>')
          else:
              conn.send(b'<h1>404 not found!</h1>')
          # 断开连接
          conn.close()
      普通版
      import socket
      # 创建一个socket对象
      sk = socket.socket()
      # 绑定IP和端口
      sk.bind(('127.0.0.1', 8000))
      # 监听
      sk.listen(5)
      # 函数
      def index(url):
          ret = '<h1>index!</h1>({})'.format(url)
          return ret.encode('utf-8')
      def home(url):
          ret = '<h1>home!</h1>({})'.format(url)
          return ret.encode('utf-8')
      # 等待连接
      while True:
          conn, addr = sk.accept()
          # 接收数据
          data = conn.recv(1024)
          data = data.decode('utf-8')
          url = data.split()[1]
          conn.send(b'HTTP/1.1 200 OK
      
      ')
          if url == '/index/':
              # 返回数据
              ret = index(url)
          elif url == '/home/':
              ret = home(url)
          else:
              ret = b'<h1>404 not found!</h1>'
          conn.send(ret)
          # 断开连接
          conn.close()
      函数版
      import socket
      # 创建一个socket对象
      sk = socket.socket()
      # 绑定IP和端口
      sk.bind(('127.0.0.1', 8000))
      # 监听
      sk.listen(5)
      # 函数
      def index(url):
          ret = '<h1>index!</h1>({})'.format(url)
          return ret.encode('utf-8')
      def home(url):
          ret = '<h1>home!</h1>({})'.format(url)
          return ret.encode('utf-8')
      # 定义一个list1和实际要执行的函数的对应关系 
      list1 = [
          ('/index/', index),
          ('/home/', home),
      ]
      # 等待连接
      while True:
          conn, addr = sk.accept()
          # 接收数据
          data = conn.recv(1024)
          data = data.decode('utf-8')
          url = data.split()[1]
          conn.send(b'HTTP/1.1 200 OK
      
      ')
          func = None
          for i in list1:
              if url == i[0]:
                  func = i[1]
                  break
          if func:
              ret = func(url)
          else:
              ret = b'<h1>404 not found!</h1>'
          conn.send(ret)
          # 断开连接
          conn.close()
      函数进阶版
      import socket
      # 创建一个socket对象
      sk = socket.socket()
      # 绑定IP和端口
      sk.bind(('127.0.0.1', 8000))
      # 监听
      sk.listen(5)
      # 函数
      def index(url):
          with open('index.html','rb') as f:
              ret = f.read()
          return ret
      def home(url):
          ret = '<h1>home!</h1>({})'.format(url)
          return ret.encode('utf-8')
      # 定义一个list1和实际要执行的函数的对应关系
      list1 = [
          ('/index/', index),
          ('/home/', home),
      ]
      # 等待连接
      while True:
          conn, addr = sk.accept()
          # 接收数据
          data = conn.recv(1024)
          data = data.decode('utf-8')
          url = data.split()[1]
          conn.send(b'HTTP/1.1 200 OK
      
      ')
          func = None
          for i in list1:
              if url == i[0]:
                  func = i[1]
                  break
          if func:
              ret = func(url)
          else:
              ret = b'<h1>404 not found!</h1>'
          conn.send(ret)
          # 断开连接
          conn.close()
      返回html页面
      import socket
      import time
      # 创建一个socket对象
      sk = socket.socket()
      # 绑定IP和端口
      sk.bind(('127.0.0.1', 8000))
      # 监听
      sk.listen(5)
      # 函数
      def index(url):
          with open('index.html', 'rb') as f:
              ret = f.read()
          return ret
      def home(url):
          ret = '<h1>home!</h1>({})'.format(url)
          return ret.encode('utf-8')
      def timer(url):
          now = time.strftime('%H:%M:%S')
          with open('time.html','r',encoding='utf-8') as f:
              data = f.read()
          data = data.replace('xxtimexx',now)
      ​
          return data.encode('utf-8')
      # 定义一个list1和实际要执行的函数的对应关系
      list1 = [
          ('/index/', index),
          ('/home/', home),
          ('/time/', timer),
      ]
      # 等待连接
      while True:
          conn, addr = sk.accept()
          # 接收数据
          data = conn.recv(1024)
          data = data.decode('utf-8')
          url = data.split()[1]
          conn.send(b'HTTP/1.1 200 OK
      
      ')
          func = None
          for i in list1:
              if url == i[0]:
                  func = i[1]
                  break
          if func:
              ret = func(url)
          else:
              ret = b'<h1>404 not found!</h1>'
          conn.send(ret)
          # 断开连接
          conn.close()
      补充:time.html
      
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <h1>当前时间是:@@time@@</h1>
      </body>
      </html>
      返回动态页面

    五、wsgiref

    • 常用的WSGI服务器有uWSGI、Gunicorn

      • Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器

    • 简单示例:

      """  
      根据URL中不同的路径返回不同的内容--函数进阶版  
      返回HTML页面  
      让网页动态起来  
      wsgiref模块版  
      """       
      from wsgiref.simple_server import make_server     
          
      # 将返回不同的内容部分封装成函数   
      def index(url):   
          # 读取index.html页面的内容   
          with open("index.html", "r", encoding="utf8") as f:   
              s = f.read()   
          # 返回字节数据   
          return bytes(s, encoding="utf8")       
           
      def home(url):   
          with open("home.html", "r", encoding="utf8") as f:   
              s = f.read()   
          return bytes(s, encoding="utf8")       
           
      def timer(url):   
          import time   
          with open("time.html", "r", encoding="utf8") as f:   
              s = f.read()   
              s = s.replace('@@time@@', time.strftime("%Y-%m-%d %H:%M:%S"))   
          return bytes(s, encoding="utf8")        
           
      # 定义一个url和实际要执行的函数的对应关系   
      list1 = [   
          ("/index/", index),   
          ("/home/", home),   
          ("/time/", timer),   
      ]        
           
      def run_server(environ, start_response):   
          start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息   
          url = environ['PATH_INFO']  # 取到用户输入的url   
          func = None   
          for i in list1:   
              if i[0] == url:   
                  func = i[1]   
                  break   
          if func:   
              response = func(url)   
          else:   
              response = b"404 not found!"   
          return [response, ]      
           
      if __name__ == '__main__':   
          httpd = make_server('127.0.0.1', 8090, run_server)   
          print("我在8090等你哦...")   
          httpd.serve_forever()  
      示例

    六、jinja2

    1. 模板渲染现成的工具:jinja2

      • 下载jinja2:pip install jinja2

    2. 示例:

      from wsgiref.simple_server import make_server  
      from jinja2 import Template    
        
      def index(url):  
          # 读取HTML文件内容  
          with open("index2.html", "r", encoding="utf8") as f:  
              data = f.read()  
              template = Template(data)   # 生成模板文件 
              ret = template.render({'name': 'alex', 'hobby_list': ['抽烟', '喝酒', '烫头']})   # 把数据填充到模板中  
          return bytes(ret, encoding="utf8")  
        
      def home(url):  
          with open("home.html", "r", encoding="utf8") as f:  
              s = f.read()  
          return bytes(s, encoding="utf8")  
        
      # 定义一个url和实际要执行的函数的对应关系  
      list1 = [  
          ("/index/", index),  
          ("/home/", home),  
      ]   
        
      def run_server(environ, start_response):  
          start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息  
          url = environ['PATH_INFO']  # 取到用户输入的url  
          func = None  
          for i in list1:  
              if i[0] == url:  
                  func = i[1]  
                  break  
          if func:  
              response = func(url)  
          else:  
              response = b"404 not found!"  
          return [response, ]  
        
      if __name__ == '__main__':  
          httpd = make_server('127.0.0.1', 8090, run_server)  
          print("我在8090等你哦...")  
          httpd.serve_forever() 
      <!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>Title</title>
      </head>
      <body>
          <h1>姓名:{{name}}</h1>
          <h1>爱好:</h1>
          <ul>
              {% for hobby in hobby_list %}
                  <li>{{hobby}}</li>
              {% endfor %}
          </ul>
      </body>
      </html>
      index2.html
  • 相关阅读:
    Python并发编程-IO模型-IO多路复用实现SocketServer
    Python并发编程-IO模型-非阻塞IO实现SocketServer
    Python并发编程-协程实现socketserver
    Pytho并发编程-利用协程实现简单爬虫
    Python正则表达式中的re.S
    Python-正则表达式
    django-模板初探
    django-response对象
    django-QueryDict 对象
    django-request对象
  • 原文地址:https://www.cnblogs.com/zengyi1995/p/11328892.html
Copyright © 2020-2023  润新知