Django: подсчет вложенных реверсов Foreignkey

мои модели:

class Course(models.Model):
    ...


class Section(models.Model):
    course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='sections')
    ...


class SubSection(models.Model):
    section = models.ForeignKey(Section, on_delete=models.CASCADE, related_name='subsections')
    registration_required = models.BooleanField(default=True)

Теперь я хочу узнать, если менее 5 подразделов курса являются registration_required = False. что-то вроде:

def validate(self, attrs):
    course = self.instance
    
    if course.sections.subsections.filter(registration_required=False).count() < 5:
        # do something ...

как лучше это сделать?

a = Course.objects.get({something})
Course.objects.filter(pk=a.pk, section__subsection__registration_required=False).count()

Вы можете проверить наличие одного Course объекта course с помощью:

Subsection.objects.filter(
    registration_required=False, section__course=my_course
).count() < 5

или с агрегатом:

from django.db.models import Count, Q

my_course.sections.aggregate(
    total=Count(
        'subsections',
        filter=Q(subsections__registration_required=False),
    )
)['total'] < 5

Если вы хотите сделать это в большом количестве, используйте:

from django.db.models import Count, Q

Course.objects.alias(
    nsubsec=Count(
        'sections__subsections',
        filter=Q(sections__subsections__registration_required=False),
    )
).filter(nsubsec__lt=5)

Таким образом, сначала мы подсчитываем количество SubSection с registration_required=False, а затем отфильтровываем Course на это число (nsubsec) так, чтобы оно было меньше пяти.

Попробуйте это

def validate(self, attrs):
    course = self.instance

    # Count the number of SubSections with registration_required=False for the given course
    count = SubSection.objects.filter(
        section__course=course,
        registration_required=False
    ).count()

    if count < 5:
        # Do something if fewer than 5 SubSections have registration_required=False
        pass

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