tags:

views:

66

answers:

2
class Article(models.Model):
    def user_may_see_full_version(self, user):
        # do something very sophisticated with the user
        return [True/False whatever]

now i want to create a template like this:

{% for article in articles %}
    {% if article.user_may_see_full_version request.user %}{{ article }}{% else %}{{article.title }}{% endif %}
{% endfor %}

but this doesn't work because I can't pass the argument to the method...

Is there any nice way to solve this problem?

+1  A: 

You are breaking with Django's philosophy of not having logic within the template. You could use another template language like Jinja2. But that way you will loose some of the cool stuff Django templates provide.

So your best choice is generate that variable in the view and pass it to the template. So if the view that renders your template passes a list of articles, in which everyone has a variable called user_may_see_full_version then you simply can do:

{% if article.user_may_see_full_version %} whatever

Focus on processing the logic in your view. Templates are only a way to render the information passed.

maraujop
but this requires iterating the queryset twice - not very nice ;-)
Alex
Depends on how you implement, you wouldn't have to. On the other hand using the filter tag will need to call a function, that calls another each time, creating memory contexts and maybe hitting DB every time. Django way of doing things is not passing parameters within the template.
maraujop
+2  A: 

There's no way to pass an argument to a method directly from a template. A template filter is the best way to go:

{% if article|user_may_see_full_version:user %}{{ article }}{% else %}{{article.title }}{% endif %}

The filter is implemented like this:

@register.filter()
def user_may_see_full_version(article, user):
    return article.user_may_see_full_version(user)
Ned Batchelder