[Answered ]-How to Django queryset annotate True when all BooleanField of related objects are True else False?

1👍

You can make use of Django’s Conditional expressions in combination with the Q objects.

Give this a try

from django.db.models import Case, When, Value, BooleanField, Count, Q

test = Test.objects.annotate(
    number_of_test=Count("testversion", distinct=True)
).annotate(
    all_validated=Case(
        When(
            Q(testversion__validation_1=True)
            & Q(testversion__validation_2=True)
            & Q(testversion__validation_3=True)
            & Q(testversion__validation_4=True),
            then=Value(True),
        ),
        default=Value(False),
        output_field=BooleanField(),
    )
).distinct()

if all of your test validations are True then the value of output filed all_validated will be True otherwise it be False

0👍

I finally find an other answer :

from test.models import Test, TestVersion
from django.db.models import Count, Case, When, Exists, OuterRef, Value, BooleanField

test = Test.objects.filter(
    user=request.user
).annotate(
    number_of_test=Count("testversion", distinct=True),
    all_validation_1=Case(
        When(
            Exists(TestVersion.objects.filter(test=OuterRef('pk'), validation_1=False)), 
            then=Value(False)
        ),
        default=Value(True),
        output_field=BooleanField()
    )
).distinct()

In this case :

>> test.first().all_validation_1 == all(test.first().testversion_set.all().values_list('validation_1', flat=True))
True

So I just need to reiterate the same thing for validation_2, 3 and 4 and it should be ok.

But I think it will be a little bit fat code. Or it can be a good practice ?

Let me know before I check the answer.

Leave a comment