tags:

views:

269

answers:

2

hi there,

i m trying to make the result of a template tag dependent from another template tag. the use case is the following. i have a headers list which contains all the columns i want to show in a table + the column of the model they are showing +whether they are visible or not.

LIST_HEADERS = (
    ('Title', 'title', True),
    ('First Name', 'first_name', True),
    ('Last Name', 'last_name', True),
    ('Modified At', 'modified', False),
)

now i have a templatetag which prints out all the headers. consequently i wanted to create a template tag which prints out the body of the table. therefore i want to take the headers list and check which header is visible and want to accordingly show or hide my value.

therefore i created the templatetag template below:

<tr class="{% cycle odd,even %}">
  {% for header in headers %}
  {% if header.visible %}
    <td><a href="{{ model_instance.get_absolute_url|escape }}">{{ model_instance.title }}</a></td>
  {% else %}
    <td style="visibility:hidden;"><a href="{{ model_instance.get_absolute_url|escape }}">{{ model_instance.title }}</a></td>
  {% endif %}
  {% endfor %}
</tr>

you see the value {{ model_instance.title }} there. this value i want to change to model_instance.title, model_instance.first_name, model_instance.last_name, ... at runtime.

thus i m searching a way how i can combine {{ model_instance }} with header.model_column .

model_column equals to the second entry in the LIST_HEADERS. Thus model_column would be title, first_name,..

thus the solution would be something like [pseudocode] {{ model_instance.header.model_column }} [pseudocode]

..thus i search a way how i can combine a django template method call with a django template tag attribute..huh.. sounds crazy :D

i hope i explained it good enough! probably there is a much easier solution to my problem. but this seems to me pretty generic and easy and would work.

+1  A: 

I would do this as a filter, as they provide an easy way to render a result dependent on the value of a variable.

@register.filter
def field_from_name(instance, field_name):
    return getattr(instance, field_name, None)

and then in the template:

{{ model_instance|field_from_name:header.model_column }}
Daniel Roseman
thanks. i think i will give this a try! looks good and easy.
Tom Tom
+2  A: 

Simplify this.

First, read about the things the Django template language actually can do. It's not much. It can deference variables, lists and dictionaries.

It's simpler if you do all the "work" in your view function.

show = [ ]
for  title, field_name, visible in LIST_HEADERS:
     if visible: style= "visibility:hidden"
     else: style= ""
     show.append( (style, title, getattr(object,field_name) )
render_to_response( "template", { 'show_list': show, ... }, ... )

In your template

{% for style, name, value in show_list %}
<tr class="{% cycle odd,even %}">
    <td class="{{style}}"><a href="...">{{value}}</a></td>
{% endfor %}

Indeed, I'd suggest dropping LIST_HEADERS from your view function.

show = [ 
    ("", 'Title', object.title),
    ("",'First Name', object.first_name),
    ("",'Last Name', object.last_name),
    ("visibility:hidden",'Modified At', object.modified),
]
render_to_response( "template", { 'show_list': show, ... }, ... )

I find the above much easier to work with because it's explicit and it's in the view function.

S.Lott
+1 for doing more in the view, less in the template. It will make everything more readable.
celopes
wow.. impressing. so fast.. and i learned a lot from your post.
Tom Tom