Django : Ignore a __in type filter in the queryset if it searches the empty list

Question:

Having this code sequence:

queryset = self.filter(
            brand_id__in=(
                UserObjectPermission.objects.filter(
                    content_type=brand_ctype,
                    user=user,
                ).values_list('object_pk')
            )
        )

If there is no UserObjectPermission object that matches the filter content_type=brand_ctype, user=user then the end result will be empty queryset, because brand_id __in will search in [empty queryset].

But I need the reverse. If there is no UserObjectPermision object for this filter (content_type=brand_ctype, user=user) then return all objects, that is, ignore this filter (

brand_id__in=(UserObjectPermission.objects.filter(
                    content_type=brand_ctype,
                    user=user,
                ).values_list('object_pk')
            )

I need the brand_id__in filter to run only if there is at least one object in the queryset.

Asked By: johny

||

Answers:

You can check if the queryset contains any items:

brands = UserObjectPermission.objects.filter(
    content_type=brand_ctype,
    user=user,
).values_list('object_pk')

if brands:
    queryset = queryset.filter(brand_id__in=brands)
Answered By: Willem Van Onsem

you can try the OR (|) operator

from django.db.models import Q, Exists

brands_qs = UserObjectPermission.objects.filter(
    content_type=brand_ctype,
    user=user,
).values_list('object_pk')

queryset = self.filter(
    Q(brand_id__in=brands_qs) | ~Exists(brands_qs)
)
Answered By: Rodi Zaharadji