• JsonResponse对象, CBV源码, 模板语法


    JsonResponse对象

    • 小白必会三板斧: HTTPResponse, render, redirect

    • 视图函数必须要有一个返回值, 并且返回值的

    • 数据类型必须是HTTPResponse对象

    • render: Template + Context

      def test(request):
          from django.template import Template, Context
          html_obj = Template('<h1>{{user}}</h1>')
          data_obj = Context({'user': {'user_name': 'jason'}})
          complete_html = html_obj.render(data_obj)
          return HttpResponse(complete_html)
      

    前后端分离

    • 前后端数据交互采用json, 字符串形式的字典

    • 后端写好相应的url接口, 前端访问这个接口,

    • 后端返回一个大字典给前端, 并附上开发文档

    • 前端根据大字典中的数据和开发文档渲染页面

    • 前后端序列化反序列化使用的方法

      • python后端: json.dumps, json.loads
      • js前端: JSON.stringify, JSON.parse
    • 设置json不自动对中文转码

      • 方式一: 查看json.dumps源码-->发现ensure_ascii参数, 将其值设为False

        def test(request):
            import json
            user_dic = {'name': '蔡启龙'}
            json_str = json.dumps(user_dic, ensure_ascii=False)  # {"name": "蔡启龙"}
            return HttpResponse(json_str)  # {"name": "u8521u542fu9f99"}
        
      • 方式二: 使用django封装的JsonResponse

        查看JsonResponse源码-->找到json.dumps-->推测出json_dumps_params参数值

        def test(request):
            from django.http import JsonResponse
            user_dic = {'name': '蔡启龙'}  # {"name": "u8521u542fu9f99"}
            return JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})  # {"name": "蔡启龙"}
        
    • 设置序列化json能序列化的其他数据类型

      根据报错信息, 更改参数: safe=False

      def test(request):
          from django.http import JsonResponse
          lt = [1, 2]
          return JsonResponse(lt, safe=False)  # [1, 2]
      # In order to allow non-dict objects to be serialized set the safe parameter to False.
      

    CBV及其源码分析

    CBV: 基于类的视图, Class Based Views

    • FBV: Function Based Views, 基于函数的视图
    • FBV的写法: 路由 + 视图函数名, url(r'^index/', views.index)
    • CBV的写法: url(r'^login/', views.MyLogin.as_view()), # 返回view, cbv本质上还是fbv, 路由+函数名

    CBV的源码, 要求: 能直接说出流程

    为什么CBV能够根据请求方式的不同, 自动执行不同的方法

    • 函数名加括号执行的优先级最高
    • 项目一启动, 就会自动执行as_view方法
    • 源码只看自己能看懂的, 不要纠结于看不懂的部分
    1. 执行类方法as_view(), 返回view
    2. 正则表达式匹配到"login/", 执行view(),
    3. view()返回dispatch(request, ...),
    4. 执行dispatch(request, ...), 会拿到请求方式字符串, 通过反射查找对象中的方法
    5. 如果找到, 将该方法记录给handler, 找不到则将报错函数记录给handler, 最后返回handler的执行结果, 为一个HttpResponse对象
    from django.views import View
    
    
    class MyLogin(View):
        def get(self, request):
            print('MyLogin的get方法')
            return render(request, 'login.html')
    
        def post(self, request):
            return HttpResponse('MyLogin的post方法')
    
    @classonlymethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):  # as_view内的闭包函数
            self = cls(**initkwargs)  # cls为自定义的MyLogin类, self为自定义的类实例化出的对象
            return self.dispatch(request, *args, **kwargs)
    
        return view
    
    
    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() in self.http_method_names:  # 判断当前请求方式是否在八个默认的方法内
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)  # 以get请求为例, getattr(obj, 'get')
        else:
            handler = self.http_method_not_allowed  # 调用get方法
        return handler(request, *args, **kwargs)  # 返回调用get方法的到的结果, 一个HttpResponse对象
    

    给CBV加装饰器的方式

    from functools import wraps
    import time
    
    
    def deco(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            exec_time = time.time() - start_time
            print('函数执行时间: %s' % (exec_time,))
            return res
    

    方式一: 直接装饰

    '''
    @deco
    def get(self, request):
    	...
    '''
    

    方式二: 使用内置模块, 如果不使用内置模块直接对类装饰会报错: 'function' object has no attribute 'as_view'

    from django.utils.decorators import method_decorator
    
    '''
    @method_decorator(deco, name='post')
    class MyLogin(View):
    	...
    
    @method_decorator(deco)  # 推荐写法
    def get(self, request):
    	...
    '''
    
    

    方式三: 一次性给类中所有方法加装饰器, 如果想在视图函数执行之前做一些操作, 可以在CBV中自定义dispatch方法来实现

    from django.utils.decorators import method_decorator
    
    
    @method_decorator(deco, name='dispatch')
    class MyLogin(View):
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request, *args, **kwargs)
    
    

    模板语法

    模板语法的格式

    两种: 变量相关{{}}, 逻辑相关{{%%}}

    模板传值

    能传的数据类型, python基本的数据类型都支持

    def test(request):
        lt = [1, 2, 3]
        s = 'hello world'
        file_len = 666666
        tag = "<h1>tag</h1>"
        user_dic = {'name': 'jason', 'pwd': '123'}
    
        def index():
            return 'index的函数返回值'
    
        class TestClass:
            pass
    
        test_obj = TestClass()
    
        # locals会将当前名称空间中的所有名字传递给html页面
        return render(request, 'test.html', locals())
    
    • 传函数名: <p>{{ index }}</p>

      给HTML页面传函数名时, 会自动调用该函数, 并将函数返回值展示出来, 但不支持函数传参

    • 传类名: 自动加括号实例化产生对象, 所有只要是可调用对象, 传递到html页面上都会自动加括号调用

      '''
      <p>{{ TestClass }}</p>
      <p>{{ test_obj }}</p>
      
      <app02.views.test.<locals>.TestClass object at 0x0000028D321F9F28>
      <app02.views.test.<locals>.TestClass object at 0x0000028D321EAD30>
      '''
      

    过滤器

    模板语法提供的一些内置方法, 用来快速处理数据, 但是最多只能有两个参数

    会将|左边的数据当做过滤器的第一个参数传入, ":"右边的数据当做第二个参数传入

    • 统计长度: <p>{{ lt|length }}</p>, # 3, 如果无法统计默认返回0

    • 加法运算: <p>{{ s|add:'nick' }}</p>, # hello worldnick

    • 切片操作: <p>{{ lt|slice:'0:2:1' }}</p>, # [1, 2], 顾头不顾尾, 也支持步长, 但不支持负数索引

    • 转换成文件大小格式: <p>{{ file_len|filesizeformat }}</p>, # 651.0 KB

    • 截取文本内容: <p>{{ s|truncatechars:5}}</p>, # he..., 截取5个字符, 并且3个点也算

    • 截取5个单词, 按空格计算, 3个点不算: truncatewords

    • 判断是否有值: <p>{{ ''|default:'为空时的默认值' }}</p>, # 为空时的默认值, 非空展示原值, 空展示默认值

    • 展示带有标签的文本:

      默认情况下不会自动转成前端html标签, 防止恶意攻击

      如果要识别html语法, 可以设置在前端或后端设置取消转义

      '''
      前端设置取消转义
          <p>{{ tag }}</p>  # <h1>tag</h1>
          <p>{{ tag|safe }}</p>  # tag
      '''
      
      # 后端设置取消转义
      from django.utils.safestring import mark_safe
      safe_tag = mark_safe(tag)
      # <p>{{ safe_tag }}</p>  # tag
      

    标签

    标签指的是与逻辑相关的一系列代码, 例如if判断, for循环等都在标签中

    for循环

    '''
    forloop对象: 
    	first/last判断for循环的开始与结束
    	count0, 从0开始的索引值
    	counter, 对数据进行的计数, 例如解决主键值不连续
    
    {% for num in lt %}
        <p>{{ forloop }}</p>
    {% endfor %}
    
    {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 3, 'revcounter0': 2, 'first': True, 'last': False}
    ...
    '''
    

    if判断

    {% if s %}
        <p>s有值</p>
     {% else %}
        <p>s没有值</p>
    {% endif %}
    

    组合使用

    {% for num in lt %}
        {% if forloop.first %}
            <p>第一循环, 数字为: {{ num }}</p>
        {% elif forloop.last %}
            <p>最后一次循环, 数字为: {{ num }}</p>
        {% else %}
            <p>中间循环, 数字为: {{ num }}</p>
        {% endif %}
        {% empty %}
            <p>for循环对象为空时触发</p>
    {% endfor %}
    

    for循环字典

    '''
    {% for key in user_dic.keys %}
        <p>{{ key }}</p>
    {% endfor %}  # name  pwd
    
    {% for value in user_dic.values %}
        <p>{{ value }}</p>  # jason  123
    {% endfor %}
    
    {% for item in user_dic.items %}
        <p>{{ item }}</p>  # ('name', 'jason')  ('pwd', '123')
    {% endfor %}
    '''
    

    模板语法的取值

    只有一种方式, 统一采用句点符: "."

    '''
    complex_dic = {'name': 'json', 'hobby': ['read', ['run', {'music': 'if you'}]]}
    <p>{{ complex_dic.hobby.1.1.music }}</p>  # if you, 获取music的值
    
    # 数据获取方式复制时使用别名, 但是别名只能在with内部使用
    {% with complex_dic.hobby.1.1.music as music %}
        <p>{{ music }}</p>
    {% endwith %}
    '''
    

    自定义过滤器和标签

    自定义的过滤器可以在逻辑语句中使用, 而自定义的标签不可以, 普通标签的符号也是{%%}

    自定义前必须要有三步准备:

    1. 在应用名下新建一个名字必须叫templatetages的文件夹
    2. 在该文件夹内, 新建一个任意名称的py文件
    3. 在该py文件下书写两句代码: from django.template import Library, register = Library()

    自定义过滤器:

    # 自定义过滤器
    @register.filter(name='division')
    def handle(x, y):  # 跟默认过滤器一样, 最多接收两个参数
        return x / y
    

    使用自定义过滤器

    先要将过滤器所在的文件加载过来, 类似于import

    {% load my_filters_tags %}
    {{ 1|division:10 }}
    

    自定义标签

    可以接收任意多个参数

    # 自定义标签
    @register.simple_tag(name='my_tag')
    def handle(a, b, c):
        return '%s?%s?%s' % (a, b, c)
    

    使用自定义标签

    接收的多个参数必须以空格隔开

    '''
    {% load my_filters_tags %}
    {% my_tag 'c' 'q' 'l' %}  # c?q?l
    '''
    

    自定义inclusion_tag

    1. 是一个函数, 能够接收外界传入的参数, 然后传递给一个html片段
    2. 该html片段获取数据并渲染
    3. 最后将渲染好的html片段返回到调用inclusion_tag的地方
    # 自定义inclusion_tag
    @register.inclusion_tag('part_html.html')
    def inclusion_tag(n):
        lt = []
        for i in range(n):
            lt.append('第%s项' % (i,))
        return locals()  # 将lt传递给html片段
    

    使用inclusion_tag, 重要

    应用场景: 当需要使用一些页面组件, 并且该页面组件需要参数动态渲染

    '''
    part_html.html
    <ul>
        {% for ele in lt %}
            <li>{{ ele }}</li>
        {% endfor %}
    </ul>
    
    test.html
    {% load my_filters_tags %}
    {% inclusion_tag 3 %}
    '''
    

    模板的继承

    需要事先在想要使用的HTML页面上划定区域, 在继承之后, 就可以对划定的区域进行使用, 否则无法修改任何内容

    一般至少有三块区域, html代码区域, css区域, js区域

    1. 在父页面上通过block模板语法划定区域
    2. 在子页面上通过extends模板语法继承父页面
    3. 在子页面使用block模板语法选择想要修改的区域
    {% extends 'test.html' %}
    
    {% block css %}
        <style>
            h1 {
                color: red;
            }
        </style>
    {% endblock %}
    
    {% block content %}
        <h1>登录页面</h1>
        {{ block.super }}  {#    在子页面上沿用父页面的内容#}
    {% endblock %}
    
    {% block js %}
        <script>
            alert(123)
        </script>
    {% endblock %}
    

    模板的导入

    将一个html片段当做模块的方式直接导入使用

    与inclusion_tag区别:

    • 模板的导入是写死的, 不支持传参,
    • 而inclusion_tag支持传参, 可以根据参数不同动态渲染HTML片段
    '''
    test111.html:
    	<h1>这是一个特别好看的form表单</h1>
    
    {% block content %}
        {% include 'test111.html' %}
    {% endblock %}
    '''
    
  • 相关阅读:
    【转】UCenter的MVC架构
    最新的windows xp sp3序列号(绝对可通过正版验证)
    马丁催眠的花园
    【转】UCenter 的 daddslashes详解
    ckEditor与ckFinder的集成
    【转】UCenter代码研究第一篇(ROOT/admin.php)
    MVC学习第三节:Controller与View
    MVC学习第二节:UrlRouting
    MVC 学习第十节 请求Controller
    MVC学习第九节 HtmlHelper
  • 原文地址:https://www.cnblogs.com/-406454833/p/11970245.html
Copyright © 2020-2023  润新知