简体   繁体   中英

Django — how to use templatetags filter with multiple arguments

I have a few values that I would like to pass into a filter and get a URL out of it.

In my template I have:

{% 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 %}

In my templatetags I have:

@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  

The output URL should look like:

http://foo.org/john-smith-ARGScustidZZ11QQsortidZZ2

Where ARGS is the start of the arguments, ZZ is '=' and QQ is an '&' equivalent.

First of all: This would work, but I get the custid=name.id coming in the add_args(), where I want to have custid=11 to come in. How pass in the id as an id and not text.

Also, is there a way to just send in an array of key=>value like in PHP. In PHP I would build an array, let say:

arglist = array('custid' => $nameid, 'sortid' => $sortid ); 

Then I would pass the arglist as an argument to add_args() and in add_args() I would do

foreach( arglist as $key => $value)
  $argstr .= $key . 'ZZ' . $value . 'QQ'.

Does anyone have a better way of making this work?

Note: if I have to pass all arguments as a string and split them up in the filter I don't mind. I just don't know how to pass the name.id as its value ...

This "smart" stuff logic should not be in the template. Build your end-of-urls in your view and then pass them to template:

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))

In template.html:

 ....

    <a href='{{url_stuff}}'>{{name}}</a>

 ....

If you need a url for a whole bunch of objects consider using get_absolute_url on the model.

You can't pass name.id to your filter. Filter arguments can be asingle value or a single literal. Python/Django doesn't attempt any "smart" variable replacement like PHP.

I suggest you to create a tag for this task:

<a href='{% add_args "custid" name.id "sortid" "2" %}{{name|slugify}}{% end_add_args %}'>{{name}}</a>

This way you can know which argument is a literal value and which should be taken fron context etc... Docs are quite clear about this, take a look at the example .

Also if this name is any way related to a model, say we want to get to the permalink, adding a method that returns the URL with the proper arguments might be the tidiest solution.

Overall, I would refrain putting too much logic into templates. Django is not PHP.

You're calling argz.join a couple times and never assigning the results to anything: maybe you're operating under the misconception that the join method of a string has some mysterious side effect, but it doesn't -- it just returns a new string, and if you don't do anything with that new string, poof , it's gone. Is that at least part of your problem...?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM