一. 前言
Django模板层的知识包括标签,过滤器,自定义标签,自定义过滤器以及inclusion_tag,最重要的是模板的继承和导入,模板层最重要的是模板语法,之前我们涉及到的变量用模板语法{{}},涉及到逻辑用模板语法{% %},这里我们在追加几点,过滤器在模板语法{{ }}中写,而且只能传两个参数;标签在模板语法{% %}中写,且能传多个参数(参数之间用空格隔开).模板的继承和导入也是在模板语法{% %}中写.
接下来我们回顾下后端朝前端传递数据的两种方式:
from django.shortcuts import render # Create your views here. def login(request): ‘‘‘模板语法只有2个: 渲染变量:{{}} 1.深度查询--->>句点符;2.过滤器 渲染标签:{% %} :param request: :return: ‘‘‘ name = "panshao" i = 10 #整型 l = [1,2,3] #列表 info = {"name":"panshao", "age":22} #字典 b = True #布尔 class Person(object): def __init__(self, name, age): self.name = name self.age = age alex = Person("alex",33) #对象 egon = Person("egon",38) person_list = [alex, egon] #return render(request, "login.html", {"name":name}) return render(request, "login.html", locals()) #locals是局部变量的意思,这样就不用一个个去对应了;它会把这些局部变量直接传给模板,它传的时候就是按照{“name”:name} {"alex":alex}这种方式传的
()
两种方法有利有弊,不过在之后我们会选用locals(),后端除了能向前端提交的Python的基本的数据类型: int, float, str, list, dict, tuple, set数据外,还能提交函数与类的对象,当我们传递函数名给前端时,会自动拿到该函数return的结果, 但是不支持传参,只支持传递无参函数.当传递类的对象obj给前端时,相当于print (obj),前端拿到的是该obj的内存地址,因为print(obj)走的是类的__str__()方法.所以传递类对象时,我们重新写__str__()能让前端拿到想要的内容. 前端想要获取后端传递过来的容器类型中的元素时,统一使用句点符(.):
二. 过滤器
过滤器在模板语法{{ }}中书写,过滤器最多支持传两个参数,(会把|左边的参数当做过滤器的第一个参数传进去),过滤器的基本语法: {{ 参数1|过滤器名字: 参数2}}, 有些过滤器没有参数2
统计字符串长度{{ s|length}}: 会将s当做length的参数传进去,将s的长度打印出来
获取的数据为空时就返回default后面定义的值{{ s|default: ‘s是空的字符串‘}}, 这种方法跟后端的get方法很像,default必须要有两个参数
将数字转化为表示文件大小的格式{{ file_size|filesizeformat}} 给file_size一串数字,会转化为多少兆,多少G之类的,如果file_size是204800,执行该过滤器后就是200kb
格式化时间{{ ctime|date: ‘Y-m-d‘}}不需要和后端一样加% (‘%Y-%m-%d‘),后端代码为
from datetime import datetime ctime = datetime.now()
字符串的切片操作{{s|slice:‘0: 8: 2‘}},如果s=‘hello world‘,执行完该过滤器后是‘hlow‘, slice后面的参数同python字符串切片参数一样,开头: 结尾: 步长,切片顾头不顾尾
截取固定长度的字符串{{s|truncatechars:10}} 如果s=‘hello world‘ 执行完该过滤器后是‘hello w...‘, 超出长度的部分会用...代替,当我们的参数为10时, 实际上截取的字符串长度为7,因为...占3位.
按照空格截取文本内容{{s|truncatewords:2}} 如果s=‘he llo wor ld‘,执行完该过滤器后是:‘he llo ...’,截取至前两个空格,之后的内容用...表示。
加法亦或是字符串拼接{{ n1|add:n2}} 如果n1=2, n2=4,那么结果为6。如果n1=‘hello‘, n2=‘world‘,那么结果为‘helloworld‘
当我们后端向前端提交的字符串含有标签时,比如‘<h1>this is title</h1>‘,为了防止脚本攻击(比如<script>while(1){alert(‘come on‘)}</script>),前端之后把你当成普通的字符串。当我们想要让前端帮我们执行提交的字符串中的标签内容时,有两种方式。
1. 在前端通过{{字符串|safe}}告诉前端字符串很安全,可以大胆执行
2. 后端用模块操作一下字符串,告诉前端我们给它的字符串很安全。
from django.utils.safestring import mark_safe def login(request): html = reverse(‘login‘) s = ‘<h1>this is title</h1>‘ s = mark_safe(s) return render(request, ‘login.html‘, locals()) # 前端直接{{ s }}即可
三. 标签
标签在模板语法中{% %}书写, {% %}涉及到逻辑,标签一般是for循环,f判断以及它们的嵌套使用,除此之外还有empty标签。
for 循环中可以使用forloop来给我们提供一些信息:
for循环
<!--l = [1, 2, 3, 4, 5]--> {% for foo in l %} <p>{{ foo }}</p> <p>{{ forloop }}</p> {% endfor %}
if判断
{% if flag %} <p>flag不为空</p> {% else %} <p>flag是空</p> {% endif %
if与for嵌套使用
{% for foo in s %} {% if forloop.first %} <p>这是第一次</p> {% elif forloop.last %} <p>这是最后一次</p> {% else %} <p>keep up</p> {% endif %} {% endfor %}
empty
{#{% for foo in ‘‘ %}#} {# {% if forloop.first %}#} {# <p>这是我的第一次</p>#} {# {% elif forloop.last %}#} {# <p>这是最后一次了啊</p>#} {# {% else %}#} {# <p>来啊来啊!!!</p>#} {# {% endif %}#} {# {% empty %}#} {# <p>当for循环的对象为空的时候 会走empty</p>#} {#{% endfor %}#}
四. 自定义inclusion_tag
要自定义过滤器与标签,必须先做三件事
from django import template register = template.Library()
自定义inclusion_tag
from django import template register = template.Library() @register.inclusion_tag(‘login.html‘, name=‘login‘) def login(n): l = [‘第%s项‘ % i for i in range(n)] return {‘l‘: l}
<!--login.html--> <ur> {% for foo in l %} <li>{{ foo }}</li> {% endfor %} </ur>
在该例子中, 我们在前端调用inclusion_tag时:
{% load my_tags %} {% login 5 %}
首先会将参数5传给login函数,函数执行完后的结果提交至login.html,然后将login.html的页面显示在调用该inclusion_tag的地方。
inclusion_tag会将渲染过的login.html界面返回至调用它的位置,正是因为这种机制,所以它所渲染那个html页面中可以不需要head和body等各种标签,你需要返回什么就在里面写什么。
五. 模板的继承
1. 模板的继承
首先需要被继承的模板中划分多个区域:
{% block 给区域起的名字 %} {% endblock %}
通常情况下一个模板至少需要三块区域:
{% block css %} 页面css代码块 {% endblock %} {% block js %} 页面js代码块 {% endblock %} {% block content %} 页面主体内容 {% endblock %}
子模板继承模板,首先要继承所有的内容:
{% extends ‘home.html‘ %}
{#先继承home,必须写在首行,不然它不知道block是什么意思 跟include不一样,它有它自己独特的优势#}
根据被block快的名字修改指定区域的内容
{% block content %} <h1>登录页面</h1> <form action=""> <p>username:<input type="text" class="form-control"></p> <p>password:<input type="text" class="form-control"></p> <input type="submit" class="btn btn-success"> </form> {% endblock %}
可以使用{{block.super}}使用父模板的该block的内容(使用该方法没有提示,要手撸)
{% block content %} {{ block.super }} {% endblock %}
注意:原模板中的block区域越多越好,因为越多代表可以修改的细节很多,扩展性就越强。继承后,子模板只能修改block区域中的内容。
2. 静态文件配置
当我们为了让路由名字改变时我们不需要修改HTML页面和视图函数中的内容,我们引入了反向解析。同理,为了防止settins.py文件夹中static文件夹的接口前缀改变而我们不需要html页面中head中script和link的接口前缀(需要修改的前提是他们导入的是static文件夹中的东西),我们引入了静态文件配置。
{% load static %} <link rel=‘stylesheet‘ href="{% static ‘css/mycss.css‘%}"> # 第一种方式 <link rel=‘stylesheet‘ href="{% get_static_prefix %}css/mycss.css"> # 第二种方式
原文:https://www.cnblogs.com/panshao51km-cn/p/11546207.html