How to get related set models without hit database in Django - django

Here you'll always get two separate db calls, and adding select_related() anywhere won't help at all. One extra db call isn't that significant.
<ul>
{% for obj in myobjects %}
<li>{{ myobj.name }}</li>
<ul>
{% for relobj in myobj.backwardsrelationship_set.all %} {# hit database at every row #}
<li>{{ relobj.name }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
Any idea here?

I found the solution.
prefetch_related can solve this
Publisher.objects.filter(city='NY').prefetch_related('book_set')

Related

Django Stopping loop after x times within a template

I have queryset that returns many records but in the template I use it twice to return value.
For example:
On one instance I need to return the latest 5 posts and then show all the posts on that same page. So for that reason I can't use LIMIT in my queryset.
{% for post in blog_posts %}
<li>{{ post.title }}</li>
{% endfor %}
From that example how can I stop to loop after 5 times.
Use the slice filter:
{% for post in blog_posts|slice:":5" %}
<li>{{ post.title }}</li>
{% endfor %}

work around setting variables in django templates

I have this code that I used from twig to display sections according to the same date.
I'm trying to use the same code in Django but I can't set variables in its template system. What is the sane way to do this? The correct way? How do people tackle such a problem?
{% set date = "prout" %}
{% for article in articles %}
{% if article.date != date %}
{% if date != "prout" %}
</ul>
</section>
{% endif %}
{% set date = article.date %}
<section class="row">
<h2>{{ article.date }}</h2>
<ul>
<li>+ {{ article.titre }}</li>
{% else %}
<li>+ {{ article.titre }}</li>
{% endif %}
{% endfor %}
</ul>
</section>
The closer concept to 'set' variables is with tag. Quoting Built-in template tags and filters django docs:
with
Caches a complex variable under a simpler name. This is useful
when accessing an “expensive” method (e.g., one that hits the
database) multiple times.
For example:
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}

Problem with django templates

Is there any solution to do something like this:
{% for c in categories %}
{% for s in c.subcategory_set %}
<li>{{ s.name }}</li>
{% endfor %}
{% endfor %}
???
Reverse relations on a FK have a manager. As such, you need to use the all() method if you want to access all related objects.
{% for s in c.subcategory_set.all %}

Django, loop over all form errors

At my template, I want to iterate through all form errors, including the ones that are NOT belonging to a specific field. ( which means for form.errors, it should also display for __all__ errors aswell)
I have tried several versions, Ie:
<div id="msg">
{% if form.errors %}
<div class="error">
<p><span>ERROR</span></p>
<ul>
{% for key,value in form.errors %}
{% for error in value %}
<li>{{ error }}</li>
{% endfor %}
{% endfor %}
</ul>
</div>
{% endif %}
</div>
Still no achievement, I will be greatful for any suggestion.
Form errors in Django are implemented as an ErrorDict instance (which is just a subclass of dict with extras). Try a slight adjustment to your template for loop syntax:
{% for key, value in form.errors.items %}
Are you, by any chance, looking for form.non_field_errors? That is how you would get access to the errors that aren't associated with a particular field.
{% if form.non_field_errors %}
<ul>
{{ form.non_field_errors.as_ul }}
</ul>
{% endif %}
Check the forms.py test suite as well for another example. Search for form.non_field_errors

Separating ManyToManyFields in a template

Following my question at link text I'd like to separate the features in the template using categories such as Interior, Exterior, Mechanical etc.
I'm trying out the code below, but apparently it's not giving me what I want.
{% for feature in vehicle.features.all %}
{% ifequal vehicle.features.type.type "Interior" %}
<li>{{ feature }}</li>
{% endifequal %}
{% endfor %}
How do I go about this?
You want:
{% for feature in vehicle.features.all %}
{% ifequal feature.type.type "Interior" %}
<li>{{ feature }}</li>
{% endifequal %}
{% endfor %}
vehicle.features is a ManyToManyRelatedManager which can be used to access Feature objects, but does not actually carry Feature's relationships.
EDIT: In response to the comment below about doing this on the view, you could easily do:
interior_features = vehicle.features.filter(type__type='Interior')
and pass interior_features to the context of the template directly. This would actually make more sense as a method on the model:
def get_interior_features(self):
return self.features.filter(type__type='Interior')
The result of this could be filtered further, of course, as needed.
options = vehicle.get_interior_features().filter(is_standard=False)
or something.
Use Django's regroup tag: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#regroup
Would probably end up looking something like:
{% regroup vehicle.features.all by type as vehicle_features %}
{% for feature in vehicle_features %}
{% ifequal feature "Interior" %}
<li>{{feature}}</li>
{% endifequal %}
{% endfor %}