У меня есть следующие модели:
Организация
Студент
Курс
Зачисление
Студент принадлежит к организации
Студент может записаться на 1 или более курсов
Так Запись о регистрации в основном состоит из данного курса и данного студента
from django.db import models
from model_utils.models import TimeStampedModel
class Organisation(TimeStampedModel):
objects = models.Manager()
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Student(TimeStampedModel):
objects = models.Manager()
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(unique=True)
organisation = models.ForeignKey(to=Organisation, on_delete=models.SET_NULL, default=None, null=True)
def __str__(self):
return self.email
class Course(TimeStampedModel):
objects = models.Manager()
language = models.CharField(max_length=30)
level = models.CharField(max_length=2)
def __str__(self):
return self.language + ' ' + self.level
class Meta:
unique_together = ("language", "level")
class EnrollmentManager(models.Manager):
def org_students_enrolled(self, organisation):
return self.filter(student__organisation__name=organisation).all()
class Enrollment(TimeStampedModel):
objects = EnrollmentManager()
course = models.ForeignKey(to=Course, on_delete=models.CASCADE, default=None, null=False, related_name='enrollments')
student = models.ForeignKey(to=Student, on_delete=models.CASCADE, default=None, null=False, related_name='enrollments')
enrolled = models.DateTimeField()
last_booking = models.DateTimeField()
credits_total = models.SmallIntegerField(default=10)
credits_balance = models.DecimalField(max_digits=5, decimal_places=2)
Обратите внимание на пользовательский EnrollmentManager, который позволяет мне найти всех студентов, зачисленных в данную организацию.
Как я могу добавить собственного менеджера для извлечения всех курсов из данной организации, у которых зачислены студенты?
Что я пробовал
Я думал создать CourseManager и каким-то образом запросить / Отфильтруйте с этой стороны отношений:
class CourseManager(models.Manager):
def org_courses_enrolled(self, organisation):
return self.filter(enrollment__student__organisation__name=organisation).all()
Это работает, но дает мне те же 100 записей о зачислении: (
Что я пытаюсь получить: основано на данной организации найти всех студентов, которые зачислены, а затем (DISTINCT?), чтобы получить Список зарегистрированных курсов для этой организации
Это представление:
class OrganisationCoursesView(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
serializer_class = CourseSerializer
queryset = Course.objects.get_courses(1)
и URL:
# The below should allow: /api/v1/organisations/1/courses/
router.register('api/v1/organisations/(?P<organisation_pk>\d+)/courses', OrganisationCoursesView, 'organisation courses')
ОБНОВЛЕНИЕ 1
Основываясь на ответе h1dd3n, я попытался сделать следующее:
class CourseManager(models.Manager):
def get_queryset(self):
return super(CourseManager, self).get_queryset()
def get_courses(self, organisation):
return self.get_queryset().filter(student__organisation_id=organisation)
, но это выдает ошибку (как я и ожидал):
FieldError: Невозможно разрешить ключевое слово 'student' в поле. Варианты выбора: курсы, созданные, идентификатор, язык, уровень, изменение, прогресс
ОБНОВЛЕНИЕ 2 - ближе!
Хорошо, с помощью комментариев @ AKX :
class CourseManager(models.Manager):
def get_queryset(self):
return super(CourseManager, self).get_queryset()
def get_courses(self, organisation):
return self.get_queryset().filter(courses__student__organisation_id=organisation)
теперь возвращает курсы, но возвращает копию для каждого зачисленного студента. Теперь мне нужно сгруппировать их, чтобы каждая запись появлялась только один раз ...