example of to_attr argument in Prefetch in Django Document

I see this example of to_attr in Django document about Prefetch and I don’t quite understand why these two statements are different link

>>> Question.objects.prefetch_related(prefetch).get().voted_choices
[<Choice: The sky>]
>>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

First, the common case:

This is a query returning a single instance of Question, with the related Choice objects retrieved and associated with that instance.

Then looking at the second statement:

it adds the reference to the related object manager (choice_set) and returns the related Choice objects as a QuerySet. (Among other things, this means that you could chain additional queryset methods on to it, such as a values function.)


needs to be understood in the context of the previous definition of voted_choices which is:
voted_choices = Choice.objects.filter(votes__gt=0)
prefetch = Prefetch('choice_set', queryset=voted_choices, to_attr='voted_choices')

The to_attr parameter means that the Question instance being returned by that query is going to have a new attribute named voted_choices referencing the list defined by the voted_choices query. That is what is being demonstrated by the use of the .voted_choices reference on the first query.

It might be more clear to you if you were to refactor the code and think about it like this:

a_question = Question.objects.prefetch_related(prefetch).get(pk=1)
           ^^^^^^^^^^^^^^ # Returns all objects from the related manager
           ^^^^^^^^^^^^^ # Returns the new attribute defined by `prefetch`