Как отфильтровать таблицу на основе данных из другой таблицы

есть три таблицы:

class Course(models.Model):

 name = models.CharField(max_length=255)
 description = models.CharField(max_length=255)
 start_date = models.CharField(max_length=255)
 end_date = models.CharField(max_length=255)

 def get_count_student(self):

     count = CourseParticipant.objects.filter(course=self.id)
     return len(count)

 def __str__(self):
     return f'{self.name}'

class Student(models.Model):

 first_name = models.CharField(max_length=255)
 last_name = models.CharField(max_length=255)
 email = models.CharField(max_length=255)

 def __str__(self):
    return f'{self.first_name}'

class CourseParticipant(models.Model):

 course = models.ForeignKey(Course, related_name='course', on_delete=models.CASCADE)
 student = models.ForeignKey(Student, related_name='student', on_delete=models.CASCADE)
 completed = models.BooleanField(default=False)

Хочу получить студентов которые не участвуют в конкретных курсах, выполняю следующий запрос

potential = Student.objects.exclude(courseparticipants__course=pk)

где в pk указываю id курса, в ответ получаю:

django.core.exceptions.FieldError: Cannot resolve keyword 'courseparticipants' into field. Choices are: email, first_name, id, last_name, student


Ответы (1 шт):

Автор решения: Za Ars

Во первых, у вас не правильные related_name

course = models.ForeignKey(Course, related_name='course', on_delete=models.CASCADE)
student = models.ForeignKey(Student, related_name='student', on_delete=models.CASCADE)
 

Что такое related_name ? Это название свойства у связанного объекта, которое используется для обращения к объекту, в котором указана эта связь.

Это значит, что для связи со студентами, related_name должен быть, например, participantion. Для курсов - participants.

Тогда получение доступа к этим данным из объекта Student будет выглядеть так

# student - объект Student
student.participantion.all() # queryset модели CourseParticipant

А теперь по вопросу. С учетом моих советов, надо написать так:

potential = Student.objects.exclude(participantion__course=pk)

Для вашего примера без моих правок

potential = Student.objects.exclude(student__course=pk)
→ Ссылка