Django - 如何使用 templatetags 过滤器传递多个参数
我有一些值想要传入一个过滤器,然后得到一个网址。
在我的模板里,我有:
{% if names %}
{% for name in names %}
<a href='{{name|slugify|add_args:"custid=name.id, sortid=2"}}'>{{name}}</a>
{%if not forloop.last %} | {% endif %}
{% endfor %}
{% endif %}
在我的模板标签里,我有:
@register.filter
def add_args(value, args):
argz = value.strip() + '-' + 'ARGS'
arglist = args.split(',')
for arg in arglist:
keyval = arg.split('=')
argz.join(keyval[0] + 'ZZ' + keyval[1])
argz.join('QQ')
return argz
输出的网址应该看起来像这样:
http://foo.org/john-smith-ARGScustidZZ11QQsortidZZ2
其中 ARGS 是参数的开始部分,ZZ 是 '=',QQ 是 '&' 的等价物。
首先,这样是可以工作的,但我在 add_args() 里得到的是 custid=name.id,我希望能传入 custid=11。也就是说,我想把 id 作为数字传入,而不是文本。
另外,有没有办法像在 PHP 中那样直接传入一个键值对的数组?在 PHP 中,我会构建一个数组,比如:
arglist = array('custid' => $nameid, 'sortid' => $sortid );
然后我会把这个 arglist 作为参数传给 add_args()
,在 add_args()
里我会这样做:
foreach( arglist as $key => $value)
$argstr .= $key . 'ZZ' . $value . 'QQ'.
有没有人有更好的方法来实现这个?
注意:如果我必须把所有参数作为字符串传入,然后在过滤器里拆分开来,我也没问题。我只是不知道怎么把 name.id 作为它的值传入……
3 个回答
你在调用 argz.join
这个方法好几次,但从来没有把结果保存到任何地方。也许你误以为字符串的 join
方法会有什么神秘的副作用,其实并没有——它只是返回一个新的字符串,如果你不对这个新字符串做什么,啪,它就消失了。这个问题是不是你遇到的部分原因呢……?
你不能把 name.id
直接传给你的过滤器。过滤器的参数只能是一个单独的值或者一个简单的文字。Python/Django 不像 PHP 那样会进行“智能”的变量替换。
我建议你为这个任务创建一个标签:
<a href='{% add_args "custid" name.id "sortid" "2" %}{{name|slugify}}{% end_add_args %}'>{{name}}</a>
这样你就能清楚地知道哪个参数是固定的值,哪个是需要从上下文中获取的等等……文档对此解释得很清楚,可以看看这个 例子。
另外,如果这个 name
和某个模型有关系,比如我们想获取永久链接,添加一个返回带有正确参数的 URL 的方法可能是最整洁的解决方案。
总的来说,我建议不要在模板中放太多逻辑。Django 不是 PHP。
这些“聪明”的逻辑不应该放在模板里。你应该在视图里构建好所有的链接,然后再把它们传给模板:
def the_view(request):
url_stuff = "custid=%s, sortid, ...." % (name.id, 2 ...)
return render_to_response('template.html',
{'url_stuff':url_stuff,},
context_instance = RequestContext(request))
在template.html里:
....
<a href='{{url_stuff}}'>{{name}}</a>
....
如果你需要为一大堆对象生成链接,可以考虑在模型上使用 get_absolute_url 方法。