Pesquisas reversas de chaves estrangeiras no Django
Django é uma estrutura de desenvolvimento web eficiente que simplifica a criação de aplicativos web. Django torna fácil lidar com autenticação e autorização, criação de templates HTML, lidar com arquivos estáticos, interagir com bancos de dados e realizar operações CRUD sobre eles.
Falando em bancos de dados, o Django simplifica a maioria das consultas que você pode fazer enquanto trabalha com bancos de dados. Uma dessas perguntas é a aparência inversa; um exemplo é quando temos que obter todos os objetos de uma tabela que fazem referência a um determinado registro da mesma tabela ou de um modelo diferente.
Este artigo mostrará como é simples realizar pesquisas reversas de chaves estrangeiras no Django.
Pesquisas reversas em modelos Django
Antes de passarmos para a etapa real, precisamos de alguns modelos ou tabelas para demonstração. Vamos considerar duas entidades: professor e aluno. O aluno tem dois tipos de professores; um professor de classe e um professor favorito. O modelo Student
faz referência ao modelo Teacher
.
from django.db import models
class Teacher(models.Model):
name = models.CharField(max_length=200)
subject = models.CharField(max_length=200)
class Student(models.Model):
name = models.CharField(max_length=200)
classTeacher = models.ForeignKey(
Teacher, on_delete=models.SET_NULL, null=True, related_name="classTeacherOf"
)
favouriteTeacher = models.ForeignKey(
Teacher, on_delete=models.SET_NULL, null=True, related_name="favouriteTeacherOf"
)
Dois campos do modelo Student
fazem referência ao modelo Teacher
. No Django, ao fazer referência ao mesmo modelo mais de uma vez, temos que fornecer um related_name
para todos os campos porque o padrão related_name
do Django para um único campo de referência entra em conflito com outros campos de referência. Caso contrário, o Django lançará uma exceção.
O related_name
é o que usamos para a pesquisa inversa. Em geral, é uma boa prática fornecer um related_name
para todas as chaves estrangeiras ao invés de usar o nome relacionado padrão do Django.
Exemplo 1
Temos um professor cujo id
é 1
. Se tivermos que obter todos os alunos que têm esse indivíduo como professor da turma, faremos o seguinte:
teacher = Teacher.objects.get(id=1)
students = teacher.classTeacherOf.all()
print(students) # A QuerySet of Student objects
Observe como estamos usando o related_name
. O teacher.classTeacherOf
é um objeto gerenciador, o que significa que nele chamamos métodos como all()
, filter()
, exclude()
.
Exemplo 2
Temos um professor cujo id
é 6
. Se tivermos que conseguir todos os alunos que consideram esse professor como seu professor favorito, faremos algo assim:
teacher = Teacher.objects.get(id=6)
students = teacher.favouriteTeacherOf.all()
print(students) # A QuerySet of Student objects
Exemplo 3
Temos um professor cujo id
é 25
. Se tivermos de verificar se este professor é o professor da turma de um aluno cujo id
é 5
, faremos o seguinte:
teacher = Teacher.objects.get(id=25)
student = teacher.classTeacherOf.filter(id=5)
print(student) # A QuerySet of either 1 or 0 Student
Observe que, se nenhum objeto for encontrado na pesquisa reversa, um QuerySet
vazio será retornado.