我翻阅了多个类似的问题,但找不到逻辑,我的操作不成功。
我有一个论坛应用程序,其结构是“论坛->子论坛->主题->评论”,对应子论坛、主题和评论的模型。我必须在每个子论坛页面上实现一个过滤器(其中显示相应主题的列表),通过它我可以通过多种条件配置主题之间的搜索。
特别是我必须实现一个自定义过滤器,我的想法是为空主题创建一个过滤器,即仅包含初始评论且没有回复的主题。经过绝望的挣扎,我终于明白了如何在查询集中实现反向外键连接,但现在我不能使用查询集表达式作为过滤器,因为它返回 TypeError: Cannot filter against a non-conditional expression.
具体内容如下:
过滤器.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
上述方法不起作用 - 显然,无法提供查询集表达式的链接作为过滤条件。但即使输入表达式本身,那就是:
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
那么它也不起作用。
比较一下:
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
返回了另一个错误:TypeError:'QuerySet'和'int'的实例之间不支持'>='。
现在我很难为潜在的查询集制定适当的过滤器表达式。因此我来这里寻求帮助和建议。
如果需要任何其他信息/文件,我准备提供。
.filter(…)
[Django-doc] 在 .annotate(…)
[Django-doc] 上使用:
def filter_empty(self, queryset, 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