Question

Following the tutorial at djangoproject, I have created a Poll with 2 polls.

In [14]: Poll.objects.all()
Out[14]: [<Poll: poll1>, <Poll: poll2>]

When I apply the filter

In [18]: Poll.objects.filter(choice__choice_text__isnull=False)

The following is returned, even though there are only 2 polls.

Out[18]: [<Poll: poll1>, <Poll: poll1>, <Poll: poll1>, <Poll: poll2>, <Poll: poll2>, <Poll: poll2>]

Why are there multiple occurences of the same poll? The goal of the filter is to filter out the polls that don't have any choices. In addition, other filters like below do work.

In [19]: Poll.objects.filter(pub_date__lte=timezone.now)
Out[19]: [<Poll: poll1>, <Poll: poll2>]
Was it helpful?

Solution

Do the polls being returned have choices? It looks like it's returning one instance of a poll for every associated choice, resulting in duplicates. To get rid of these, use distinct():

Poll.objects.filter(choice__choice_text__isnull=False).distinct()

Update: let's go under the hood. Your first query is spanning the Poll-Choice relationship, using a JOIN behind-the-scenes to "combine" the two tables. (JOINs can be complicated, so if this is confusing I suggest researching them.) Your query is returning a Poll object for every Choice whose text is null.

On the other hand, your second query is simply selecting from your Poll table. The line:

Poll.objects.filter(pub_date__lte=timezone.now)

translates to SELECT * FROM poll WHERE pub_date <= tz.now. For more details on field lookups, see the docs. For more guidance on spanning relationships, see the docs again.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top