博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django(三)模板
阅读量:2302 次
发布时间:2019-05-09

本文共 6013 字,大约阅读时间需要 20 分钟。

1 简介

1.1 什么是模板

视图函数的作用是生成请求的响应,这种响应通常就是用户所看到的html网页。模板就是带有模板语法({

{ }}, {% %})的html文件,它能接收视图函数传递的变量,通过模板引擎,模板被渲染成html页面。

1.2 语法

在模板中,使用{

{ }}结构表示一个变量,它是一种特殊的占位符,告诉模板引擎,这个位置的值从渲染模板时传入的变量获取;使用{% %}结构渲染标签(控制结构)。

1.3模板查找机制

模板一般放在应用下的templates文件夹,Django的模板渲染引擎会自动查找所有应用下这个文件夹,直到找到指定的模板,因此如果不同应用下有同名的模板,Django很可能找错。因此建议的做法是,在每个应用下的templates文件夹下创建以应用名命名的文件夹,将与该应用相关的模板放在这个文件夹中,就像这样:app/templates/app/XXX.html。当视图函数返回render响应时,相应地在模板名称前加上app的名字,就像这样:return render('app/XXX.html')

2 模板变量

2.1 深度查询

Django的模板引擎能识别python中所有类型的变量,对于列表、字典、和对象这些复杂的变量,我们可以通过万能的句点法(深度查询)来访问集合或对象,比如:

对列表取值:{

{ list.index }}

对字典取值: {

{ dict.key }}

访问对象的属性: {

{ obj.attr }}

2.2 使用变量过滤器

作用:修改变量在模板中的显示

格式:{
{ var|filter: arg }}
注意,过滤器函数默认接收变量,除此之外,最多只能接收一个参数

看个栗子:

1.我们在视图函数中定义一些变量,通过locals()全部传入模板渲染

def index(request):    string = 'he l lo'    day = datetime.datetime.now()    l = []    post = "this is my post, it's very very very long"    k = ['cat', 'dog', 'pig']    size = 12345678    return render(request, 'blog/index.html', locals()) # 注意,blog前不要加/    # locals() 将视图中的所有变量对应到模板中的变量

2.在模板中应用过滤器来修改变量

filter过滤器效果!

{
{ string }} --> {
{ string|cut:" " }} 剔除指定字符串

{
{ day }} --> {
{ day|date:"Y-m-d" }} 格式化日期

{
{ l }} --> {
{ l|default:"查询结果为空" }} 当集合为空时,设置默认显示,比如数据库查询结果为空时,我们自定义前端的提示信息

{
{ post }} --> {
{ post|truncatewords:6 }} 截断指定数量的单词,可用于显示文章摘要

{
{ k }} --> {
{ k|join:", " }} 拼接列表

{
{ size }} --> {
{ size|filesizeformat }} 显示友好的文件大小

3.浏览器显示效果:

这里写图片描述

4.变量过滤器一览

过滤器 说明
add 给变量加上一个值
addslashes 给变量中的引号前加/斜线
capfirst 首字母大写
lower 转换为小写
truncatewords:30 截断指定数量的单词,可用于显示文章摘要
join 用指定字符拼接列表
default 如果变量为空或false,使用默认值
length 显示字符串/列表的长度
filesizeformat 显示易读的文件大小
date 格式化日期字符串
cut 从字符串中移除指定的字符
safe 渲染值时不转义。出于安全考虑,模板引擎会转义所有的变量。如果确实需要显示变量中的html代码,就可以使用safe过滤器。不要对不可信的变量使用safe过滤器,比如用户提交的表单中输入的文本,可能包含攻击代码。

过滤器也支持链式操作:

{
{ var|filter1|filter2 }}

5.更多过滤器的使用,请参考

2.3 自定义过滤器和标签

2.3.1 自定义过滤器

过滤器本质就是一个函数,只需要如下几步,我们也可以定制自己的过滤器

1. 将当前应用添加到settings.py的INSTALLED_APPS 列表中
2. 在项目的应用文件夹下新建一个包,命名为templatetags
3. 在刚刚新建的包下写一个脚本,比如my_filter.py:

```from django import templateregister = template.Library()# 导入template 并实例化一个对象,命名为 register@register.filter  # 装饰自定义函数为过滤器def num_to_char(x): # 自定义函数,将数字转为字符    return chr(x)```

4. 在模板的<head>标签内中导入自定义的过滤器(使用前导入就行,不一定非要在<head>内):{% load my_filter %} 。另外,发现一个问题,自定义过滤器导入后,自带的过滤器可能工作不正常,具体原因不明,有知道的伙伴可以分享下。

5. 重启服务,你就可以使用自定义的过滤器了

2.3.2 自定义标签

自定义标签的流程和自定义过滤器是相同的,只是装饰器修改为@register.simple_tag

另外在使用格式上,自定义标签是这样:
{% func var [arg1] [arg2] ... [argn] %}
二者的其他差异:
1. 过滤器除了接收变量本身,最多可以额外接收一个参数,而自定义标签无限制
2. 过滤器可以配合其它标签使用,比如if控制语句:

```{% if var|filter %}    do something```但是自定义标签不能这样使用。

补充:自定义标签的另一种形式 inclusion_tag:

  1. 应用下新建templatetags目录,新建脚本custom_tag.py,通过inclusion_tag自定义标签

    from django.template.library import Libraryregister = Library()@register.inclusion_tag('sample.html')def get_result(x):    print('do something')    return {
    'content': 'XXX', 'comments': ['aa', 'bb', 'cc']}

    说明:

    • inclusion_tag接收一个模板路径,这里是”sample.html”,并将函数的返回值拿到模板中渲染
    • “sample.html”模板的渲染结果,返回给调用该自定义标签的模板中,即步骤3的模板。
  2. 定义”sample.html”模板:

    {
    { content }}
      {% for comment in comments %}
    • {
      { comment }}
    • {% endfor %}
  3. 调用自定义标签:

    {% load custom_tag %}
    {% get_result x %}

3 控制结构

Django的模板引擎提供了多种控制结构,用来改变模板的渲染流程。

3.1 if语句

{% if user %}    Hello, {
{ user }}!{% else %} Hello, {
{ Stranger }}!{% endif %}

3.2 for循环

渲染从数据库取出的一组评论,使用for循环可以实现这一需求

    {% for comment in comments %}
  • {
    { comment }}
  • {% endfor %}

3.2.1 forloop变量

forloop用在for循环内,配合if语句,可以用来控制循环:

1. forloop.counter 索引,从1开始,可用于显示清单中条目的序号
2. forloop.counter0 索引,从0开始
3. forloop.revcounter 索引,倒序到1
4. forloop.revcounter0 索引,倒序到0
5. forloop.first 当第一次循环时,值为True
6. forloop.last 当第一次循环时,值为False

看个栗子:

    {% for comment in comments %}
    {% if forloop.first %}
  • {% else %}
  • {% endif %} {
    { comment }}
  • {% endfor %}

3.2.2 for … empty

for循环可以可以接受一个{% empty %}从句,如果循环的对象为空,将显示{% empty %}从句下的内容:

    {% for comment in comments %}
  • {
    { comment }}
  • {% empty %}
  • No comments yet!
  • {% endfor %}

3.3 代码重用

3.3.1 模板继承

模板继承(extends)类似Python中的类继承。它允许我们重用模板中相同的部分,定制不同的部分。首先,创建一个名为base.html的基模板:

    {% block head %}    {% block title %}Title{% endblock %}    {% endblock %}{% block body %}{% endblock %}

block标签定义的块可以在衍生模板中修改,并且每个block标签都有名字。这里,我们只是简单定义了head, title(因为每个页面都应该显示一个不同title), body的块。注意,title包含中head中。下面我们来写一个基模板的衍生模板:

{% extends 'base.html' %}{% block title %}Home{% endblock %}{% block head %}    {
{ block.super }} {% endblock %}{% block body %}

Hello, World!

{% endblock %}}

{% extends 'base.html' %}继承指令放在首行,声明该模板衍生自base.html。我们在衍生模板中重定义了三个block的内容,模板引擎会根据block名字,将其插入适当的位置。另外,通过{% block.super %},可以重用原来block中的内容,以便在其基础上添加内容。

3.3.2 模板包含

需要在多处重复使用的模板代码片段可以写在单独的文件,再包含(include)在要用的模板中,以避免重复:

{% include 'common.html' %}

3.4 其它标签

  • {% url %} 通过视图函数别名,生成url绝对路径,它还可以接收路由分组的参数: {% url 'name' v1 v2 %}
  • {% with %} 用更简单的变量名替代复杂的变量名
{% with total=business.employees.count %}    {
{ total }} employee{
{ total|pluralize }}{% endwith %}
{% with business.employees.count as total %}...{% endwith %}
  • {% verbatim %} 告诉模板引擎,不要渲染这个标签内的内容
{% verbatim %}    {
{ 我就是要显示两个花括号! }}{% endverbatim %}
  • {% load %} 载入自定义的模板标签,记住,目标不加引号

更多标签,请参考

模板上下文处理器

令某些变量在所有模板中可用,比如,网站的顶部分类菜单,在很多页面中都是相同的。

settings.py:

TEMPLATES = [    {        'BACKEND': 'django.template.backends.django.DjangoTemplates',        'DIRS': [os.path.join(BASE_DIR, 'templates')]        ,        'APP_DIRS': True,        'OPTIONS': {            'context_processors': [                'django.template.context_processors.debug',                # ...                'app.views.get_funcs', # 视图加入上下文处理器列表            ],        },    },]
FUNCTIONS = [    (1,"园子"),    (2,"随笔"),    (3,"新闻"),    (4,"博文"),]

views.py

def get_funcs(request):    return ({
"funcs": settings.FUNCTIONS})

template: funcs变量在所有模板中可用

{% for func in funcs %}    
  • {
    { func.1 }}
  • {% endfor %}
    你可能感兴趣的文章
    Raid详解
    查看>>
    MySQL5.7重启MySQL服务时报错解决方案
    查看>>
    Mycat简单实现读写分离与分库分表
    查看>>
    Swift Socket 实例 两份资料不错
    查看>>
    pthread之工作模式
    查看>>
    路由器DSCP target
    查看>>
    java.util.ConcurrentModificationException
    查看>>
    jquery拿到HtmlObject类型
    查看>>
    ddpush 学习之路 3 StringUtil.java
    查看>>
    Linux【oh-my-zsh】ls命令无法tab键跳转文件文件夹
    查看>>
    杂谈:项目管理的是与非
    查看>>
    Java1.0/1.1中遗留的集合
    查看>>
    Linux平台超级好用服务器远程管理工具webmin的安裝
    查看>>
    去掉Sublime Text 3烦人的更新新版本提醒
    查看>>
    启动vsftpd的问题---500 OOPS
    查看>>
    ubuntu lamp的部署
    查看>>
    CAS简单实例
    查看>>
    CAS结合openldap
    查看>>
    数据库基础知识
    查看>>
    Spring事务管理
    查看>>