Django基础入门⑦:Django模板继承
🏘️🏘️个人简介:以山河作礼。
🎖️🎖️:Python领域新星创作者,CSDN实力新星认证,阿里云社区专家博主,CSDN内容合伙人
🎁🎁:Web全栈开发专栏:《Web全栈开发》免费专栏,欢迎阅读!
🎁🎁:文章末尾扫描二维码可以加入粉丝交流群,不定期免费送书。
Django模板补充
load加载标签或过滤器
可以使用load
标签和load
过滤器来加载其他模板标签或自定义过滤器。
- 加载标签
要加载其他模板标签,可以在模板中使用load
标签,指定要加载的标签库:
{% load my_tags %}
其中,my_tags
是标签库的名称,在这个例子中,引入了一个自定义标签库my_tags
。
然后就可以在模板中使用这个标签库中的标签,例如:
{% my_tag arg1 arg2 %}
其中,my_tag
是标签库my_tags
中定义的标签名称,arg1
、arg2
则是传递给标签的参数。
- 加载过滤器
要加载自定义的过滤器,也可以使用load
标签,指定要加载的过滤器库:
{% load my_filters %}
其中,my_filters
是过滤器库的名称,在这个例子中,引入了一个自定义过滤器库my_filters
。
然后就可以在模板中使用这个过滤器库中的过滤器,例如:
{{ my_value|my_filter }}
其中,my_value
是需要过滤的变量,my_filter
是过滤器库my_filters
中定义的过滤器名称。
要定义自定义的模板标签或过滤器,可以在app目录下新建一个
templatetags
包,并在其中定义标签库或过滤器库。在标签库或过滤器库中定义的标签或过滤器,可以在其他模板中使用。
过滤器与标签在于使用的装饰器不同,过滤器采用@register.filter
在templatetags包中创建一个名为my_filters.py的文件,并在其中定义你的自定义过滤器。例如,定义一个将字符串反向的过滤器:
from django import template
register = template.Library()
# 定义过滤标签
@register.filter
def reverse_str(value):
return value[::-1]
# 视图中使用过滤标签
{% load book_tags %}
{{ name|reverse_str }}
load 标签加载静态文件
load 标签用于在模板中加载自定义模板标签集或者过滤器,可以加载项目中的静态文件,格式使用如下:
{% load static %} # 加载静态文件
使用static
模板标签需要先在settings.py
中定义静态文件的目录:
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
其中,
STATIC_URL
是静态文件的URL前缀,STATICFILES_DIRS
是静态文件所在的目录。这里的/static/
指的是静态文件在项目中的URL前缀,BASE_DIR / 'static'
则是静态文件所在的物理目录路径。
后在模板中使用static
模板标签加载静态文件,例如:
{% load static %}
<img src="{% static 'images/example.png' %}" alt="example image">
上面的代码中,
{% load static %}
用于加载static
模板标签,而{% static 'images/example.png'%}
则用于生成指向静态文件/static/images/example.png
的URL,以便在模板中使用。
加载示例:
要在Django中加载CSS或JavaScript文件,可以使用static
模板标签中的特殊语法。下面是一个例子:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<script type="text/javascript" src="{% static 'js/main.js' %}"></script>
在上面的代码中,我们首先加载
static
模板标签,这样我们才能在模板中使用它。然后,我们使用href
属性指定要加载的CSS文件css/style.css
,并通过src
属性的值来加载JavaScript文件js/main.js
。这些路径都由static
标签解释器解析,固定使用的前缀是在STATIC_URL
设置中定义的值。
当使用
{% static %}
标签时,我们向它提供了一个路径参数,这个路径应该相对于STATICFILES_DIRS
中指定的某个目录,它是你的项目的静态资源存储在其中的地方。在默认情况下,这个目录是一个名为static
的子目录,但是我们可以使用任何我们喜欢的名称,只需在之前设置STATICFILES_DIRS
就可以了
。
注意点:
使用 load
函数加载静态文件,常用于在模板中引入 CSS、JavaScript 等静态文件。如果不使用 load
函数,可能会遇到以下问题:
- 文件路径不正确:没有使用
load
函数时,需要手动在模板文件中设置正确的文件路径,如果路径设置不正确,静态文件无法正确加载。 - 缓存问题:Django 在加载静态文件时,会利用缓存减少静态文件的访问,如果不通过
load
函数来加载静态文件,可能影响缓存的使用效果。 - 安全问题:如果静态文件的地址通过手动设置,可能存在安全问题,例如可能会导致 XSS 攻击等问题。
因此,建议在 Django 中还是使用 load
函数加载静态文件,以确保静态文件的准确性、安全性和性能。
csrf_token标签
csrf_token
标签是Django提供的一个内置模板标签,用于在表单中包含CSRF令牌,以提供一定的安全措施。CSRF代表跨站点请求伪造,它是一种常见的网络攻击类型,可以通过伪造用户会话来执行未授权的操作。
在Django中使用csrf_token
标签非常简单,只需在表单中使用它即可。例如:
<form method="post">
{% csrf_token %}
<input type="text" name="username">
<input type="password" name="password">
<button type="submit">登录</button>
</form>
在上面的代码中,我们使用
{% csrf_token %}
标签在表单中包含了CSRF令牌。这个标签将生成一个包含令牌值的隐藏字段,这个值是从浏览器的Cookies中自动获取的。当用户提交表单时,这个令牌将与请求一起发送到服务器,并由Django进行验证。
注意,在使用csrf_token
标签时,必须确保表单的方法是POST,否则Django将不会生成CSRF令牌,并会引发一个警告。例如,如果你的表单使用GET方法,那么Django将不会为它生成CSRF令牌,这可能会导致不安全的代码行为。
模板语言的注释
注释可以使用两个大括号和一个#号进行,如下所示:
{# 这是一个注释 #}
你可以在Django模板中使用注释标签来记录特定的指令、提醒特定的模板维护人员进行针对性的修改等。
例如,在一个页面的头部模板中,你可以添加一条注释来提醒某个开发人员更新他的JavaScript文件:
{# 辉辉,不要忘记更新你的 JavaScript 文件! #}
注释将不会被渲染为HTML页面的一部分,而是被视为模板语法的一部分,并且将在呈现前被忽略。因此,注释在查看Django模板的源代码时是可见的,但在实际呈现该页面时不会被包含在生成的内容中。
在模板标签中也可以使用注释。你可以在模板标签中注释多行文本,而且不用担心它会影响模板的呈现。例如:
{% comment %}
文本内容1
文本内容2
{% endcomment %}
上面的代码会被完全忽略掉,不会有任何影响。通常,模板标签中的注释对于提供针对性的指令或与团队进行特定方面的沟通特别有用。
Django模板继承
Django模板继承是一个强大的工具,可以将通用页面元素(例如页眉、页脚、侧边栏等)分离出来,并在多个页面之间共享他们。
模板继承和 Python 语言中类的继承含义是一样的,在 Django 中模板只是一个文本文件,如 HTML。
模板继承的概念
模板继承是 Django 模板语言中最强大的部分。模板继承使你可以构建基本的“骨架”模板,将通用的功能或者属性写在基础模板中,也叫基类模板或者父模板。子模板可以继承父类模板,子模板继承后将自动拥有父类中的属性和方,我们还可以在子模板中对父模板进行重写,即重写父模板中方法或者属性,从而实现子模板的定制。模板继承大大提高了代码的可重用性,减轻开发人员的工作量。
模板继承应用
在模板继承中最常用了标签就是 {% block %} 与 {% extends %} 标签,其中 {% block% } 标签与 {% endblock %} 标签成对出现,而 {% extends %} 放在子模板的第一行且必须是模板中的第一个标签,标志着此模板继承自父模板,它们使用方法如下所示:
#定义父模板可被重写内容
{% block block_name %}
...可以被子模板覆盖的内容
{% endblock block_name %}
#继承父模板
{% extends '父模板名称' %}
#子模板重写父模板
{% block block_name %}
...子模板覆盖后呈现的新内容
{% endblock block_name %}
需要注意的是子模板不需要重写父模板中的所有 block标签定义的内容,未重写时,子模板原封不动的使用父模板中的内容。下面我们通过一个简单的例子来看一下具体的实现过程。
首先在 templates/index 目录下定义父模板 base.html,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome to 我的课堂 {% endblock title %}</title>
</head>
<body>
<!--区域1默认区域不可以被子模板修改-->
<p>亲爱的同学您好:</p>
<hr>
<!--区域2可以被子模板重写-->
{% block content %}
<p>这是主体内容可以被子模板重写</p>
{% endblock content %}
<hr>
<!--区域3可以被子模板重写-->
{% block footer %}
<p>这是结尾的内容也可以被重写</p>
{% endblock footer %}
</body>
</html>
然后在父模板同级路径下定义子模板文件 test.html,代码如下所示:
{% extends 'index/base.html' %}
<!--重写title-->
{% block title %} 欢迎你学习Django教程 {% endblock %}
<!--区域1保持父模板默认状态-->
<!--对父模板的区域2进行重写-->
{% block content %}
{% for item in course %}
<li>{{ item }}</li>
{% endfor %}
{% endblock content %}
{% block footer %}
<p>最后希望<span style="color:green">{{ name }}</span>可以学有所成</p>
{% endblock footer %}
在 index/views.py 文件编写视图函数,如下所示:
# 定义父模板视图函数
def base_html(request):
return render(request, 'index/base.html')
# 定义子模板视图函数
def index_html(request):
name = 'xiaoming'
course = ['python', 'django', 'flask']
return render(request, 'index/test.html', locals())
然后更新子路由,代码如下所示:
# 127.0.0.1:8000/index/test 访问子模板
path('test/', views.index_html),
# 127.0.0.1:8000/index/base 访问父模板
path('base/', views.base_html)
我们在父模板中标记了哪些区域可以被子模板重写覆盖,现在我们访问子模板地址.
我们可以看出,子模板对父模板中 {% block %}包含的内容进行了重写覆盖,这就是模板继承应用。如果在多个模板中出现了大量复杂的代码,那么就应该考虑使用模板继承来减少重复性代码。
总结归纳
本节介绍了模板继承的使用,以及它的优势,Django 官网建议,在父模板中应尽量多的使用 {% block %} 标签,这样可以给我们更多的选择空间。本节知识点总结如下:
- block 标签需要成对出现,使用 {{ endblock }} 作为结束标签;
- 定义 block 标签名字,子模板中具有同样名称的 block 块完成对父模板的替换;
- 子模板不需要定义父模板中的所有 block,未定义时,子模板将原样使用父模板中的内容;
- 子模板需要使用 {% extends %} 标签继承父模板,且必须是模板中的第一个标签,并放在文件的第一行;