基本规则
模板通过render返回
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
- BACKEND:是实现Django模板后端API的模板引擎类的路径。内置是django.template.backends.django.DjangoTemplates和 django.template.backends.jinja2.Jinja2(使用这个需要额外安装jinja2库)
- DIRS :按搜索顺序定义引擎应该查找模板源文件的目录列表
- APP_DIRS:告诉引擎是否应该在已安装的应用程序中查找模板
- OPTIONS:包含后端特定的设置
多引擎用法
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
'/home/html/example.com',
'/home/html/default',
],
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
'/home/html/jinja2',
],
},
]
django.template.loader.get_template
该函数使用给定名称加载模板并返回一个 Template对象,找到第一个匹配的模板即返回
template = get_template('story_detail.html')
Django将要查找的文件,依次为:
- /home/html/example.com/story_detail.html('django'引擎)
- /home/html/default/story_detail.html('django'引擎)
- /home/html/jinja2/story_detail.html('jinja2'引擎)
方法的模板查找FVB
from django.shortcuts import render
def my_view(request):
return render(
request,
'myapp/index.html',
{'foo': 'bar'},
content_type='application/xhtml+xml'
)
loader方法
from django.http import HttpResponse
from django.template import loader
def my_view(request):
t = loader.get_template('myapp/index.html')
# t = loader.select_template(['myapp/index1.html','myapp/index2.html'])
c = {'foo': 'bar'}
return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
从方法进入,找第一个文件,通过setting配置信息自上而下搜索,没找到在找第二个文件,然后重复直到找到,或者没文件找了报错
Django将要查找的文件,依次为:
- /home/html/example.com/myapp/index1.html('django'引擎)
- /home/html/default/myapp/index1.html('django'引擎)
- /home/html/jinja2/myapp/index1.html('jinja2'引擎)
- /home/html/example.com/myapp/index2.html('django'引擎)
- /home/html/default/myapp/index2.html('django'引擎)
- /home/html/jinja2/myapp/index2.html('jinja2'引擎)
变量
Django 模板语言的语法涉及四个构造
- 变量: 变量从上下文中输出一个值,上下文是一个类似于字典的对象,将键映射到值
- 标签: 标签在渲染过程中提供使用逻辑的方法,比如:if和for
- 过滤器: 过滤器转换变量和标签参数的值
- Comments: 注释
变量
变量被这样包围 :{{变量}} ,如下所示:
定义:学的技术是 {{ first_name }}. 语言为 {{ last_name }}
传参:{'first_name': 'IT', 'last_name': 'Python'}
输出:我学的技术是 IT. 语言为 Python
带有属性的对象也是可以的
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
render使用模板
模板标签if elif else ……逻辑运算符的使用
标签被 {%
和 %}
包围
if
判断标签{% if %} {% endif %} :
# athlete_list 不为空
{% if athlete_list %}
# 输出 athlete_list 的长度 | 是过滤器
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
firstof
输出不是False的第一个参数,所有参数都为False,则什么都不输出
{% firstof var1 var2 var3 %}
等同于
{% if var1 %}
{{ var1 }}
{% elif var2 %}
{{ var2 }}
{% elif var3 %}
{{ var3 }}
{% endif %}
使用默认值:
{% firstof var1 var2 var3 "默认值" %}
逻辑运算符
and、or和not and优先级高于or
{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% endif %}
{% if not athlete_list %}
There are no athletes.
{% endif %}
{% if athlete_list or coach_list %}
There are some athletes or some coaches.
{% endif %}
{% if not athlete_list or coach_list %}
There are no athletes or there are some coaches.
{% endif %}
{% if athlete_list and not coach_list %}
There are some athletes and absolutely no coaches.
{% endif %}
比较运算符
==, !=, <, >, <=, >=, in, not in, is, 和 is not
{% if somevar == "x" %}
This appears if variable somevar equals the string "x"
{% endif %}
{% if "bc" in "abcdef" %}
This appears since "bc" is a substring of "abcdef"
{% endif %}
{% if somevar is not True %}
This appears if somevar is not True, or if somevar is not found in the
context.
{% endif %}
优先级,从低到高:
- or
- and
- not
- in
- ==,!=,<,>,<=,>=
for
循环遍历,{% for %} {% endfor %} 结束 ,可以遍历列表,字典等
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
反向循环:
{% for athlete in athlete_list reversed%}
字典: data.items 这种调用方法,是不加 () 的
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}
设置默认值, for empty ,类似python的 for else:
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
等同于,但是比下面的写法更加简便:
<ul>
{% if athlete_list %}
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
{% else %}
<li>Sorry, no athletes in this list.</li>
{% endif %}
</ul>
for循环在循环中设置了许多变量:
变量名 | 描述 |
---|---|
forloop.counter | 循环计数器,表示当前循环的索引(从 1 开始)。 |
forloop.counter0 | 循环计数器,表示当前循环的索引(从 0 开始)。 |
forloop.revcounter | 反向循环计数器(以最后一次循环为 1 ,反向计数)。 |
forloop.revcounter0 | 反向循环计数器(以最后一次循环为 0 ,反向计数)。 |
forloop.first | 当前循环为首个循环时,该变量为 True |
forloop.last | 当前循环为最后一个循环时,该变量为 True |
forloop.parentloop | 在嵌套循环中,指向当前循环的上级循环 |
url标签
{% url 'some-url-name' v1 v2 %}
第一个参数是url模式名称,后面跟着的是参数,以空格分隔
可以使用关键字:
{% url 'some-url-name' arg1=v1 arg2=v2 %}
如果您想检索命名空间的URL,请指定完全限定的名称:
{% url 'myapp:view-name' %}
with标签
{% with %}
和 {% endwith %}
, 简单的名称缓存复杂变量,当访问多次耗时的方法
{% with total=business.employees.count%}
{{ total }} employee
{% endwith %}
{% with a=1 b=2 %}
...
{% endwith %}
过滤器
具体方法查看官方文档:内置模板标签和过滤器 | Django 文档 | Django
通过|
来使用
CSRF_token
csrf_token是解决CSRF跨站请求伪造的方式,安全性
Django提供CSRF的中间件
# 无参数标签 csrf_token ,这个标签是用于html进行 form 表单提交时,包含一个 随机变化的字符串,在html页面中,其实就是一个 input type='hidden'
# 作用是用于防止跨域攻击
{% csrf_token %}
静态模板的使用
在settings.py中配置static文件夹位置,注意文件夹创建位置应该在主应用下面,和子应用同级别
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
在html文件中使用方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>静态模板使用</title>
{% load static %}
<link rel="stylesheet" href="{% static '/css/static_css.css' %}">
</head>
<body>
<h1>静态模板使用</h1>
<img src="{% static '/imgs/1.png' %}" alt="我们的歌">
</body>
</html>
注意的一点是在编写url路径的时候不要将路径名称设置为static和STATIC_URL同名
include标签
在当前模板中引入另外一个模板内容
使用方法
模板名称可以是变量,也可以是单引号或双引号的硬编码(带引号)的字符串
{% include "文件夹/bar.html" %}
{% include template_name %}
include传参数
view传参 在视图函数render模板返回处传参,通用模板也可以获取参数
-
context
render(request, 'temp.html',{'greeting': 'hello', 'person': 'John'})
-
模板传参 在模板内传参使用with关键字
-
原模板通过with传递参数
{% include "name_snippet.html" with person="John" greeting="Hello" %}
模板与view同时传参,模板参数值 优先 view参数
模板的继承,子模版使用的时候可以替换掉父模板中可替换的信息
如下,定义一个base.html, 如下:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock sidebar %}
</div>
<div id="content">
{% block content %}{% endblock content %}
</div>
</body>
</html>
block的基本使用方法:{% block title %} {% endblock %}
继承父模板
子页面detail.html继承上面这个base.html,内容如下
{% extends "base.html" %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
使用{% extends "base.html" %} 继承 base.html,本页面有2个block,对应base.html的2个block,会在base.html中,使用本detail.html的对应内容进行替换,而block sidebar 并没有对应的block,因此继续使用base.html的 sidebar 的内容
- 如果在模板中使用,{% extends %}必须是该模板中的第一个模板标签。否则模板继承将不起作用。
- 基本模板中的越多{% block %}标签越好。子模板不必定义所有父块,因此可以在多个块中填写合理的默认值
- 如果发现自己在多个模板中复制了内容,则可能意味着您应该将该内容移至父模板的 {% block %} 中
- 如果需要从父模板中获取块的内容,则使用 {{ block.super }}
- 在使用模板标签语法之外创建的变量不能在块{% block% }内使用。例如,该模板不会呈现任何内容