(day52)四、视图层、模板层

一、视图层

(一)Request和Response对象

(1)Request对象

页面被请求时,Django创建的传给视图函数的Request对象

  1. method:返回请求方式,大写的字符串
  2. GET:返回GET请求所携带的数据,类字典对象
  3. POST:返回POST请求所携带的数据,类字典对象
  4. paht_info:返回用户访问的url,不包括域名
  5. body:请求体,byte类型,存放post请求携带的数据
# 以GET举例
request.GET.get(xxx='xxx')  # 默认获取最后一个元素
request.GET.getlist()  # 获取所有元素

(2)Response对象

视图函数必须有一个返回值,数据类型必须是HttpResponse(render和redirect都继承了HttpResponse)

  1. content:响应内容
  2. charset:响应内容的编码
  3. status_code:响应的状态码

(二)JsonResponse对象

(1)前后端分离

  1. HttpResponse对象的子类,专门用来生成JSON编码的响应,用于前后端数据交互

  2. 后端只需要写好相应的url接口,前端访问接口,只需要返回一个大字典+开发文档(告诉前端,接口会返回哪些数据)即可

from django.http import JsonResponse
import json
def index(request):
    user_dic = {'name':'json是个傻逼','password':123}

    l = [1,2,3,3,4,5,65]
    return JsonResponse(l,safe=False)

(2)json_dumps_params参数

默认转码成ascii值,设置该参数中的ensure_ascii来控制不对中文进行转码

# 如何让json不对中文进行转码 方法1
json_str = json.dumps(user_dic,ensure_ascii=False)
return HttpResponse(json_str)

#如何让json不对中文进行转码 方法2
return JsonResponse(user_dic,json_dumps_params={"ensure_ascii":False})

(3)safe参数

JsonReponse默认序列化字典,如果序列化其他类型(json模块可以序列化的),你需要设置safe参数为False

l = [1,2,3,3,4,5,65]
return JsonResponse(l,safe=False)

(三)FBV与CBV

  1. FBV:基于函数的视图

    # views.py
    from django.shortcuts import render,HttpResponse,redirect
    
    def get(self,request):
    print('mylogin>get')
    return  render(request,'login.html')
    
    # urls.py  
    url(r'^get/', views.get), 
  2. CBV:基于类的视图

    # views.py
    from django.shortcuts import render,HttpResponse,redirect
    from django.views import View
    
    class MyLogin(View):
        def get(self,request):
            print('mylogin>get')
            return  render(request,'login.html')
    
        def post(self,request):
            print('mylogin>post')
            return HttpResponse('post')
    
    # urls.py  
    url(r'^login/', views.MyLogin.as_view()), 

(四)CBV的源码

  1. 项目一启动就会自动执行as_view方法,返回调用函数view(本质上也是FBV)

  2. 函数view中返回调用对象的dispatch方法

    @classonlymethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):  # 闭包函数
            self = cls(**initkwargs)  # cls是我们自己写的类 MyLogin  self是我们自己定义的类的对象
            # 在看源码的时候 你一定要把握住一个顺序 对象在查找属性和方法的时候
            return self.dispatch(request, *args, **kwargs)
        return view
  3. dispatch函数中利用反射方法获得请求的方式,从而调用对应方法

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        # 判断当前请求方式在不在默认的八个方法内
        # 1.先以GET请求为例
        if request.method.lower() in self.http_method_names:
            # 利用反射去我们自己定义类的对象中查找get属性或者是方法  getattr(obj,'get')
            # handler = get方法
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)  # 调用get方法

(五)装饰器

(1)FBV加装饰器

和普通函数加装饰器一样

(2)CBV加装饰器

可以利用method_decorator装饰器将函数装饰器转化为方法装饰器

  1. 函数装饰器直接加
  2. 方法装饰器直接加(推荐用法)
  3. 方法装饰器通过name指定
  4. 通过自定义dispatch方法,给所有方法加
from django.views import View
from django.utils.decorators import method_decorator
from django.utils.safestring import mark_safe
# 3.方法装饰器通过name指定
@method_decorator(outer,name='post')
# 4.1 方法装饰器通过name指定dispatch给所有方法加
# @method_decorator(outer,name='dispatch') 
class MyLogin(View):
    # 4.2 通过自定义dispatch方法,给所有方法加
    def dispatch(self, request, *args, **kwargs):  # 在视图函数执行之前的操作
        return super().dispatch(request,*args,**kwargs)

    # 1. 函数装饰器直接加
    @outer
    def get(self,request):
        print('mylogin>get')
        return  render(request,'login.html')

    # 2. 方法装饰器直接加 (推荐写法)
    @method_decorator(outer)
    def post(self,request):
        print('mylogin>post')
        return HttpResponse('post')

二、模板层

(一)模板语法

  1. {{}}:和变量相关
  2. {%%}:和逻辑相关

(二)模板传值

(1)传值方式(render)

  1. 通过字典传值:适用于传值较少
  2. 通过locals()传值:将当前所在名称空间所有的名字全部传递给html页面,适用于传值较多
# 给html传值的方式1,传递的值较多时,不方便
return render(request,'test.html',{'n':n})

# 给html传值的方式2,local()会将当前所在名称空间所有的名字全部传递给html页面
return render(request,'test.html',locals())

(2)基础数据类型

python基本数据类型全部支持传值

(3)函数和对象

  1. 给html页面传递函数名或类名的时候,模板语法会自动加括号调用,并返回返回值
  2. 模板语法不支持函数传参,即传给html的函数只能是无参函数或者不需要传参调用的函数

(4)点(.)

  1. Django中的模板语言的.具有特殊含义,可以用于字典取值,属性或方法调用,数字索引查询
  2. 查询顺序:字典查询>属性或方法查询>数字索引查询
# views.py
dic = {'username':'wick','hobby':['read','study',['run','sing',{'age':18}]]}

# html中取值方法
{{dic.hobby.2.2.age}}  # 18

(三)过滤器|

(1)定义和语法

  1. 模板语法提供的的内含方法,可以快速的处理数据
  2. 语法:{{ value|filter_name:参数 }}
  3. 支持链式操作
  4. 管道符|左右没有空格

(2)常用过滤器

  1. length:返回值的长度
  2. filesizeformat:返回自动转换后的文件大小
  3. safe:返回转义后html和JS标签(默认不会自动转移html标签)
  4. add:返回数字相加结果,支持字符串
  5. slice:返回切片结果,支持步长,负数
  6. default:值为空返回默认值,否则返回值本身
  7. truncatechar:截取文本字符,包含···
  8. truncatewords:截取文本内容,不包含···,根据空格判断
<p>统计长度:{{ s|length }} (无法统计,默认返回0)</p>
<p>文件大小自动转换:{{ file_size|filesizeformat }}</p>
<p>展示带有标签的文本:{{ sss }}(默认不会自动转换成html标签,防止恶意攻击)</p>
<p>展示带有标签的文本:{{ sss|safe }}(safe设置自动转换成html标签)</p>
<p>加法运算:{{ n|add:234567 }} (内部异常捕获,支持数字相加,字符串相加,都不符合,返回'')</p>
<p>切片操作:{{ l|slice:'0:2'}} (支持步长、负数)</p>
<p>判断是否有值:{{ is_value|default:'is_value变量名指向的值为空' }}</p>
<p>截取文本内容(字符):{{ s|truncatechars:4}} (截取4个字符,包含···)</p>
<p>截取文本内容:{{ s2 | truncatewords:5}} (按照空格截取5个单词,不包含···)</p>

(3)前后端取消转义

  1. 前端:safe

  2. 后端:mark_safe

    from django.utils.safestring import mark_safe
    res = mark_safe(cc)

(四)标签

逻辑相关

(1)for循环

  • 分类
    1. 普通for循环
    2. for ... empty:当for循环的对象为空时,执行该语句
  • 自带参数forloop
    1. forloop.counter0:当前循环的索引值(从0开始)
    2. forloop.counter:当前循环的计数(从1开始)
    3. forloop.revcounter0: 当前循环的倒序索引值(从0开始)
    4. forloop.revcounter: 当前循环的倒序计数值(从1开始)
    5. forloop.first: 判断当前循环是不是第一次循环(布尔值)
    6. forloop.last :判断当前循环是不是最后一次循环(布尔值)
    7. forloop.parentloop : 本层循环的外层循环

(2)if判断

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断

{% for foo in l %}
    {% if forloop.first %}
        <p>这是第一个数</p>
    {% elif forloop.last %}
        <p>这是最后一个数</p>
    {% else %}
        <p>中间的数{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>当for循环的对象为空时,执行该语句</p>
{% endfor %}

(3)with

  1. 定义一个中间变量,多用于给一个复杂的变量起别名,等号左右不要加空格。
  2. 别名只可以在with内部可以用
<!--dic = {'username':'wick','hobby':['read','study',['run','sing',{'age':18}]]}-->
{% with  dic.hobby.2.2.age as age   %}
    <p>{{ age }}</p>
{% endwith %}

(4)csef_token

  1. 这个标签用于跨站请求伪造保护。

  2. 在页面的form表单里面写上{% csrf_token %}

(五)自定义

自定义必须要做的三件事:

  1. 在应用下新建一个templatetags的文件夹
  2. 该文件夹内新建一个任意名称的py文件
  3. 在该py文件中必须先写下面两句话:
    1. from django.template import Library
    2. register = Library()

可以自定义过滤器、标签和inclusion_tag,使用时必须在页面上加载一下

  • inclusion_tag:是一个函数,能够接受外界传入的参数,然后传递给一个html页面,页面获取数据渲染完成后将页面返回
# mytag.py
# 自定义过滤器(和默认的过滤器一样,最大只能接受两个参数)
@register.filter(name='baby')
def index(a,b):
    return a+b

# 自定义标签,可以接受任意多个参数
@register.simple_tag(name='mytag')
def mytag(a,b,c,d):
    return f'{a}?{b}?{c}?{d}'

# 自定义inclusion_tag
@register.inclusion_tag('mytag.html',name='xxx')
def index6(n):
    l = []
    for i in range(n):
        l.append(f'第{i}项')
    return locals()  # 将l直接传递给mytag.html页面
<p>自定义过滤器的使用</p>
{% load mytag %}
{{ 1|baby:1 }}

{#<p>自定义标签的使用,可以接受多个参数,参数必须用空格隔开</p>#}
{#{% load mytag %}#}
{#{% mytag 'a' 'b' 'c' 'd' %}#}

{#<p>自定义的过滤器可以在逻辑语句中使用,而自定义标签不可以</p>#}
{#{% if 1|baby:2 %}#}
{#    <p>有值</p>#}
{#{% else %}#}
{#    <p>无值</p>#}
{##}
{#{% endif %}#}

<p>自定义inclusion_tag的使用,当需要使用一些页面组件,且该组件需要参数才能正常渲染时使用</p>
{% load mytag %}
{% xxx 11 %}
</body>
</html>

(六)模板的继承和导入

(1)继承模板extends

在子页面中在页面最上方使用下面的语法来继承母板

{% extends 'home.html' %}

(2)块(block)

在父页面上利用block划定想要修改的区域,继承后就可以通过名字找到对应的名字找到该区域,并修改

  1. 模板上的block区域越多,页面的扩展性越强,推荐你一个模板页面至少有三块区域(css区域,html代码区域,js区域)
  2. 通过这三个区域,就能够实现每一个页面都有自己独立的css和js代码
  3. 可以在子页面上通过{{ block.super }}沿用父页面的内容

(3)导入(include)

将html页面当做模块的直接导入使用:{% include 'form.html'%}

{% block content %}
    <p>我改成home1页面内容</p>
    {{block.super}}
    {% include 'form.html' %}
{% endblock %}

{% block css %}
    <style>
        p {
            color: green;
        }
    </style>
{% endblock %}

{% block js %}
    <script>
        alert('login')
    </script>
{% endblock %}

猜你喜欢

转载自www.cnblogs.com/wick2019/p/11938333.html