Búsquedas inversas de claves externas en Django
Django es un marco de desarrollo web eficiente que simplifica la creación de aplicaciones web. Django facilita la tarea de autenticar y autorizar, crear plantillas HTML, manejar archivos estáticos, interactuar con bases de datos y realizar operaciones CRUD sobre ellos.
Hablando de bases de datos, Django simplifica la mayoría de las consultas que puede realizar mientras trabaja con bases de datos. Una de esas consultas es la vista inversa; un ejemplo es cuando tenemos que obtener todos los objetos de una tabla que hacen referencia a un registro particular de la misma tabla o de un modelo diferente.
Este artículo mostrará lo simple que es realizar búsquedas inversas de claves externas en Django.
Búsquedas inversas en modelos Django
Antes de pasar al paso real, necesitamos algunos modelos o tablas para la demostración. Consideraremos dos entidades: profesor y alumno. El alumno tiene dos tipos de profesores; un maestro de clase y un maestro favorito. El modelo Student
hace referencia al 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"
)
Dos campos del modelo Student
hacen referencia al modelo Teacher
. En Django, cuando se hace referencia al mismo modelo más de una vez, tenemos que proporcionar un related_name
para todos los campos porque el related_name
predeterminado de Django para un solo campo de referencia choca con otros campos de referencia. De lo contrario, Django lanzará una excepción.
El related_name
es lo que usamos para la búsqueda inversa. En general, es una buena práctica proporcionar un related_name
para todas las claves externas en lugar de usar el nombre relacionado por defecto de Django.
Ejemplo 1
Tenemos un profesor cuyo id
es 1
. Si tenemos que conseguir a todos los alumnos que tienen a este individuo como profesor de clase, haremos lo siguiente:
teacher = Teacher.objects.get(id=1)
students = teacher.classTeacherOf.all()
print(students) # A QuerySet of Student objects
Observe cómo estamos usando el related_name
. El teacher.classTeacherOf
es un objeto administrador, lo que significa que llamamos a métodos como all()
, filter()
, exclude()
en él.
Ejemplo 2
Tenemos un profesor cuyo id
es 6
. Si tenemos que conseguir a todos los alumnos que consideran a este profesor como su profesor favorito, haremos algo como esto:
teacher = Teacher.objects.get(id=6)
students = teacher.favouriteTeacherOf.all()
print(students) # A QuerySet of Student objects
Ejemplo 3
Tenemos un profesor cuyo id
es 25
. Si tenemos que comprobar si este profesor es el profesor de clase de un alumno cuyo id
es 5
, haremos algo de la siguiente manera:
teacher = Teacher.objects.get(id=25)
student = teacher.classTeacherOf.filter(id=5)
print(student) # A QuerySet of either 1 or 0 Student
Tenga en cuenta que si no se encuentran objetos en la búsqueda inversa, se devuelve un QuerySet
vacío.