tags:

views:

242

answers:

4

I'm trying to write a django inclusion tag that takes an arbitrary number of arguments:

@register.inclusion_tag('so.html')
def table_field(*args):
fields = []
for arg in args:
 fields.append(arg)
return { 'fields': fields, }

However, when I call this from django's template engine:

{% table_field form.hr form.bp form.o2_sat %}

I get the error:

table_field takes 0 arguments

Is this yet another limitation of django's template engine?

+1  A: 

You'll have to write your own template tag i guess.

Dmitry Shevchenko
+1  A: 

Re: I'm trying to write a django inclusion tag that takes an arbitrary number of arguments

I think you should pass the arbitrary number of arguments in from the view as a single argument, as some sort of collection.

Based on the documentation, I think you should pass some collection object from the view to the template to the inclusion tag, and write the inclusion tag as:

@register.inclusion_tag('so.html')
def table_field(args):
    return { 'fields': [arg for arg in args], }

Then your template looks like this:

{% table_field whatever_was_passed_in_from_the_view %}

I don't think that templates are expected to make presentation decisions regarding the selection of data and that that decision is best handled in the view.

hughdbrown
My question asks about passing an arbitrary number of arguments to an inclusion tag, yet you post an inclusion tag taking only one argument. Where is the logic? I don't remember asking about design. I have already decided the template is the correct place for this presentation logic...
slypete
Sometimes, "Don't do that" is the right answer.
hughdbrown
I understand. However, not in this case.
slypete
A: 

This is another limitation of django's inclusion tags. Currently, in django's trunk version, this cannot be done.

slypete
+1  A: 

As of 1.2.1 you can pass arguments to inclusion tags.

Here is an example from my mods to django voting templatetags

@register.inclusion_tag("voting/vote_form.html", takes_context=True)
def vote_form(context, vote_object, vote_dict, score_dict):
    if isinstance(vote_dict, dict):

and the template looks like:

{% vote_form bookmark vote_dict score_dict %}

What I don't like about this is there is no way to name the arguments, only to put them in order, but it does work.

What is not so clear to me right now is why when you specify takes_context, that parent context is not passed along with the context that you return to be used in rendering the inclusion template.

Your trying to use *args won't work though because the # of args passed is checked against the function.

Mark0978
Hi Mark, this is not new to 1.2.1. I've been doing it for a while. My question was about arbitrary positional arguments. Your answer has one sentence on this topic, and it mimics my answer from last year.
slypete
I'm sorry, I don't see my one sentence anywhere on the page. The checking that is done at that level of the code makes it impossible to do what you are asking. There is an explicit check for the # of args passed to an inclusion tag, since that check can't divine what you do with a *args, it is impossible to do with inclusion tags. If that check were not there, or could be switched off, you would be good to go. I happened to be debugging in that area is the only reason that I knew it was impossible.
Mark0978