Reputation: 2902
I have a model "Invoice" with a method
def item_objects(self):
return self.invoiceitem_set.filter(kind='item')
I then have a template with that model in its context "invoice"
in that template I use a with tag to try and cache that item_objects
{% with item_object=invoice.item_objects%}
{{item_object}}
{{item_object}}
{% endwith %}
Regardless I still hit the database for each time I call {{item_object}}
What am I doing wrong?
Upvotes: 2
Views: 643
Reputation: 239390
Your simplified code is likely hiding the problem, as the behavior you describe should not be happening. The entire purpose of the with
template tag is to cache the results of an expensive method for use later.
However, your method, item_objects
, returns a QuerySet
, and when you assign it to item_object
, it is still a QuerySet
. QuerySet
s are lazy-loaded, so up to this point, no database hits have been made. As a result, depending on what you actually do with item_object
, you can negatively impact the query performance.
For example, the following will result in two queries to the DB, even though you're dealing with a cached QuerySet
:
{{ item_object.count }}
{{ item_object|first }}
You need to be careful with what operations you perform on querysets and in which order. For example, if you know that you are going to loop through the queryset at some point, but you need a count first, it's actually more efficient to use {{ item_object|length }}
instead of {{ item_object.count }}
Upvotes: 1