Use of _set in Django framework

Asked

Viewed 16 times

0

I’m following the framework tutorial but I got lost in the use of the command _set of the shell initialized by python manager.py shell.
The sequence of commands is as follows::

from polls.models import Choice, Question
q = Question.objects.get(pk=1)
q.choice_set.all()
q.choice_set.create(choice_text='Not much', votes=0)
q.choice_set.create(choice_text='The sky', votes=0)

py.models

import datetime

from django.db import models
from django.utils import timezone

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):
        return self.pub_date >= timezone.now() - datetime.timedelta(days = 1)

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 question is, why choice before _set? How exactly does this command work? The q. at the beginning is to assign the Question q to the field of the type models.ForeignKey?

1 answer

1


The pattern <modelo>_set or default_related_name is essentially responsible for making the reverse relationship of one (its object q instantiated from the class Question) for many (0 or more class created objects Choice associated with the class instance Question by relationship of ForeignKey).

In short, when the foreign key relationship is established (or ForeignKey above) in the model Choice pointing to the model Question automatically a one to many relation is established from the property choice_set (Choice based on the name of the adjacent model, always in lowercase) in the instance q.

As you originally observed, when using the method q.choice_set.create the object q will be automatically injected into the creation of the related class objects (Choice); analogously, when accessing the method q.choice_set.all you will be informing the framework that you want to get all class objects Choice that are related to the instance q specifically.

It is important to note that Choice.objects.all is different from q.choice_set.all in this case: the first will be getting all the objects of the class Choice without filtering the relationship with the class Question; in the second, as stated in the previous paragraph, a filter is basically established to obtain only the data related to the instance q.

To illustrate all this, note the following case:

from django.utils import timezone

# Criando um objeto Question
q = Question.objects.create(question_text='Que faz agora?', pub_date=timezone.now())

# Criando escolhas (Choice) relacionadas ao objeto Question
q.choice_set.create(choice_text='Programando', votes=0)
q.choice_set.create(choice_text='Jogando', votes=0)

'''
Demonstrando a criação de um novo objeto Question em que é definida
a associação diretamente na criação dos objetos Choice respectivos
'''
q2 = Question.objects.create(question_text='De onde fala?', pub_date=timezone.now())
Choice.objects.create(question=q2, choice_text='Brasil', votes=0)
Choice.objects.create(question=q2, choice_text='EUA', votes=0)

Finally, getting the Choices, we have the following results:

# Obtendo as escolhas (Choice) da pergunta (Question) 'Que faz agora?'
>>> q.choice_set.all()
<QuerySet [<Choice: Programando>, <Choice: Jogando>]>

# Mesma coisa para a pergunta 'De onde fala?'
>>> q2.choice_set.all()
<QuerySet [<Choice: Brasil>, <Choice: EUA>]>

# Obtendo os objetos Choice sem filtrar por qualquer dos Question relacionados
>>> Question.objects.all()
<QuerySet [<Choice: Programando>, <Choice: Jogando>, <Choice: Brasil>, <Choice: EUA>]>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.