I'm working on a project in Django.
Earlier today, I discovered the new (Django >= 1.4) assignment_tag
. I immediately decided that it was just what I needed EVERYWHERE and threw some logic into one that executed a very simple query against the database and returned the resulting queryset. The function I wrapped takes an argument that allows the invoking context to specify how many results to grab, directly in the template when I am using the template tag.
It is quite convenient - I don't have to update my view when I decide this list should have 5 items, not 3 - but it seems like one of those gray areas where we aren't supposed to tread (i.e. pushing application logic into templates) when writing good, maintainable Django code.
Now, a couple of hours separated from writing the code, I'm wondering if I should scrap the assignment_tag entirely.
Code:
models.py:
class SomeObject(models.Model):
is_active = models.BooleanField(default=False)
(...)
templatetags/myapp_tags.py:
from django import template
from myapp.models import SomeObject
register = template.Library()
@register.assignment_tag
def get_someobjects_list(max_results=0):
queryset = SomeObject.objects.filter(is_active=True)
if max_results == 0:
return queryset
elif max_results > 0:
return queryset[:min(max_results, queryset.count())]
else:
return None
templates/myapp/chunks/someobject_list.html:
{% load myapp_tags %}
{% get_someobjects_list as someobjects_list %}
# or {% get_some_objects_list 5 as someobjects_list %} ... flexible!
{% if someobjects_list %}
<ul>
{% for someobject in someobjects_list %}
<li>
<a href="{{ someobject.get_absolute_url }}">
{{ someobject.name }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<span>No someobjects exist</span>
{% endif %}
I was really excited to discover these existed - it's convenient for me in this particular case. Now that my excitement over finding a new feature has passed, it seems pretty clear that I'm misusing it. The example given in the Django docs seems like a better application of this - grabbing the string representation of current datetime, something that doesn't require a DB query. My worry is that I'm setting myself up for heartache if I start using this pattern regularly. Following the slippery slope all the way down: I'll end up not even bothering to pass a context to my templates and ALL my DB queries will be hidden away in template tags where nobody would think to look for them.
It seems the code would be cleaner if I just threw out this whole "great idea" I had when I discovered assignment_tags and created a custom model manager instead.
Are there other clean ways of accomplishing this that I am missing? Are manager methods the consensus best way among Django developers?