Two crucial questions are raised here.
First: How is choice_set called into existence?
Second: What is it?
I will describe, how I made it easy for me while learning it first time. Let me address the second question first, "What is it" with the help of these 3 words: Model Instance, Objects-set related to that instance, Related_manager.
Models.py from Django tutorial:
from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0)
Instance:
q = Question.objects.get(pk=3) # Here q is an instance of model class 'Question'. c = Choice.objects.get(pk=32) # Here c is an instance of model class 'Choice'.
Model Instance is a single ROW of an entire TABLE of your database
Here, the Question Model is used as a foreign key to the Choice Model. Therefore, all the objects-set related to instance q can be filtered by using:
q.choice_set.all()
Therefore, choice_set here is, all the choices related to the question, that has pk=3.
Now, the answer to the first question needs the third word Related Manager. Django documentation here:-
If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercase. This Manager returns QuerySets, which can be filtered and manipulated as described in the “Retrieving objects” section above.
This word (choice_set) can be changed using the 'related_name' parameter in the Foreign_key.
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="choices")
For backward relationships through foreign keys:
q.choice_set.all() # If using related_name, then it is the same as q.choices.all() # All the choices related to the instance q.
For forward relationship:
choice_qs = Choice.objects.all() choice_qs.filter(question=q) # Same result as above. All the choices related to instance q.