Problem with queryset filtering with Django’s new Prefetch option

955 views
Skip to first unread message

Tobias Abdon

unread,
Nov 29, 2014, 8:21:03 AM11/29/14
to django...@googlegroups.com
I am trying to use prefetch_related’s new Prefetch option to further filter a database query. Using debug toolbar I can see that prefetch_related is doing its job in making only three DB queries. However, I am positive that the queryset filter I’m passing in is not working. Even though I’m using the option, all of the records are being retrieved in the query.

The goal of the below code is to show a list of Chapters. For each chapter, show its lessons. For each lesson, show the logged in user’s status (complete/incomplete).

Models
class Chapter(models.Model):
    status = models.IntegerField(choices=STATUS_CHOICES, default=1)
    name = models.CharField(max_length=100)
    slug = AutoSlugField(populate_from='name')
    desc = models.TextField()

class Lesson(models.Model):
    name = models.CharField(max_length=100)
    chapter = models.ForeignKey(Chapter, related_name=‘les_chapter’)

class LessonStatus(models.Model):
    status = models.IntegerField(choices=STATUS_CHOICES, default=1)
    lesson = models.ForeignKey(Lesson, related_name="status_lesson")
    student = models.ForeignKey(User)
    chapter = models.ForeignKey(Chapter, related_name=“status_chapter")


View
def chapter_list(request, course_slug):

    course = Course.objects.get(slug=course_slug)

    chapters = Chapter.objects.filter(course=course).prefetch_related(
        Prefetch('status_chapter__lesson__chapter', queryset=LessonStatus.objects.filter(student=request.user)),
    )

    return TemplateResponse(request,
        'course/chapter_list_parent.html',
        {'chapters': chapters, 'course': course,}
    )


Template
<div id="chapters">
    {% for ch in chapters %}
        <p>{{ ch.name }}</p>
        {% for le in ch.status_chapter.all %}
            <p>lesson status: {{ le.status }}</p>
            <p>lesson name: {{ le.lesson.name }}</p>
        {% endfor %}
    {% endfor %}
</div>

When I run this code the LessonStatus is not being filtered by student=request.user. Instead, it is simply getting all LessonStatus records, including those that are for other users. 

Can anyone see if there's something wrong with the above code? Or any ideas how to troubleshoot? There are no errors generated.

Collin Anderson

unread,
Nov 30, 2014, 2:20:12 PM11/30/14
to django...@googlegroups.com
Hi,

Try this:

chapters = Chapter.objects.filter(course=course).prefetch_related(
        Prefetch('status_chapter', queryset=LessonStatus.objects.filter(student=request.user).select_related('lesson')),
)

Otherwise, maybe the to_attr will help.

Collin
Reply all
Reply to author
Forward
0 new messages