Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you make a custom template tag that returns a queryset? If yes, how? - Django

Let's make this very easy for my fellow SOians(?).

This is how normally the custom template tags work -

Template ->

{% block content %}

     blah blah blah

     {% custom_tag_load %}

{% endblock %}

The custom_tag_load is called and it returns a string. What I want to return is a queryset which I could possibly use like this ->

{% block content %}

     blah blah blah

     {% for x in custom_tag_load %}

          {{ x.datetime }}

     {% endfor %}

{% endblock %}

Note -> What I'm basically trying to do is to avoid passing the queryset through the view, and I'm not sure if I should be comfortable storing querysets in my global context.

like image 418
Sussagittikasusa Avatar asked Oct 31 '11 12:10

Sussagittikasusa


People also ask

What are Django template tags?

Django Code The template tags are a way of telling Django that here comes something else than plain HTML. The template tags allows us to to do some programming on the server before sending HTML to the client.

What does the built in Django template tag Lorem do?

lorem tag displays random “lorem ipsum” Latin text. This is useful for providing sample data in templates.


2 Answers

You can return anything you like from a tag, including a queryset. However, you can't use a tag inside the for tag - you can only use a variable there (or a variable passed through a filter). What you could do is get your tag to put the queryset into a variable in the context, and use that variable in the for loop. See the docs on how to set a variable from a tag - although note that the development version has an easier method for doing this.

However, you shouldn't be concerned about putting a queryset into a context processor, either. Don't forget that querysets are lazy, so no database hit will be made unless the queryset is evaluated or iterated in the template.

like image 91
Daniel Roseman Avatar answered Sep 23 '22 23:09

Daniel Roseman


A template tag can do whatever you want. From your pseudo code, you could accomplish what you need with an inclusion tag:

#my_tags.py
from django import template
from my_app.models import MyModel

register = template.Library()

@register.inclusion_tag('my_template.html')
def my_custom_tag():
    things = MyModel.objects.all()
    return {'things' : things}


#my_template.html
{% if things %}
    <ul>
    {% for thing in things %}
        <li>{{ thing }}</li>    
    {% empty %}
        <li>Sorry, no things yet.</li>
    {% endfor %}
    </ul>
{% endif %}


#the_view.html
{% load my_tags %}

{% my_custom_tag %}

Alternatively, you could write a custom tag that adds a queryset to the context. Hope that helps you out.

like image 43
Brandon Avatar answered Sep 22 '22 23:09

Brandon