一. 前言

  Django模板层的知识包括标签、过滤器、自定义标签、自定义过滤器以及inclusion_tag,最重要的是模板的继承和导入。

  首先模板层最重要的是模板语法,之前我们提过涉及到变量用模板语法{{ }},涉及到逻辑用模板语法{% %},这里再追加几点。过滤器在模板语法{{  }}中写,而且只能传两个参数;标签在模板语法{%%}中写,而且能传多个参数(参数间用空格隔开)。模板的继承与导入也是在模板语法{%%}中写。

  接下来再回顾一下后端朝前端页面传递数据的两种方式:

# 第一种
return render(request, 'index.html', {'nums': nums}) # 第二种
return render(request, 'index.html', locals())

  该两种方法有利有弊,不过我们偏爱locals()。

  后端除了能向前端提交python的基本数据类型:int、float、str、list、dict、tuple、set数据外,还能提交函数与类的对象。当我们传递函数名给前端时,会自动调用该函数拿到函数return的结果,但是不支持传参,所以只能传递无参函数名。当传递类的对象obj给前端时,相当于print(obj),前端拿到的是该obj的内存地址,因为print(obj)走的是类的__str__()方法。所以传递类的对象时,我们可以重写__str__()让前端拿到想要的内容。

  前端想要获取后端传递过来的容器类型中的元素时,统一使用句点符(.):

<!--假设前端拿到的数据是 L = [1, 2, 3]  D = {'age': 18}-->
{{ L }} <!--[1, 2, 3]-->
{{ L.1 }} <!-- 2 索引也是从0开始--> {{ D }} <!--{'age': 18}-->
{{ L.age }} <!-- 18 -->

  前端可以调用python自带的内置方法,不过只能调用不需要传参的,比如字典dic的dic.keys(),dic.values(),dic.items()等,注意:在前端调用方法不需要加(),直接dic.keys即可。

  模板语法的注释不会展示到前端(用谷歌浏览器的检查也看不到),只能在后端看到,原生的HTML注释前后端都可以看到。

二. 过滤器

  过滤器在模板语法{{ }}中书写,实际上过滤器内部走的是后端的语法,过滤器最多支持传两个参数(会把|左边的参数当做过滤器的第一个参数传进去),不过可以把参数改成容器类型,然后在内部动手脚处理参数中的数据,间接实现传递多参数,这需要我们自定义过滤器来实现。

  过滤器基本语法:{{ 参数1|过滤器名字:参数2 }}  有些过滤器没有参数2。

  • 统计字符串长度 {{ s|length }}:会将s当做length的参数传进去,内部就是后端语法

  • 获取的数据为空就返回default后面定义的值{{ s|default:'s是空的字符串' }}

  • 将数字转化为成表示文件大小的格式{{ file_size|filesizeformat }}

   如果file_size是204800,执行该过滤器后是 200.0KB

  • 格式化时间{{ ctime|date:'Y-m-d' }}

      不需要同后端一样加%('%Y-%m-%d'),如果ctime是2019-06-11 16:56:38.903314,执行完该过滤器后是2019-06-11。

  • 字符串的切片操作{{ s|slice:'0:8:2' }}

  如果s='hello world',执行完该过滤器后是‘hlow’,slice后面的参数同python字符串切片参数一样,开头:结尾:步长,其中步长默认为1,切片顾头不顾尾。

  • 截取固定长度的字符串{{ 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 index(request):
html = reverse('index')
s = '<h1>this is title</h1>'
s = mark_safe(s)
return render(request, 'index.html', locals()) # 前端直接{{ s }}即可

二. 标签

  标签在模板语法{%%}中书写,{%%}涉及到逻辑,标签一般是for循环,if判断以及它们的嵌套使用,除此之外还有empty标签。

  for循环中可以使用forloop来给我们提供一些信息:

1. for循环

<!--l = [1, 2, 3, 4, 5]-->
{% for foo in l %}
<p>{{ foo }}</p>
<p>{{ forloop }}</p>
{% endfor %}

2. if判断

{% if flag %}
<p>flag不为空</p>
{% else %}
<p>flag是空</p>
{% endif %}

3. if与for嵌套使用

{% for foo in s %}
{% if forloop.first %}
<p>这是第一次</p>
{% elif forloop.last %}
<p>这是最后一次</p>
{% else %}
<p>keep up</p>
{% endif %}
{% endfor %}

4. empty

{% for foo in l %}
{% if forloop.first %}
<p>这是我的第一次</p>
{% elif forloop.last %}
<p>这是最后一次了啊</p>
{% else %}
<p>嗨起来!!!</p>
{% endif %}
{% empty %}
<p>你给我的容器类型是个空啊,没法for循环</p>
{% endfor %}

5. 补充

  当后端传来的数据中,我们想要的数据需要句点符点很多次才能拿到且后面还需要用到该数据时,我们可以选择给该数据取别名。

三.自定义过滤器与标签、inclusion_tag

  要自定义过滤器与标签,必须先做三件事:

  1. 在应用文件夹下新建templatetags文件夹(必须叫这个名字)
  2. 在templatetags文件夹中新建一个py文件,名字任意,不过最好不要有中文
  3. 在该py文件中固定写以下两句代码:
from django import template

register = template.Library()

  再次强调,一定要按照以上步骤进行,文件夹一定要叫templatetags!!!

1. 自定义过滤器

from django import template

register = template.Library()

# 自定义过滤器
@register.filter(name='my_add') # name是HTML页面中调用该过滤器用的名字
def my_add(a, b):
return a+b

2. 自定义标签

from django import template

register = template.Library()

@register.simple_tag(name='my_tag')
def my_tag(a, b, c):
return a + b + c

3.自定义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等各种标签,你需要返回什么就在里面写什么。

4.结论

  想要使用自定义的过滤器、标签和inclusion_tag,必须要先在html界面中加载该模块

<!--加载my_tags.py模块-->
{% load my_tags %} {{ n1|my_add:n2 }} <!--调用自定义过滤器-->
{% my_tag n1 n2 n3 %} <!--调用自定义标签-->
{% login 5 %} <!--调用自定义inclusion_tag-->

四. 模板的继承与导入

1. 模板的继承

  1.1 首先需要被继承的模板中划分多个区域:

{% block 给区域起的名字 %}

{% endblock %}

  1.2 通常情况下一个模板中至少有三块区域:

{% block css %}
页面css代码块
{% endblock %} {% block js %}
页面js代码块
{% endblock %} {% block content %}
页面主体内容
{% endblock %}

  1.3 子模板继承模板,首先要先继承模板所有的内容:

{% extends 'home.html' %}

  1.4 根据被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 %}

  1.5 可以使用{{ block.super }}使用父模板的该block的内容(使用该方法是没有提示,要手打)

{% block content %}
{{ block.super }}
{% endblock %}

  注意:原模板中的block区域越多越好,因为越多代表可以修改的细节很多,扩展性就越强。继承后,子模板只能修改block区域中的内容。

2. 模板的导入

  模板导入同自定义标签inclusion_tag有点像,都是将一个HTML页面显示到调用它们的地方,而且他们的HTML页面都是要啥就写啥就行了,不需要body、head等标签。不过inclusion_tag是动态的,可以传递参数,而模板导入是静态的。

  模块导入{% include '想导入的html文件名' %}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login2</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!--导入模板index2.html-->
{% include 'index2.html' %}
</body>
</html>
<h1>我是这条gai最靓的仔</h1>
<form action="">
<p><input type="text"></p>
<p><input type="text"></p>
<input type="submit">
</form>

index2.html

3. 静态文件配置

  当我们为了让路由名字改变时我们不需要修改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"> # 第二种方式

Django模板层学习笔记的更多相关文章

  1. NVelocity模板引擎学习笔记

    NVelocity模板引擎学习笔记 学习模板引擎有一段时间现在做一些总结

  2. Django RF:学习笔记(8)——快速开始

    Django RF:学习笔记(8)——快速开始 安装配置 1.使用Pip安装Django REST Framework: pip install djangorestframework 2.在Sett ...

  3. 完整的Django入门指南学习笔记2

    part2: 前沿 在第一节中,我们安装了项目所需要的一切:Python3.6以及在虚拟环境中运行的Django2.0,这部分教程继续在项目上编写代码. 开始写代码前,先讨论下项目的相关背景知识,然后 ...

  4. django——模板层

    每一个Web框架都需要一种很便利的方法用于动态生成HTML页面. 最常见的做法是使用模板. 模板包含所需HTML页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分. 说白了,模板层就是 ...

  5. 完整的Django入门指南学习笔记3

    前言 在本节课中,我们将深入理解两个基本概念: URLs 和 Forms.在这个过程中,我们还将学习其它很多概念,如创建可重用模板和安装第三方库.同时我们还将编写大量单元测试. 如果你是从这个系列教程 ...

  6. Django模板层

    一:模板简介 二:模板语法值变量 三: 模板之过滤器 四: 模板之标签 五:自定义标签和过滤器   一:模板简介 def current_datetime(request): now=datetime ...

  7. 关于Django路由层简单笔记

    Django—路由层 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来的某个U ...

  8. Django——模板层(template)(模板语法、自定义模板过滤器及标签、模板继承)

    前言:当我们想在页面上给客户端返回一个当前时间,一些初学者可能会很自然的想到用占位符,字符串拼接来达到我们想要的效果,但是这样做会有一个问题,HTML被直接硬编码在 Python代码之中. 1 2 3 ...

  9. Django模板层之templates

    一 模版简介 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. def current_datetime(request): now ...

随机推荐

  1. 用PHP实现的快速排序算法(支持记录原始数组下标)

    代码如下 <?php /** * 快速排序 */ define("MAX_LENGTH_INSERT_SORT", 7); class QuickSort { /** * 交 ...

  2. 【WPF学习】第五十一章 动画缓动

    线性动画的一个缺点是,它通常让人觉得很机械且不能够自然.相比而言,高级的用户界面具有模拟真实世界系统的动画效果.例如,可能使用具有触觉的下压按钮,当单击时按钮快速弹回,但是当没有进行操作时它们会慢慢地 ...

  3. iOS 使用系统的UITabBarController 修改展示的图片大小

    1. 设置TabBarItem图片的大小 1 - (void)configurationAppTabBarAndNavigationBar { // 选中的item普通状态图片的大小 UIImage ...

  4. Docker实战之Kafka集群

    1. 概述 Apache Kafka 是一个快速.可扩展的.高吞吐.可容错的分布式发布订阅消息系统.其具有高吞吐量.内置分区.支持数据副本和容错的特性,适合在大规模消息处理场景中使用. 笔者之前在物联 ...

  5. MVC08

    1. c# 索引器(indexer) using System; using System.IO; namespace IO { class Program { ]; static void Main ...

  6. Git将文件上传至Github过程

    1.安装Git工具(在这里就不多说了) 2.我们需要先创建一个本地的版本库(其实也就是一个文件夹). 你可以直接在桌面右击新建文件夹,也可以右击打开Git bash命令行窗口通过命令来创建. 现在我通 ...

  7. springboot1.5.9整合websocket实现实时显示的小demo

    最近由于项目需要实时显示数据库更新的数据变化情况,一开始想过在前端使用ajax异步轮询方法实现,但后面考虑到性能和流量等要求,就放弃该方法而选择使用websocket(毕竟现在springboot整合 ...

  8. RedisTemplate:我不背锅,是你用错了

    今天分享一个RedisTemplate的问题,感兴趣的可以继续看下去了,不感兴趣的继续撩妹去吧! 如下图:一位朋友给了我一个报错的图片,为啥为啥取不到值? 我也有点懵,第一反应就是RedisTempl ...

  9. 06 yarn是什么

    yarn集群中有两个角色: 主节点:Resource Manager  1台 从节点:Node Manager   N台 Resource Manager一般安装在一台专门的机器上 Node Mana ...

  10. golang的sync.WaitGroup使用示例

    下面一段代码 len(m) 不一定会打印为 10,为什么?.如果想要 len(m) 打印为 10,应该怎么修改代码? func main() { const N = 10 m := make(map[ ...