什么是模板标签(tags)

模板标签都是放在{%  %}括号里的,常见的模板标签有{% load xxxx %}, {% block xxxx %}, {% if xxx %}, {% url 'xxxx'  %}。这些模板标签的本质也是函数,标签名一般即为函数名。这些标签的主要作用包括载入代码渲染模板或对传递过来的参数进行一定的逻辑判断或计算后返回。

比如下例中的url标签接收两个参数,一是命名的url, 一个是文章id,将其进行反向解析,生成一个类似blog/article/4/的链接。

<a href="{% url 'blog:article_detail' article.id  %}">详情</a>

Django模板标签(tags)的分类

Django的模板标签(tag)一共分2类:

simple_tag (简单标签 : 处理数据,返回一个字符串或者给context设置或添加变量。

inclusion_tag (包含标签) : 处理数据,返回一个渲染过的模板。

熟悉Django的都知道,我们一般在视图view里设置context,然后通过它来传递数据给模板。 一个context是一系列变量和它们值的集合。通过使用simple_tag, 我们可以在视图外给context设置或添加变量。注: Django 1.9以后不再支持assignment_tag了,均使用simple_tag。

如何自定义模板标签

首先你要在你的app目录下新建一个叫templatetags的文件夹(不能取其它名字), 里面必需包含__init__.py的空文件。在该目录下你还要新建一个python文件专门存放你自定义的模板标签函数,本例中为blog_extras.py,当然你也可以取其它名字。整个目录结构如下所示:

blog/
   __init__.py
   models.py
   templatetags/
       __init__.py
       blog_extras.py
   views.py
在模板中使用自定义的模板标签时,需要先使用{% load blog_extras %}载入自定义的过滤器,然后通过{% tag_name %} 使用它。

自定义模板标签的3个简单例子

我们将定义3个简单模板标签,一个返回string, 一个给模板context传递变量,一个显示渲染过的模板。我们在blog_extra.py里添加下面代码。

#blog_extra.pyfrom django import template
import datetime
from blog.models import Articleregister = template.Library()# use simple tag to show string
@register.simple_tag
def total_articles():return Article.objects.filter(status='p').count()# use simple tag to set context variable
@register.simple_tag
def get_first_article():return Article.objects.filter(status='p').order_by('-pub_date')[0]# show rendered template
@register.inclusion_tag('blog/latest_article_list.html')
def show_latest_articles(count=5):latest_articles = Article.objects.filter(status='p').order_by('-pub_date')[:count]return {'latest_articles': latest_articles, }
# latest_article_list.html<ul>
{% for article in latest_articles %}
<li>{{ article.title }} </li>
{% endfor %}
</ul>
# index.html (使用我们自定义的模板标签){% extends "blog/base.html" %}
{% load blog_extras %}{% block content %}<p>文章数: {% total_articles %}</p>
{% show_latest_articles %}{% get_first_article as first_article %}
<p>第一篇文章: </p>
<p>{{ first_article.title }}</p>{% endblock %}

一个复杂的例子: 从模板或context接收参数后返回结果

上述3个简单例子的信息传递都是单向的,更常见的情况是标签函数接收从模板或context传递过来的参数,处理后再返回字符串或渲染过的模板。

下例中show_results标签需要接收模板传递的poll这个参数,才能返回poll结果。

{% show_results poll %}
这时我们可以这样写show_results函数。

@register.inclusion_tag('results.html')
def show_results(poll):
    choices = poll.choice_set.all()
    return {'choices': choices}
当然poll这个变量出现在模板中并不是必需的,很多时候一个对象或一个对象清单已经存在全局变量context里,我们可以使用takes_context=True来直接使用context里的变量。假设poll已经存在context里,我们上面代码可以改为:

@register.inclusion_tag('results.html', takes_context=True)
def show_results(context):
    choices = context['poll'].choice_set.all()
    return {'choices': choices}
此时模板可以简化为如下代码,不再需要poll这个参数,即可显示poll的结果。

{% show_results %}

如何处理从模板中传递过来的多个参数

{% show_results poll %}中我们自定义的标签函数只接收了从模板传递过来的一个poll参数。一个模板也可以传递多个参数,如果参数名字或数量已知,Django的tag函数是可以按位置处理传递过来的参数的。

{% my_tag "abcd" book.title warning=message profile=user.profile %}

@register.inclusion_tag('my_template.html')
def my_tag(a, b, *args, **kwargs):
    warning = kwargs['warning']
    profile = kwargs['profile']
    ...
    return ...

但类似{% url "article_detail" article.id article.slug %}中的url标签显然要复杂得多。它可以接收未知数量的参数和未知名字的参数, 而且参数中有的带双引号,有的不带双引号。

对于这种情况Django的做法是先对标签所在的节点进行解析(parser), 把接收过来的字符串整体作为一个token,先对token进行split拆分,然后再分别处理。

我们现在来看看{% format_time %}这个标签是如何时间日期的格式化的。

<p>Published at at {% format_time article.pub_date "%Y-%m-%d %I:%M %p" %}.</p>

自定义的format_time标签函数完整代码如下。

from django import template

register = template.Library()

@register.tag(name="format_time")
def do_format_time(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        tag_name, date_to_be_formatted, format_string = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError(
            "%r tag requires exactly two arguments" % token.contents.split()[0]
        )
    if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
        raise template.TemplateSyntaxError(
            "%r tag's argument should be in quotes" % tag_name
        )
    return FormatTimeNode(date_to_be_formatted, format_string[1:-1])

class FormatTimeNode(template.Node):
    def __init__(self, date_to_be_formatted, format_string):
        self.date_to_be_formatted = template.Variable(date_to_be_formatted)
        self.format_string = format_string

def render(self, context):
        try:
            actual_date = self.date_to_be_formatted.resolve(context)
            return actual_date.strftime(self.format_string)
        except template.VariableDoesNotExist:
            return ''
我们现在来着重看下上面这段代码是如何工作的。

Django模板解析器扫描整个模板,碰到了format_time这个标签,把其当作一个新的节点Node,获取了format_time article.pub_date "%Y-%m-%d" 这一长串字符串作为token

get_format_time方法利用token自带的split_contents方法把上述字符串拆分成三部分: 标签名(tag_name), 需要格式化的日期(date)和指定格式(format), 并返回需要格式化的日期和格式交由FormatTimeNode处理。format_string[1:-1]的作用是去掉双引号。

FormatTimeNode这个节点类负责渲染节点,通过render方法渲染新的节点,还可以通过context给模板传递其它的变量(如下所示)。当render方法不返回一个具体的值的时候,需要返回一个空字符串。

def render(self, context):
    actual_date = self.date_to_be_formatted.resolve(context)
    context['formatted_time'] = actual_date.strftime(self.format_string)
    return ''

模板标签(tags)的介绍及如何自定义模板标签相关推荐

  1. template标签_Django实战: 利用自定义模板标签实现仿CSDN博客月度归档

    应网友慕之岩的请求,现提供下Django项目中如何使用自定义标签实现仿CSDN博客的月度归档(如下图所示).要求按月统计每个月发表的博文篇数, 跳过空白月份,最后结果按发布时间逆序排列.点击每个月份可 ...

  2. 目标检测标注工具(可自定义生成标签模板)

    点击查看项目源码 全新升级,整改为JAR包运行模式,既然是java项目自然支持各个系统 下载JAR包 JDK版本要求:JDK8-JDK10 上不去github的戳这 CSDN 0积分下载 运行方式 j ...

  3. Android Studio自定义模板之MVPActivity

    前言 Android开发中经常需要创建Activity.一般情况下,咱们都是"New"->Java Class/Activity.但是Android Studio自带的Act ...

  4. php如何配置gii,深入浅析yii2-gii自定义模板的方法

    Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序.接下来通过本文给大家介绍yii2-gii自定义模板的方法,需要的朋友参考下吧 前言: Yii 是什么 Yii 是一个 ...

  5. 使用tld文件自定义jsp标签库

    目录 一,标签库描述文件(tld文件) 二,标签处理类 三,在JSP页面中使用自定义的标签 四,举个例子 通过Java的TagSupport类或者BodyTagSupport类,和配套的tld文件,可 ...

  6. html网页制作教程按钮添加,网页制作html5自定义video标签的海报与播放按钮功能...

    一.问题 1.默认播放按键不好看 2.设置自定义封面图 以上这两点都想自定义 二.思路 1.使用div把video标签盖住 2.div中显示自定义的海报图片与按钮 三.步骤分解 1.海报图片作为div ...

  7. html video 修改封面,html5自定义video标签的海报与播放按钮功能

    一.问题 1.默认播放按键不好看 2.设置自定义封面图 以上这两点都想自定义 二.思路 1.使用div把video标签盖住 2.div中显示自定义的海报图片与按钮 三.步骤分解 1.海报图片作为div ...

  8. 实现自定义select标签

      我们经常会遇到这种场景:     假设项目中有一个分类对象,类似数据字典,一个code对应一个name.这个在页面作为一个过滤条件:选择分类.一般做法是在jsp页面直接写select标签,用opt ...

  9. MyBatisPlus3.x代码生成器自定义模板配置

    场景 MyBatisPlus3.x中使用代码生成器(全注释): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/89518466 M ...

最新文章

  1. QDoc关联事物Relating Things
  2. 洛谷P1937 [USACO10MAR]仓配置Barn Allocation
  3. 提高你的Java代码质量吧:使用valueof前必须进行校验
  4. usaco题思考记录
  5. Tensorflow图像处理以及数据读取
  6. 一步一步写算法(之查找)
  7. CSS魔法堂:小结一下Box Model与Positioning Scheme
  8. 函数式编程-将Monad(单子)融入Swift
  9. 网络疯传华为面试题:800公斤牛,过承重700公斤的桥,有答案了?
  10. ubuntu装指定分区_Ubuntu安装过程中如何手动指定分区
  11. 经典动态规划:打家劫舍系列问题
  12. 正好配资点评北交所成立,新基建起爆
  13. 熊猫在线压缩图_回归图与熊猫和脾气暴躁
  14. Windows 2016 服务器安全配置
  15. API接口怎么使用(教你使用api接口获取数据)
  16. 订单需求BOM合并 自动计算
  17. 软件:股票小助手/盯盘小助手!
  18. tensorflow出现报错: Could not locate zlibwapi.dll或者Could not load library cudnn_cnn_infer64_8.dll.
  19. 高压开关柜中变送器和传感器有什么不同怎么区分
  20. 田野调查手记·浮山篇(七)

热门文章

  1. 从互联网到“产业互联网”,房多多改造房产经纪N种可能
  2. 倾斜摄影/航测遥感的来看看,这里有最详细的ContextCapture极速计算存储集群方案
  3. 2022-2028全球城市轨道交通信号系统市场专题研究及投资评估报告
  4. html5 第一次作业
  5. HUB集线器,交换机,路由器的差异
  6. 集线器Hub、交换机、arp获取mac地址、路由器
  7. Java枚举Enum 与字符串的比较
  8. 吐血力作——追mm红宝书zz
  9. 两种高效的并发模式:半同步/半异步和领导者/追随者
  10. 【微信每日早安推送】