Ahop Ahop - 1 year ago 87
Python Question

Queryset in view or in template

I am trying to speed up my code. In development, everything ran very smooth, but once I put it in production, and started adding more depth of data into the database, I realize that it is running very slow.

I noticed on django-toolbar that it is running THOUSANDS of queries, where it should only be maybe 10-20. I am wondering if it may be because of the way I have a lot of content being delivered.

For example, I have code that looks like this:

{% if user.profile.is_admin %}
{% endif %}


{% for stuff in user.profile.get_somestuff %}
{{ stuff.info }}
{{ stuff.other_info }}
{% endfor %}

Does each one of these execute a new query?

Should I run the query for
in the view, pass it through context? I am asking from a performance perspective.

Answer Source

If profile.get_somestuff is an expensive operation and you call it multiple times in the template, and yes, you should call that in the view once and pass the result to the template via context.

def view(request):
    stuff = request.user.profile.get_somestuff()
    return render(request, 'page.html', {'stuff': stuff})

Alternatively, you can use {% with %} tag to create a scope containing the value in its own context:

{% with stuff=user.profile.get_somestuff %}
   {{ stuff.info }}
   {{ stuff.other_info }}
   ... do some other things with stuff
{% endwith %}

Personally, I would go with the first option because, with the help of django.db.connection.queries, it is relatively easier to monitor db queries you make in the view. Make sure you avoid sending template querysets, lazy expressions etc. as much as possible.

BTW, please note that DEBUG must be set to True for connection.queries to work.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download