各位,
如果在请求对象中没有找到我在 Meta.fields 中定义的参数,是否有设置默认过滤器字段和值的选项?
如果没有这样的选择,您认为最好的方法是什么?
问候,
安德留斯
嗨@andrius-senulis。 django-filter 建立在常规 django 表单之上,所以这个问题可以归结为“如何为绑定表单提供默认字段值?” 根据此 SO answer ,您可以向表单添加clean_<field_name>
方法以提供默认值。 不幸的是,底层的表单类没有直接公开,所以你不能子类化它并添加该方法(请参阅编辑)。 也就是说,过滤器有一个底层表单字段,因此您可以子类化该字段并覆盖其clean()
方法。 这有点麻烦。 例如,
class DecimalDefaultField(forms.DecimalField):
def clean(self, value):
if value is None:
return 4.0
return super(DecimalDefaultField, self).clean(value)
class NumberDefaultFilter(filters.NumberFilter):
field_class = DecimalDefaultField
class MyFilterSet(FilterSet):
some_field = NumberDefaultFilter(name='some_field')
...
一种更简单的方法是检查传入的数据并设置默认值。
def your_view(request):
data = request.GET.copy()
data.setdefault('some_field', 'some_value')
f = YourFilterSet(data, queryset=YourModel.objects.all())
...
编辑:
您实际上可以为FilterSet.Meta
提供一个基本形式,然后在内部对其进行子类化。 所以, clean_<field name>
是可能的。
class MyForm(forms.Form):
clean_some_field(self, value):
...
class MyFilterSet(FilterSet):
class Meta:
model = MyModel
form = MyForm
fields = ['some_field']
我使用过滤器视图。 覆盖 get_filterset_kwargs 对我有用:
class MyFilterView(FilterView):
filterset_class = filters.MyFilter
# ...
def get_filterset_kwargs(self, filterset_class):
kwargs = super(MyFilterView, self).get_filterset_kwargs(filterset_class)
if kwargs["data"] is None:
kwargs["data"] = {"is_very_interesting": False}
return kwargs
编辑:当使用例如分页时,这不适用(b/c 数据不是无)。 像这样的事情可能会奏效:
if kwargs["data"] is None:
kwargs["data"] = {"is_very_interesting": False}
elif "is_very_interesting" not in kwargs["data"]:
kwargs["data"] = kwargs["data"].copy()
kwargs["data"]["is_very_interesting"] = False
使用__init__
对我有用。 (这是djangorestframework-filters
,但我认为与原版django-filter
):
class MyFilter(filters.FilterSet):
foo = ...
def __init__(self, data, *args, **kwargs):
if not data.get('foo'):
data = data.copy()
data['foo'] = 'bar'
super().__init__(data, *args, **kwargs)
不推荐使用__init__
的方法,链接中记录的解决方法对我不起作用...... https://django-filter.readthedocs.io/en/master/guide/tips.html #using -initial-values-as-defaults
get_filterset_kwargs
中的FilterView
为我工作。
不推荐使用
__init__
方法
一般不建议提供默认的表单/过滤器值,因为这是一种可能会产生混淆/不利影响的不良做法。 通过__init__
或任何其他方法实现都可以(假设您对效果没问题)。
我使用过滤器视图。 覆盖 get_filterset_kwargs 对我有用:
class MyFilterView(FilterView): filterset_class = filters.MyFilter # ... def get_filterset_kwargs(self, filterset_class): kwargs = super(MyFilterView, self).get_filterset_kwargs(filterset_class) if kwargs["data"] is None: kwargs["data"] = {"is_very_interesting": False} return kwargs
编辑:当使用例如分页时,这不适用(b/c 数据不是无)。 像这样的事情可能会奏效:
if kwargs["data"] is None: kwargs["data"] = {"is_very_interesting": False} elif "is_very_interesting" not in kwargs["data"]: kwargs["data"] = kwargs["data"].copy() kwargs["data"]["is_very_interesting"] = False
你让我今天一整天都感觉很好!
最有用的评论
我使用过滤器视图。 覆盖 get_filterset_kwargs 对我有用:
编辑:当使用例如分页时,这不适用(b/c 数据不是无)。 像这样的事情可能会奏效: