将列表作为参数传递给Django标签

时间:2018-08-28 13:03:01

标签: django django-templates django-template-filters

我在Django中有一个自定义包含标签,我需要在此处传递一个列表作为参数。遵循以下原则:

 {% my_tag paramA='asdf' paramB='fdsa' listparams=['X', 'Y'] %}

这当然是行不通的,因为Django不知道如何处理以这种方式传递的列表。

我还可以捕获诸如list_之类的通用内容,然后将它们组合到服务器端的列表中:

 {% my_tag paramA='asdf' paramB='fdsa' list_1='X' list_2='Y' list_3='Z' %}

但是我想知道是否有更好的方法来解决这个问题。

1 个答案:

答案 0 :(得分:2)

这里基本上有两种方法:

  1. 尝试以一种或另一种方式构造列表,并将其传递给my_tag;或
  2. 更改my_tag,以便传递列表更加方便。

构造列表

Django模板提供了构造列表的方法,尽管其中大多数都是相当有限的。

使用make_list模板过滤器

例如,

Django引入了一个make_list template filter [Django-doc],它接受​​一个可迭代的并将其转换为项目列表。例如,我们可以将模板过滤器用于:

{% my_tag paramA='asdf' paramB='fdsa' listparams='XY'|make_list %}

但这有两个潜在的问题:(1)对于在字符上迭代的字符串,因此元素都将是1个字符的字符串,(2)您不能构造包含整数的列表,等等。除非您已经有一个类似集合的对象,但这基本上会使make_list失去作用。

使用.split()

我们可以通过执行对.split()的调用来解决仅包含1个字符的字符串的问题,这仅适用于字符串(除非变量的类型也支持.split()函数) ,因此我们可以通过以下方式解决多字符部分的问题:

{% my_tag paramA='asdf' paramB='fdsa' listparams='XY Z'.split %}

实施自定义可变参数标记来构建列表

我们还可以定义一个可变标记,该标记首先构造一个列表。为此,我们实现了一个自定义标签:

#  app/templatetags/create_list.py

from django import template

register = template.Library()

@register.simple_tag
def create_list(*args):
    return args

然后我们可以使用两个步骤来传递列表:

{% load create_list %}
{% create_list 'X' 'Y' as mylist %}
{% my_tag paramA='asdf' paramB='fdsa' listparams=mylist %}

更改my_tag

也许一种干净的方法是在这里使用 positional 参数来获取列表。 Python中的函数具有两种类型的参数: positional 参数(在没有参数名称的情况下通过传递的参数)和 named 参数(带有key=...的文件。

因此,我们可以在此处将位置标记用于列表,并使用以下代码调用标记:

{% my_tag 'X' 'Y' paramA='asdf' paramB='fdsa' %}

如果我们不提及任何位置参数,则该列表被认为是空的。我们可以传递任意数量的参数。

例如,我们可以将标签实施为:

#  app/templatetags/my_tag.py

from django import template

register = template.Library()

@register.simple_tag
def my_tag(*listparams, paramA=None, paramB=None):
    # ... processing
    return None

这种方法的潜在问题是,在无法定义两个单独的*arg的意义上,我们只能执行一次“技巧”。我们当然可以将*args分成两个列表,但这可能很棘手。