Django: Is possible use _set into the filter() method?

Question:

I’m working on my ListView called IndexView on my polls app. This view currently return the last five published questions (not including those set to be published in the future). But my view also publish Questions that don’t have any Choice, so I also want this view to only publish Questions that have Choices.

IndexView in views.py

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """
        Return the last five published questions (not including those set to be
        published in the future).
        """
        return Question.objects.filter(
            pub_date__lte=timezone.now()
        ).order_by('-pub_date')[:5]

Question and Choice models in models.py

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text
    
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

My approach is to use the _set object and checking if the size of the queryset is bigger than 0 but I don’t know if is possible use this object into the filter() method.

Asked By: Levliam

||

Answers:

Use related_name attribute in Choice class so:

question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='choices')

Which allows you to do that:

Question.objects.filter(
  pub_date__lte=timezone.now(), choices__isnull=False
).order_by('-pub_date')[:5]
Answered By: Andreas
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.