如何在Django模板的自定义模板过滤器中添加多个参数?


89

这是我的自定义过滤器:

from django import template

register = template.Library()

@register.filter
def replace(value, cherche, remplacement):
    return value.replace(cherche, remplacement)

这是我尝试在模板文件中使用它导致错误的方式:

{{ attr.name|replace:"_"," " }}
{{ attr.name|replace:"_" " " }}
{{ attr.name|replace:"_":" " }}
{{ attr.name|replace:"cherche='_', remplacement=' '" }}

我查看了django的文档书籍,但只发现了使用单个参数的示例……甚至可能吗?

Answers:


108

这是可能的并且相当简单。

Django只允许在过滤器中使用一个参数,但是没有理由不能使用逗号将所有参数都放在单个字符串中。

因此,例如,如果您想要一个过滤器来检查变量X是否在列表[1,2,3,4]中,则需要一个如下所示的模板过滤器:

{% if X|is_in:"1,2,3,4" %}

现在,我们可以像这样创建您的templatetag:

from django.template import Library

register = Library()

def is_in(var, args):
    if args is None:
        return False
    arg_list = [arg.strip() for arg in args.split(',')]
    return var in arg_list

register.filter(is_in)

创建arg_list的行是一个生成器表达式,该表达式将所有逗号上的args字符串分割开并调用.strip()以删除任何前导和尾随空格。

例如,如果第三个参数是int,则只需执行以下操作:

arg_list[2] = int(arg_list[2])

或者如果它们都是整数,那就做:

arg_list = [int(arg) for arg in args.split(',')]

编辑:现在通过使用键,值对作为参数来专门回答您的问题,您可以使用Django用于解析URL之外的查询字符串的同一类,这也具有根据您的settings.py正确处理字符编码的好处。 。

因此,与查询字符串一样,每个参数都用'&'分隔:

{{ attr.name|replace:"cherche=_&remplacement= " }}

然后,您的替换函数将如下所示:

from django import template
from django.http import QueryDict

register = template.Library()

@register.filter
def replace(value, args):
    qs = QueryDict(args)
    if qs.has_key('cherche') and qs.has_key('remplacement'):
        return value.replace(qs['cherche'], qs['remplacement'])
    else:
        return value

您可能会加快速度,但有可能会进行一些错误的替换:

qs = QueryDict(args)
return value.replace(qs.get('cherche',''), qs.get('remplacement',''))

1
如果这些值在变量中,该如何实现...?
Anto

2
这似乎很有帮助,但是我无法使其与传递的变量一起使用。为此,我使用了-tagsimple_tag-允许多个变量,甚至可以传递命名变量。
Furbeenator 2015年

18

根据文档的这一部分是不可能的:

自定义过滤器只是采用一两个参数的Python函数:

  • 变量(输入)的值-不一定是字符串。
  • 参数的值-它可以具有默认值,也可以完全省略。

如果您使用的是硬编码字符串,Van Gale的方法将适用。Django票证[ code.djangoproject.com/ticket/1199]在自定义过滤器中支持多个参数,并且已接受补丁。
杰夫·鲍尔

17

这样很容易。

@register.filter(name='one_more')
def one_more(_1, _2):
    return _1, _2

def your_filter(_1_2, _3)
    _1, _2 = _1_2
    print "now you have three arguments, enjoy"

{{ _1|one_more:_2|your_filter:_3 }}

真的非常感谢您的解决方案。我已经对其进行了一点升级,因此您可以链接不同长度的参数。gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
菲利普Dobrovolný

1
这应该是正确的答案!这是一个漂亮的python解决方案(可能不是最好的django解决方案,请参阅@dragonroot答案)
Antoine Draune


5

它比您想象的

简单。您可以为此使用simple_tag

@register.simple_tag
def multiple_args_tag(a, b, c, d):
   #do your stuff
   return 

在模板中

{% multiple_args_tag 'arg1' 'arg2' 'arg3' 'arg4' %}

注意:不要忘记重新运行服务器。


4

在Django的Trac 2013中,此功能已标记为WONTFIX:http ://code.djangoproject.com/ticket/1199


该票证于去年(2013年)作为WONTFIX截止,他们的开发人员建议如果需要多个参数,请使用自定义标签。
Paul Lo

3

<我的网站> /globaltags/replace.py

from django.template import Library

import re

register = Library()

def search(value, search):
    return re.sub(search, '#f4x@SgXXmS', value)

def replace(value, replace):
    return re.sub('#f4x@SgXXmS', replace, value)

register.filter(search)
register.filter(replace)

在模板中:

{{ "saniel"|search:"s"|replace:"d" }}

如果您解释#f4x@SgXXmS一下会很好吗?
丹·阿布拉莫夫

1
只是用作占位符的随机字符串。我选择此字符串是因为我相信它不会成为输入字符串的一部分。例如,如果我用“ {}”代替“#f4x @ SgXXmS” {{“用{}代替off []” | search:“ off” | replace:“ of”}}将返回:“ use of而不是[]”,而不是预期的结果:“使用{}而不是[]”
theosp

5
哦,那很有道理。声明为SUBSTRING_THAT_NEVER_OCCURS思想可能会很好。
丹·阿布拉莫夫

-1

您可以简单地做到这一点:

{% assign find_total_issued = dailysalesreport | find: "TotalIssued":"13" %}

public static List<object> Find(object collection, string column, string value)

它会到达目的地,因为函数的抽象是 sjare


-2

这是一个坏主意,但有效:

{{ xml|input_by_xpath:"{'type':'radio','xpath':'//result/value'}" }}

@register.filter
def input_by_xpath(device, args): 
    args = eval(args)
    ...
    result = "<input type=\"%s\" value=\"%s\" name=\"%s\"/>"%(args['type'],value,args['xpath'])
    return mark_safe(result)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.