163
votes

There is this line in the Django tutorial, Writing your first Django app, part 1:

p.choice_set.create(choice='Not much', votes=0)

How is choice_set called into existence and what is it?

I suppose the choice part is the lowercase version of the model Choice used in the tutorial, but what is choice_set? Can you elaborate?

UPDATE: Based on Ben's answer, I located this documentation: Following relationships "backward".

1
I should have just linked to that documentation, it is clearer than my answer. - Ben James
@Ben James: no, I appreciate to have it formulated in a different way, especially the elaboration of what the ORM is doing. The Django documentation can be terse at times. - Peter Mortensen
Thank you for asking this, I was confused by this as they do not explain it in the tutorial. - claudio
Wow, that's a loaded line of code for a newbie. For me the hurdle was understanding that we're getting a Choice Object, related to the Question, in order to then increment it's choice.votes by one. The RelatedManager concept has not been mentioned in the tutorial to this point so it can be a real stumbling block. - frozenjim
@HemantKumar I tried to correct the docs but was not approved. If you find the same issue feel free to comment in the PR: github.com/django/django/pull/13330 - Escachator

1 Answers

200
votes

You created a foreign key on Choice which relates each one to a Question.

So, each Choice explicitly has a question field, which you declared in the model.

Django's ORM follows the relationship backwards from Question too, automatically generating a field on each instance called foo_set where Foo is the model with a ForeignKey field to that model.

choice_set is a RelatedManager which can create querysets of Choice objects which relate to the Question instance, e.g. q.choice_set.all()

If you don't like the foo_set naming which Django chooses automatically, or if you have more than one foreign key to the same model and need to distinguish them, you can choose your own overriding name using the related_name argument to ForeignKey.