4 ms·
It's easier to notice expensive SQL queries in the view vs in the template. Anyone who claims that it's fine to run queries in templates has smoked something r
by jmconfuzeus 5y ago
It's easier to notice expensive SQL queries in the view vs in the template.
Anyone who claims that it's fine to run queries in templates has smoked something really good. Personally, I'll continue to aggregate all my data using JOINs before presenting them.
- Nextgrid 5y agoWhen it comes to "queries" keep in mind that I'm not saying you should call "Model.objects.filter(...)" in the template (in fact that would be very difficult to do unless you pass a "Model" reference to the template). You still do that in code. However due to how Django handles queries by default, calling the ORM won't actually execute the query until the queryset is evaluated in most cases (unless requesting a single object or doing an aggregation), so your queries are still technically "ran" from the template - even if you are doing prefetch_related. I personally don't have a problem with that; explicitly casting the queryset to a list before rendering a template seems like unnecessary boilerplate and still doesn't actually isolate you from the "N+1" queries problem if your template then accesses an object's relation that hasn't been prefetched.
- jmconfuzeus 5y agoThat's the point. Instead of worrying about whether you're accessing a related attribute, join everything and evaluate the QuerySet before passing it to context. You'll never have to worry about whether {{ pizza.topping.name }} is hitting the database ever again, especially, if you install django-zen-queries because it will raise an exception if you try to.
- Nextgrid 5y agoGot it - so the magic here isn't merely to evaluate querysets ahead of time (which can still return objects with unfetched relations that'll cause a query at runtime if accessed) but to also rely on the third-party package to explicitly disallow that.
- jmconfuzeus 5y agoIt's highly unlikely that will you execute unnecessary queries from view code because usually you'll have a context like {"pizzas": page_obj.object_list}. You'll almost never execute something like: for pizza in pizzas: print(pizza.topping.name) But you'll certainly do the following in templates: {% for pizza in pizzas %} <p>{{ pizza.topping.name }}</p> {% endfor %} I also don't understand why you want to avoid 3rd party packages, especially if it helps you write better code.
- Nextgrid 5y agoMy argument was that the third-party package is what's key here. Merely converting your querysets to a list in code before handing it off to the template won't fully protect you against extra queries. I'm not necessarily trying to avoid third-party packages, in fact I've installed the package you suggested in one of my projects and will be trying it out.