Django TypeError: Cannot filter against a non-conditional expression while filtering by foreign key

I've looked through multiple similar questions, but couldn't get the logic, and my manipulations were unsuccessful.

I have a forum app, its structure is "forum->subforum->topic->comments", corresponding models for subforums, topics and comments. I have to implement a filter on each subforum page (where the list of corresponding topics is displayed), by which I can configure the search of/among the topics by several conditions.

Particularly I have to implement a custom filter, and my idea was to create a filter for empty topics, that is, for topics only with initial comments and without responses. Through a desperate struggle I've finally understood how to implement reversed foreign key connection in querysets, but now I can't use a queryset expression as a filter, as it returns TypeError: Cannot filter against a non-conditional expression.

Here are the specifics:

filters.py:

import django_filters
from django.db.models import Count

from forum.models import Topic


class TopicFilter(django_filters.FilterSet):
    date_span = django_filters.DateRangeFilter(field_name='created', label='Период создания')
    comments = django_filters.CharFilter(field_name='comment__content', lookup_expr='icontains', label='Комментарии')
    subject = django_filters.CharFilter(lookup_expr='icontains', label='Тема обсуждения')
    creator = django_filters.CharFilter(field_name='creator__username', lookup_expr='icontains', label='Создатель темы')
    is_empty = django_filters.BooleanFilter(method='filter_empty', label='Темы без комментариев')

    class Meta:
        model = Topic
        fields = ['subject', 'creator', 'date_span', 'comments', 'is_empty']

    def filter_empty(self, queryset, value):
        comment_count_gte_1 = Topic.objects.annotate(comment_count=Count('comments')).filter(comment_count__gte=1)
        comment_count_lt_1 = Topic.objects.annotate(comment_count=Count('comments')).filter(comment_count__lt=1)
        if value is True:
            return queryset.filter(comment_count_lt_1)
        elif value is False:
            return queryset.filter(comment_count_gte_1)
        else:
            return queryset

The aforementioned approach doesn't work - apparently, one can't provide a link of queryset expression as a filter criteria. But even if to enter the expression itself, that is:

def filter_empty(self, queryset, value):
        if value is True:
            return queryset.filter(Topic.objects.annotate(comment_count=Count('comments')).filter(comment_count__lt=1))
        elif value is False:
            return queryset.filter(Topic.objects.annotate(comment_count=Count('comments')).filter(comment_count__gte=1))
        else:
            return queryset

then it doesn't work either.

Comparing it the way like:

def filter_empty(self, queryset, value):
        comment_count = Topic.objects.annotate(comment_count=Count('comments'))

        if value is True:
            return queryset.filter(comment_count < 1)
        elif value is False:
            return queryset.filter(comment_count >= 1)
        else:
            return queryset

returned another error: TypeError: '>=' not supported between instances of 'QuerySet' and 'int'.

And now I have difficulties in elaborating a proper filter expression for a potential queryset. Thus I came here to ask for help and advice.

If any additional info/files are necessary, I'm ready to provide them.

You .filter(…) [Django-doc] on an .annotate(…) [Django-doc] with:

def filter_empty(self, queryset, name, value):
    queryset = Topic.objects.annotate(comment_count=Count('comments'))

    if value is True:
        return queryset.filter(comment_count__lt=1)
    elif value is False:
        return queryset.filter(comment_count__gte=2)
    else:
        return queryset
Back to Top