# 一、映射关系
在Django项目中与manage.py同级下创建一个名为templates的文件夹,其中用来存放html文件,作为View层
该文件夹中的html文件与views.py和urls.py文件存在对应关系
首先需要在settings.py中对模板路径进行修改,配置相对路径:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 配置相关html文件夹
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'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',
],
},
},
]
其中'DIRS': [os.path.join(BASE_DIR, 'templates')]
中的templates对应的就是存放html文件的文件夹
然后由于后续使用到了模板,所以在urls.py文件中使用render代替之前使用的HttpResponse,render可以使用字典context作为参数
from django.shortcuts import render
def test(request):
context = {'variable': 'variable01'}
return render(request, 'test.html', context)
# 二、模板标签
- 基本语法
views: {"HTML变量名称": "views变量"}
HTML: {{ HTML变量名称 }}
Django中可以使用三种参数作为模板
- 变量
- 列表:templates 中的 runoob.html中,可以用
.索引
下标取出对应的元素 - 字典:templates 中的 runoob.html中,可以用
.键
取出对应的值
views.py
from django.shortcuts import render
def test(request):
context = {
# 变量
'variable': 'variable01',
# 列表
'list': ['list_var01', 'list_var02'],
# 字典
'dictionary': {'name': 'dict_name', 'age': '20'}
}
return render(request, 'test.html', context)
test.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>变量:{{ variable }}</h3>
<h3>列表全部展示:{{ list }}</h3>
<h3>列表索引:{{ list.0 }},{{ list.1 }}</h3>
<h3>字典按键展示:name->{{ dictionary.name }},age->{{ dictionary.age }}</h3>
</body>
</html>
# 三、过滤器
过滤器 | 描述 |
---|---|
upper | 以大写方式输出 |
add | 给value加上一个数值 |
addslashes | 单引号加上转义号 |
capfirst | 第一个字母大写 |
center | 输出指定长度的字符串,把变量居中 |
cut | 删除指定字符串 |
date | 格式化日期 |
default | 如果值不存在,则使用默认值代替 |
default_if_none | 如果值为None, 则使用默认值代替 |
dictsort | 按某字段排序,变量必须是一个dictionary |
dictsortreversed | 按某字段倒序排序,变量必须是dictionary |
divisibleby | 判断是否可以被数字整除 |
escape | 按HTML转义,比如将”<”转换为”<” |
filesizeformat | 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 |
first | 返回列表的第1个元素,变量必须是一个列表 |
floatformat | 转换为指定精度的小数,默认保留1位小数 |
get_digit | 从个位数开始截取指定位置的数字 |
join | 用指定分隔符连接列表 |
length | 返回列表中元素的个数或字符串长度 |
length_is | 检查列表,字符串长度是否符合指定的值 |
linebreaks | 用<p> 或<br> 标签包裹变量 |
linebreaksbr | 用<br/> 标签代替换行符 |
linenumbers | 为变量中的每一行加上行号 |
ljust | 输出指定长度的字符串,变量左对齐 |
lower | 字符串变小写 |
make_list | 将字符串转换为列表 |
pluralize | 根据数字确定是否输出英文复数符号 |
random | 返回列表的随机一项 |
removetags | 删除字符串中指定的HTML标记 |
rjust | 输出指定长度的字符串,变量右对齐 |
slice | 切片操作, 返回列表 |
slugify | 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 |
stringformat | 字符串格式化,语法同python |
time | 返回日期的时间部分 |
timesince | 以“到现在为止过了多长时间”显示时间变量 |
timeuntil | 以“从现在开始到时间变量”还有多长时间显示时间变量 |
title | 每个单词首字母大写 |
truncatewords | 将字符串转换为省略表达方式 |
truncatewords_html | 同上,但保留其中的HTML标签 |
urlencode | 将字符串中的特殊字符转换为url兼容表达方式 |
urlize | 将变量字符串中的url由纯文本变为链接 |
wordcount | 返回变量字符串中的单词数 |
yesno | 将布尔变量转换为字符串yes, no 或maybe |
# 四、标签
# 4.1if/else标签
基本语法格式如下:
{% if condition %}
... display
{% endif %}
或者:
{% if condition1 %}
... display 1
{% elif condition2 %}
... display 2
{% else %}
... display 3
{% endif %}
根据条件判断是否输出。if/else 支持嵌套
{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ),例如:
{% if athlete_list and coach_list %}
athletes 和 coaches 变量都是可用的。
{% endif %}
# 4.2for标签
{% for %} 允许我们在一个序列上迭代
与 Python 的 for 语句的情形类似,循环语法是 for X in Y ,Y 是要迭代的序列而 X 是在每一个特定的循环中使用的变量名称
每一次循环中,模板系统会渲染在{% for %}和{% endfor %}之间的所有内容
例如,给定一个运动员列表 athlete_list 变量,我们可以使用下面的代码来显示这个列表:
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
给标签增加一个 reversed 使得该列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
在 {% for %} 标签里可以通过 变量获取循环序号
- forloop.counter: 顺序获取循环序号,从 1 开始计算
- forloop.counter0: 顺序获取循环序号,从 0 开始计算
- forloop.revcounter: 倒序获取循环序号,结尾序号为 1
- forloop.revcounter0: 倒序获取循环序号,结尾序号为 0
- forloop.first(一般配合if标签使用): 第一条数据返回 True,其他数据返回 False
- forloop.last(一般配合if标签使用): 最后一条数据返回 True,其他数据返回 False
可以嵌套使用 {% for %} 标签:
{% for athlete in athlete_list %}
<h1>{{ athlete.name }}</h1>
<ul>
{% for sport in athlete.sports_played %}
<li>{{ sport }}</li>
{% endfor %}
</ul>
{% endfor %}
# 4.3ifequal/ifnotequal标签
{% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值
下面的例子比较两个模板变量 user 和 currentuser :
{% ifequal user currentuser %}
<h1>Welcome!</h1>
{% endifequal %}
和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签:
{% ifequal section 'sitenews' %}
<h1>Site News</h1>
{% else %}
<h1>No News Here</h1>
{% endifequal %}
# 4.4注释标签
Django 注释使用 {# #}
{# 这是一个注释 #}
# 4.5include标签
{% include %} 标签允许在模板中包含其它的模板的内容
下面这个例子都包含了 nav.html 模板:
{% include "nav.html" %}
# 4.6csrf_token标签
csrf_token 用于form表单中,作用是跨站请求伪造保护
如果不用{% csrf_token %}标签,在用 form 表单时,要再次跳转页面会报403权限错误。
用了{% csrf_token %}标签,在 form 表单提交数据时,才会成功。
解析:
首先,向服务器发送请求,获取登录页面,此时中间件 csrf 会自动生成一个隐藏input标签,该标签里的 value 属性的值是一个随机的字符串,用户获取到登录页面的同时也获取到了这个隐藏的input标签。
然后,等用户需要用到form表单提交数据的时候,会携带这个 input 标签一起提交给中间件 csrf,原因是 form 表单提交数据时,会包括所有的 input 标签,中间件 csrf 接收到数据时,会判断,这个随机字符串是不是第一次它发给用户的那个,如果是,则数据提交成功,如果不是,则返回403权限错误。
# 五、自定义过滤器/标签
- 在应用目录下创建 templatetags目录(与templates目录同级,目录名只能是templatetags)。
HelloWorld/
|-- HelloWorld
| |-- __init__.py
| |-- __init__.pyc
| |-- settings.py
...
|-- manage.py
`-- templatetags
`-- templates
在 templatetags 目录下创建任意 py 文件,如:my_tags.py。
my_tags.py 文件代码如下:
from django import template
# register的名字是固定的,不可以改变
register = template.Library()
- 修改settings.py配置,添加libraries配置:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 配置相关html文件夹
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'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',
],
"libraries": {
'my_tags': 'templatetags.my_tags'
}
},
},
]
- 利用装饰器@register.filter自定义过滤器。
**注意:**装饰器的参数最多只能有 2 个
@register.filter
def my_filter(v1, v2):
return v1 * v2
- 利用装饰器@register.simple_tag自定义标签。
@register.simple_tag
def my_tag1(v1, v2, v3):
return v1 * v2 * v3
- 在使用自定义标签和过滤器前,要在html文件body的最上方中导入该py文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% load my_tags %}
<h1>自定义过滤器</h1>
<h3>{{ 11|my_filter:22 }}</h3>
<h1>自定义标签</h1>
<h3>{% my_tag 11 22 33 %}</h3>
</body>
</html>
- 语义化标签,在my_tags.py文件中使用mark_safe方法,使标签语义化
from django.utils.safestring import mark_safe
# register的名字是固定的,不可以改变
register = template.Library()
# 语义化标签
@register.simple_tag
def my_html(v1, v2):
temp_html = "<input type='text' id='%s' class='%s' />" %(v1, v2)
return mark_safe(temp_html)
html调用语义化标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% load my_tags %}
<h1>变量</h1>
<h3>变量:{{ variable }}</h3>
<h3>列表全部展示:{{ list }}</h3>
<h3>列表索引:{{ list.0 }},{{ list.1 }}</h3>
<h3>字典按键展示:name->{{ dictionary.name }},age->{{ dictionary.age }}</h3>
<h1>过滤器</h1>
<h3>{{ variable|upper }}</h3>
<h3>{{ variable|lower }}</h3>
<h3>{{ variable|length }}</h3>
<h3>{{ variable|first|upper }}</h3>
<h1>标签</h1>
<ul>
{% for i in list %}
<h3>{{ i }}</h3>
{% endfor %}
</ul>
<h1>自定义过滤器</h1>
<h3>{{ 11|my_filter:22 }}</h3>
<h1>自定义标签</h1>
<h3>{% my_tag 11 22 33 %}</h3>
<h1>语义化标签</h1>
{% my_html "zzz" "xxx" %}
</body>
</html>
# 六、静态文件配置
- 在项目根目录下创建 statics 目录。
- 在 settings 文件的最下方配置添加以下配置:
STATIC_URL = '/static/' # 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"),
]
在 statics 目录下创建 css 目录,js 目录,images 目录,plugins 目录, 分别放 css文件,js文件,图片,插件。
把 bootstrap 框架放入插件目录 plugins。
在 HTML 文件的 head 标签中引入 bootstrap。
注意:此时引用路径中的要用配置文件中的别名 static,而不是目录 statics
<link rel="stylesheet" href="/static/plugins/bootstrap-5.1.3-dist/css/bootstrap.css">
在模板中使用需要加入{% load static %}代码,以下实例我们从静态目录中引入图片