Django自定义模板

Django自定义模板

现在我们已经很熟悉Django的MTV模式了。

模板(template)负责如何去展示数据,而视图(view)负责筛选出正确的数据。因此通常来说逻辑都是放到视图中的,但模板也需要一些 和表示相关的逻辑 :比如循环展示(如 {% for ... %} )、或者以某种特定格式输出(如{{ ...|date:'Y-m-d' }})等,这些功能都是靠模板的 过滤器(filters) 和 标签(tags) 实现的。

Django的模板语言包含了很多内置的过滤器和标签,设计目的是满足应用需要占位逻辑需求。但有的时候这些通用的功能满足不了你的某些需求,这时候就需要自定义过滤器和标签来实现了。

前置条件

要在Django中使用模板过滤器或标签,就首先得 注册 它们。

注册方法如下:

  • 在APP中新建名为 templatetags 的目录(方便起见,教程选择了 article 这个APP)
  • 在此目录中新建名为 init.py 的空文件,使得此目录被视作一个Python的包
  • 在此目录中新建python文件(比如 my_filters_and_tags.py ),就可以在里面愉快的写代码啦

完成后的目录结构如下:

article/
  __init__.py
  views.py
  models.py
  # 新增目录
  templatetags/
    __init__.py # 空文件
    my_filters_and_tags.py # 即将写代码的地方

请注意:

  • 目录必须位于已注册的APP中,这是出于安全性的考虑
  • 新建目录后,必须手动重启服务器,里面的过滤器和标签才能生效

前置条件就完成了,接下来我们看看如何写一个模板过滤器。

 

注册模板

要成为一个可用的 filter ,文件中必须包含一个名为register的模块级变量,它是一个 template.Library实例,所有的 自定义模板 均在其中注册。所以在 my_filter_and_tags.py文件中输入以下内容:

article/templatetags/my_filter_and_tags.py:

from django import template
# 进行注册
register = template.Library()

 

模板过滤器@register.filter

filter 这个名字可能会让你误认为它只是用来筛选某些特定数据的,但实际上它远不止这点功能。它可以改变上下文的最终展示效果,也可以将上下文通过运算输出为特定的值。

接下来就可以像写普通的Python函数一样写过滤器了:

article/templatetags/my_filter_and_tags.py:

from django import template
register = template.Library()

@register.filter(name='transfer')
def lower(num1,num2):
  """将传进来的两个值进行相加"""
  return num1+num2

@register.filter()
def lower(value):
  """将字符串转换为小写字符"""
  return value.lower()

filter通过装饰器进行注册。若注册装饰器中携带了 name 参数,则其值为此filter的名称;若未携带,则函数名就是filter的名称。

filter必须是有一到两个参数的Python函数。

第一个参数是上下文本身,第二个参数则由filter提供。举个栗子,在过滤器 {{ var|foo:"bar" }} 中,变量 var 为第一个参数,变量 bar 则作为第二个参数。

调用这些filter的方法是在模板文件中用 {% load ... %} 将filter文件的名称加载进去,像这样:

# 任意模板文件中
{% load my_filters_and_tags %}    # 引入自定义模板文件
{{ 2|transfer:2 }} #输出:4 
{{ 'ABC'|lower }} # 输出:'abc'

 

模板标签@register.simple_tag

模板标签(tag)比过滤器更复杂,功能也更强大。

标签 tag 的表现形式为 {% tag_name ... %} ,比如我们非常熟悉的内置标签 {% url ... %} 、 {% static ... %} 等。如果内置标签满足不了你的需求,Django 提供了很多快捷方式,简化了编写绝大多数类型的标签过程。

创建简单标签

simple_tag 就是最重要的标签类型。标签的注册方法跟过滤器非常类似

与过滤器不同的是,标签可以接受任意数量的位置或关键字参数。例如:

@register.simple_tag
def my_tag(a, b, *args, **kwargs): #可以接收多个参数
  warning = kwargs['warning']
  profile = kwargs['profile']
  。。。。
  return 。。。。

模板中使用

在模板中调用时,任意数量的、以空格分隔的参数会被传递给模板标签。与 Python 中类似,关键字参数的赋值使用等号(" = "),且必须在位置参数后提供:

# 任意模板文件中
{% load my_filters_and_tags %}    # 引入自定义模板文件
{% my_tag 123 "abcd" book.title warning=message profile=user.profile %}

 

模板包含标签inclusion_tag

可以通过自定义包含标签来渲染html。

假设现在有一个需求,是要在文章详情页面中,显示所有相关评论的发布时间。因此在 my_filter_and_tags.py中写入:

@register.inclusion_tag('article/tag_list.html')
def show_comments_pub_time(article):
  """显示文章评论的发布时间"""
  comments = article.comments.all()
    # 把comments渲染金tag_list.html自定义包含模板中
  return {'comments': comments}

templates/article/tag_list.html:

<ul>
{% for comment in comments %}
  <li> {{ comment.created }} </li>
{% endfor %}
</ul>

然后在文章详情页面的模板中,随便找一个位置写入:

templates/article/detail.html

{% show_comments_pub_time article %} # 渲染

新详情页面,顺利的话就能看到所有评论的发表时间都展示出来了。

包含标签的另一个应用场景就是各种按钮了。有的按钮看上去长得都差不多,但是根据页面不同会有不同的功能,这时候也可以用包含标签来实现。

总之,包含标签可以将常用的模板代码打包成小组件,方便重复利用。

posted @ 2020-12-24 14:32  IT小码农!!!!  阅读(318)  评论(0)    收藏  举报