Как фильтровать объекты по атрибуту "многие ко многим

Пожалуйста, помогите мне решить следующую проблему:

У меня есть две модели, например:


class Student(model.Model): 
    first_name = models.Charfield()
    last_name = models.Charfield()

class Teacher(model.Model):
    first_name = models.Charfield()
    last_name = models.Charfield()
    subject = models.Charfield()
    students = models.ManyToManyField('Student')

Объект учителя может иметь много учеников. При добавлении нового учителя, его ученики сразу указываются, но для каждого ученика необходимо выполнить проверку, что этот ученик не привязан к другому учителю с таким же предметом. Помогите, пожалуйста, как организовать эту проверку (я предполагаю использовать фильтр).

Заранее большое спасибо!

Я пытался использовать фильтр типа Teacher.objects.filter(subject=self.subject), но не знаю, как проверить каждого ученика

Вы можете проверить, есть ли другой учитель с тем же предметом с помощью:

from django.db.models import F, Q

Teacher.objects.filter(
    ~Q(students__teacher__pk=F('pk')), students__teacher__subject=F('subject')
).annotate(
    student_id=F('students__pk'), other_teacher_id=F('students__teacher__pk')
)

В результате будут получены Teacher, для которых есть хотя бы один ученик с другим учителем с тем же предметом. Учитель будет иметь дополнительные атрибуты student_id и other_teacher_id, которые перечисляют ученика и другого учителя, для которых имеет место нарушение. Таким образом, одно и то же Teacher может встречаться несколько раз.

При этом моделирование выглядит не очень хорошо: учитель может давать только один предмет? Вместо этого вы можете сделать таблицу перекрестков с:

class Student(model.Model):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)


class Teacher(model.Model):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)
    students = models.ManyToManyField('Student', through='Subject')


class Subject(models.Model):
    teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    subject = models.CharField(max_length=128)

    class Meta:
        constraints = [
            models.UniqueConstaint(
                fields=('subject', 'student'), name='subject_once_per_student'
            )
        ]

Это гарантирует, что один и тот же студент не сможет сдавать один и тот же предмет несколько раз, и обеспечивается на уровне базы данных.

Вернуться на верх