Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialJay Norris
14,824 PointsDocumentation for Django Braces
I'm having an issue with Django Braces, specifically the PrefetchRelatedMixin. If found the documentation below, but I'm wondering if there is deeper information about the Mixins?
http://django-braces.readthedocs.io/en/latest/other.html#prefetchrelatedmixin
3 Answers
Kenneth Love
Treehouse Guest TeacherAh, yeah, this is a slight misunderstanding of how pretch_related
works. Let's see if I can explain it.
When you have a Household
record, it has 1+ Person
records attached to it through a ForeignKey
on the Person
record, right? So when you do Household.person_set.all()
, Django has to do another query to get all of those related Person
records. prefetch_related
can't eliminate this query. Nothing really can unless you wrote custom SQL for it and no one wants to do that.
What prefetch_related
does for you, though, is it consolidates the queries into the view instead of doing one in the view and then one in the template. What you have now in your CBV should be executing two queries but it doesn't add anything to the context (the variables available to the template). You'd still use the Person
records through dot notation from the Household
object.
{% for person in household.person_set.all %}
{{ person.gender }}
{% endfor %}
Kenneth Love
Treehouse Guest TeacherWhat's your issue and what are you wanting to know?
Jay Norris
14,824 PointsI've pip installed Django Braces and imported to views (see views.py below). I'm trying to convert a function based view which is based on your course_detail view from "Django ORM". The view works great, but I wanted to play with these mixins. My Household -> Person relationship is like your Course -> Quiz relationship from the ORM course. The template 'household_detail.html' shows up just fine with the Household data, but not the person_set. Django Debug Toolbar shows a query for the person_set:
SELECT ••• FROM "quotes_person" WHERE "quotes_person"."household_id" IN (57) ORDER BY "quotes_person"."birthdate" ASC
but DjDT doesn't show a person_set coming through to the template in the context like it does with the function.
I'm using Django 1.9.7.
models.py
class Household(models.Model):
last_name = models.CharField(max_length=50)
email = models.EmailField(max_length=120)
phone = models.CharField(max_length=30, blank=True)
class Person(models.Model):
gender = models.CharField(max_length=8, choices=GENDERS, default='')
birthdate = models.DateField(max_length=25)
household = models.ForeignKey(Household)
#views.py (showing only relevant imports)
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.views.generic import ListView, DetailView
from braces.views import PrefetchRelatedMixin
#*********
Old function based view - works correctly
#*********
@login_required
def household_detail(request, pk):
household = get_object_or_404(models.Household, pk=pk)
persons = sorted(chain(household.person_set.all()),
key=lambda person: person.birthdate,
reverse = False)
return render(request, 'quotes/household_detail.html', {
'household': household,
'persons': persons
})
#************
New class based view
#************
class HouseholdDetailView(LoginRequiredMixin, PrefetchRelatedMixin, DetailView):
model = models.Household
prefetch_related = [u"person_set"]
#url
url(r'household/(?P<pk>\d+)/$', views.HouseholdDetailView.as_view(), name='household'),
<!-- household_detail.html -->
<h2>{{ household.last_name }}</h2>
<dd>Phone: {{ household.phone }}</dd>
<dd>Email: {{ household.email }}</dd>
{% for person in person_set %}
<dd>{{ person.gender }}</dd>
<dd>DOB: {{ person.birthdate|date:"m/d/Y" }}</dd>
{% endfor %}
Sorry for the long post. I wanted to make sure I included everything. I love all of your courses and challenges. I've probably taken all of them! Thanks for putting together Django Braces. I can't wait to fully grok the Django classes!
Jay Norris
14,824 PointsJay Norris
14,824 PointsIt worked! I thought I had a good grasp of prefetch_related, but the way you explained it there made it crystal clear. Thank you for taking the time to explain that point to me. Thanks for all of the Python education you provide. I can't get enough of it. And thanks for making Django Braces!
Kenneth Love
Treehouse Guest TeacherKenneth Love
Treehouse Guest TeacherAwesome, glad you got it sorted and understand it better! (and you're very welcome for both the courses and django-braces).