• 开发工程师必备————【Day23】Django基础知识


    今日内容概要

    • 纯手撸web框架
    • 基于wsgiref模块
    • 框架代码优化
    • 动静态网页
    • jinja2模板语法
    • python主流web框架
    • django框架简介
    • django基本操作命令
    • django小白必会三板斧

    纯手撸web框架

    1.web框架概念
    web框架可以理解为是基于互联网的web服务端(socket服务端)

    2.步骤

    • socket服务端代码
    • HTTP协议
    • 根据网址后缀的不同请求不同的内容
    • 请求方式
      (1)GET:朝服务端索要数据
      (2)POST:朝服务端提交数据
    • 从请求数据格式中筛选出用户输入的网址后缀
    target_url = data.decode('utf8').split(' ')[1]
    
    • 1
    • 代码的缺陷:
      (1)socket代码重复编写造轮子
      (2)针对请求数据格式的处理复杂且重复
      (3)针对不同网址后缀的匹配方式过于简单

    3.未优化代码展示

    import socket
    
    server = socket.socket()  # TCP协议
    server.bind(('127.0.0.1', 8080))  # IP协议 PORT协议
    server.listen(5)  # 连接池
    
    while True:
       sock, address = server.accept()
       data = sock.recv(1024)
       sock.send(b'HTTP/1.1 200 OK\r\n\r\n')
       # print(data.decode('utf8'))  # 从字符串中截取出需要的内容
       target_url = data.decode('utf8').split(' ')[1]  # / /index /login /reg /xxx
       if target_url == '/index':
           sock.send(b'index view')
           #  with open(r'my html.html','rb') as f:
            #  sock.send(f.read())
       elif target_url == '/login':
          sock.send(b'login view')
       elif target_url == '/reg':
           sock.send(b'reg view')
       else:
           sock.send(b'404 error')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    基于wsgiref模块

    wsgiref内置模块:
    wsgiref内部封装了socket代码和对请求数据的处理。

    from wsgiref.simple_server import make_server
    
    def run(request, response):
       """
       :param request: 请求数据
       :param response: 响应数据
       :return: 返回给客户端的数据
       """
       print(request)  # 自动将请求数据全部处理成字典k:v键值对形式
       response('200 OK', [])  # 固定代码 无需掌握
       return [b'hello big baby']
    
    
    if __name__ == '__main__':
       server = make_server('127.0.0.1', 8080, run)  # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用
       server.serve_forever()  # 永久启动
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • wsgiref模块解决了两个问题:
      (1)socket代码重复编写造轮子
      (2)针对请求数据格式的处理复杂且重复
    • 思考如何再次实现根据不同的网址后缀返回不同的内容(函数化)
      先从大字典中查找出记录网址后缀的键值对。
      (1)不推荐使用连续的多个if判断
      (2)针对面条版的代码首先应该考虑封装成函数
    def index(request):
        return 'index'
    def login(request):
        return 'login'
    def register(request):
        return 'register'
    def error(request):
        return '404 error' 
    urls = (
        ('/index', index),
        ('/login', login),
        ('/register', register),
    )	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 根据py文件中功能的不同划分到不同的py文件(模块化)
    py文件功能
    urls.py对应关系
    views.py功能函数
    start.py启动文件
    templates文件夹存储html

    封装之后的最终代码

    启动文件 (start.py )from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    
    def run(request, response):
       response('200 OK', [])
       target_path = request.get('PATH_INFO')  # /login
       func_name = None
       for url_tuple in urls:  # ('/index',index)    ('/login',login)
           if url_tuple[0] == target_path:
               func_name = url_tuple[1]  # 先存储匹配到的函数名
               break  # 一旦匹配到了内容立刻结束for循环
       # for循环结束之后还需要判断func_name是不是为None(有可能存在没有匹配上)
       if func_name:
           res = func_name(request)
       else:
           res = error(request)
       return [res.encode('utf8')]  # 作统一编码处理
    
    
    if __name__ == '__main__':
      server = make_server('127.0.0.1', 8080, run)  # 任何访问>127.0.0.1:8080的请求都会给第三个参数加括号调用
      server.serve_forever()  # 永久启动
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    功能函数(views.py )
    
    def index(request):
       return 'index'
    
    
    def login(request):
       return 'login'
    
    
    def register(request):
       return 'register'
    
    
    def error(request):
       return 'error'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    对应关系(urls.py)
    
    `from views import *
    urls = (
       ('/index',index),
       ('/login',login),
       ('/register',register),
    )
    ``
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    动静态页面

    1.动态页面
    页面上的数据不是全部写死的,有些是动态获取(后端传入)
    2.静态网页
    页面上的数据直接写死的,要想改变只能修改源码。

    3.实际需求
    后端代码获取当前时间,然后让前端页面展示:
    (1)字符串替换

    def get_time(request):
       import time
       ctime = time.strftime('%Y-%m-%d %X')
       with open(r'html_get_time.html','r',encoding='utf8')as f:
           data = f.read()
       # 如何将时间嵌入html内部,之后再返回给前端浏览器(字符串的替换)
       data = data.replace('lalala',ctime)
       return data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (2)将字典数据传递给html页面并且想要在页面上操作字典数据;

    def get_dict(request):
       user_dict = {'name':'jason','pwd':123,'hobby':['read','run','music']}
       with open(r'html_get_dict.html','r',encoding='utf8')as f:
           data = f.read()
       # 如何将时间嵌入html内部,之后再返回给前端浏览器(字符串的替换)
       data = data.replace('hahaha',str(user_dict))
       return data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    考虑到问题:我们无法自己实现在html页面上使用类似于后端的语法操作数据。所以引出jinja2模块。

    jinja2模块

    1.jinjia2说明
    jinja2能够让我们在html文件内使用类似于后端的语法来操作各种数据类型。
    2.jinja2下载

    pip3 install jinja2
    
    • 1

    3.举个栗子——字典实现页面展示

    views.py:

    from jinja2 import Template
    def get_dict(request):
       user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
       with open(r'templates/myhtml04.html','r',encoding='utf8') as f:
           data = f.read()
       temp = Template(data)
       res = temp.render(data=user_dict)  # 将字典传递给html页面 页面上通过>data即可获取(data仅仅是一个变量名)
       return res
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    start.py

    from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    
    def run(request, response):
       response('200 OK', [])
       target_path = request.get('PATH_INFO')  # /login
       func_name = None
       for url_tuple in urls:  # ('/index',index)    ('/login',login)
           if url_tuple[0] == target_path:
               func_name = url_tuple[1]  # 先存储匹配到的函数名
               break  # 一旦匹配到了内容立刻结束for循环
       # for循环结束之后还需要判断func_name是不是为None(有可能存在没有匹配上)
       if func_name:
           res = func_name(request)
       else:
           res = error(request)
       return [res.encode('utf8')]  # 作统一编码处理
    
    
    if __name__ == '__main__':
      server = make_server('127.0.0.1', 8080, run)  # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用
      server.serve_forever()  # 永久启动
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    urls.py

    from views import *
    urls = (
       ('/get_dict',get_dict),
    )
    
    • 1
    • 2
    • 3
    • 4

    html_get_dict_html

    DOCTYPE html>
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <title>Titletitle>
       <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js">script>
       <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">