Django模板层学习笔记
一. 前言
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>),前端之后把你当成普通的字符串。当我们想要让前端帮我们执行提交的字符串中的标签内容时,有两种方式。
- 在前端通过{{ 字符串|safe }}告诉前端字符串很安全,让它大胆执行。
- 后端用模块操作一下字符串,告诉前端我们给它的字符串很安全。
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
要自定义过滤器与标签,必须先做三件事:
- 在应用文件夹下新建templatetags文件夹(必须叫这个名字)
- 在templatetags文件夹中新建一个py文件,名字任意,不过最好不要有中文
- 在该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模板层学习笔记的更多相关文章
- NVelocity模板引擎学习笔记
NVelocity模板引擎学习笔记 学习模板引擎有一段时间现在做一些总结
- Django RF:学习笔记(8)——快速开始
Django RF:学习笔记(8)——快速开始 安装配置 1.使用Pip安装Django REST Framework: pip install djangorestframework 2.在Sett ...
- 完整的Django入门指南学习笔记2
part2: 前沿 在第一节中,我们安装了项目所需要的一切:Python3.6以及在虚拟环境中运行的Django2.0,这部分教程继续在项目上编写代码. 开始写代码前,先讨论下项目的相关背景知识,然后 ...
- django——模板层
每一个Web框架都需要一种很便利的方法用于动态生成HTML页面. 最常见的做法是使用模板. 模板包含所需HTML页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分. 说白了,模板层就是 ...
- 完整的Django入门指南学习笔记3
前言 在本节课中,我们将深入理解两个基本概念: URLs 和 Forms.在这个过程中,我们还将学习其它很多概念,如创建可重用模板和安装第三方库.同时我们还将编写大量单元测试. 如果你是从这个系列教程 ...
- Django模板层
一:模板简介 二:模板语法值变量 三: 模板之过滤器 四: 模板之标签 五:自定义标签和过滤器 一:模板简介 def current_datetime(request): now=datetime ...
- 关于Django路由层简单笔记
Django—路由层 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来的某个U ...
- Django——模板层(template)(模板语法、自定义模板过滤器及标签、模板继承)
前言:当我们想在页面上给客户端返回一个当前时间,一些初学者可能会很自然的想到用占位符,字符串拼接来达到我们想要的效果,但是这样做会有一个问题,HTML被直接硬编码在 Python代码之中. 1 2 3 ...
- Django模板层之templates
一 模版简介 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. def current_datetime(request): now ...
随机推荐
- vue基础指令了解
Vue了解 """ vue框架 vue是前台框架:Angular.React.Vue vue:结合其他框架优点.轻量级.中文API.数据驱动.双向绑定.MVVM设计模式. ...
- 18岁,赚到了人生中的第一个10W!
大家好,我是九歌 今年我18岁,赚到了我人生中的第一个10W 截至2019年10月14日,我已经做了43天的公众号啦,粉丝也悄然增长到了1W8,感谢各位读者朋友给我的支持和鼓励. 相信大部分读者都是从 ...
- wxpython(2)--按钮,位图按钮,滑动块,微调控制器
本文介绍按钮,位图按钮,滑动块,微调控制器**.. 按钮 基本按钮 创建一个按钮,绑定点击事件,点击后修改Label 123456789101112131415161718 import wx cla ...
- Wordpress 外网访问时不显示图片解决办法
我的云服务器是 :windows2012R 打开命令行: 进入到mysql中 show databases; //查看你Wordpress使用的数据库是否存在 use blog; //例如你使用的数据 ...
- 成长日记(2) Java面向对象
本篇主要是记录自己在学习路上的笔记,如果有哪里记错了请大家直接指出 面向对象的概念 *人为抽象的一种编程模型 *面向过程 代码集中 难以维护 *类:对事物 算法 逻辑 概念等的抽象 理解成 模板 图纸 ...
- CSS 加载动画
CSS加载动画 实现加载动画效果,需要的两个关键步骤: 1.做出环形外观 border:16px solid #f3f3f3; border-radius:50%; border-top:16px s ...
- 得亏了它,我才把潜藏那么深的Bug挖出来
2020年写了很多事故解决的文章,并不是我绞尽脑汁想出来的,而是真的遇到了这些问题.通过文章的方式记录下来,分享出去,才有意义. 事故背景 首先看下面的图吧,这是我从cat上截的图. 可以看到是一个R ...
- Vue 项目分环境打包
我们开发项目的时候,用vue-cli 2.x版本新建的项目,只有dev, pro两种开发环境, 有时需要个test环境来给测试使用,所以找了很多方法,总结了个最简单的方法来给大家使用 packa ...
- Python基础-求两个字符串最长公共前轴
最长公共前缀,输入两个字符串,如果存在公共前缀,求出最长的前缀,如果没有输出no.如“distance”和“discuss”的最长公共前缀是“dis”. s1 = input('请输入第1个字符串-- ...
- mysql从5.5升级到5.7遇到的坑
在安装mysql5.7时很顺利安装完成,但在启动项目时报错: [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clau ...