尝试使用 django 过滤器为给定模型中的所有字段创建一般搜索

Posted

技术标签:

【中文标题】尝试使用 django 过滤器为给定模型中的所有字段创建一般搜索【英文标题】:Trying to create a general search using django filters for all the fields in a given model 【发布时间】:2019-11-10 11:41:30 【问题描述】:

所以我正在为我的模型创建一个自定义过滤器,我希望该过滤器中的所有字段不使用“精确”而是“包含”,但我不想手动添加所有字段。我正在尝试做这样的事情:

from django_filters import FilterSet
from polls.models import Question, Choice
from django_filters import rest_framework

class ChoiceFilter(FilterSet):
    for field in Choice._meta.get_fields():

        field = rest_framework.CharFilter(lookup_expr='icontains')
    #question = rest_framework.CharFilter(lookup_expr='icontains') #this works want to generalize this

    class Meta:
        model = Choice
        fields = '__all__'

所以第二行有效,但我的 for 循环无效,我的过滤器使用 'exact' 而不是 'contains'

【问题讨论】:

【参考方案1】:

您可以创建一个自定义的FilterSet 类,它会覆盖get_fields 方法来将查找从exact 更改为icontains

class CustomFilterSet(FilterSet):
    @classmethod
    def get_fields(cls):
        fields = super().get_fields()
        for name, lookups in fields.items():
            lookups[:] = ['icontains']
        return fields

现在你只需让ChoiceFilter 继承这个类:

class ChoiceFilter(CustomFilterSet):
    class Meta:
        model = Choice
        fields = '__all__'

请记住,将__all__ 用于字段是很危险的。

【讨论】:

谢谢!这似乎主要工作,我只是收到一个错误,上面写着'django_filters.exceptions.FieldLookupError:字段'polls.Choice.question'的不支持查找'icontains'。'。我很确定这个错误是因为“问题”是一个外键,你知道我怎么可能解决这个问题吗? 你是对的。您要么需要明确声明所有字段,要么使用exclude 排除question 字段。 你知道在一个模型中获取所有外键的方法吗? (没关系,我可以自己进行搜索,但非常感谢!) 为此您可以使用get_fields 方法,但不建议这样做。如果您向 Choice 模型添加新字段,您的 ChoiceFilterSet 将被隐式更改。 你认为这样的事情会奏效吗? ` blackList = [] for field in Choice._meta.fields: if field.get_internal_type() == 'ForeignKey': blackList.append(field.__name__) exclude = blackList`【参考方案2】:

在我的用例中,我需要通过多个基于日期的查找表达式过滤单个 DateTimeField。最有效的方法是在我的字段字典中使用 date__ 前缀:

# Bullet Filter
class BulletFilter(filters.FilterSet):
    class Meta:
        model = Bullet
        fields = 
            'bullet_header': ['icontains'],
            'bullet_cite_date': ['iexact', 'gte', 'lte'],
            'created': ['date__iexact', 'date__gte', 'date__lte'],
            'updated': ['date__iexact', 'date__gte', 'date__lte'],
        

这里bullet_header是CharField,bullet_cite_date是DateField,createdupdated是DateTimeFields。

【讨论】:

【参考方案3】:

从 django-filter v2.3 开始,您可以在 settings.py 中定义 FILTERS_DEFAULT_LOOKUP_EXPR = 'icontains',这将改变默认行为。

【讨论】:

以上是关于尝试使用 django 过滤器为给定模型中的所有字段创建一般搜索的主要内容,如果未能解决你的问题,请参考以下文章

django模型系统

django过滤器大全

django模型系统二

django模型系统二

Django:过滤一个模型记录以显示其他模型的所有记录

Django 模型过滤器以 JSONField 为目标,其中键包含连字符/破折号