Caros,
Existe uma opção para definir o campo de filtro padrão e valor a ser usado se nenhum parâmetro que eu definir em Meta.fields foi encontrado no objeto de solicitação?
Se não houvesse essa opção, qual você sugeriria como a melhor maneira de fazer isso?
Cumprimentos,
Andrius
Olá @ andrius-senulis. django-filter é construído em cima de formulários regulares django, então esta questão pode ser resumida em "Como eu forneço valores de campo padrão para formulários vinculados?" Por esta resposta do SO, você pode adicionar um método clean_<field_name>
ao seu formulário para fornecer um valor padrão. Infelizmente, a classe de formulário subjacente não é exposta diretamente, então você não pode criar uma subclasse e adicionar esse método (consulte editar). Dito isso, os filtros têm um campo de formulário subjacente, portanto, você pode criar uma subclasse do campo e substituir seu método clean()
. Isso é um pouco complicado. por exemplo,
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')
...
Um método mais fácil seria apenas inspecionar os dados de entrada e definir um valor padrão.
def your_view(request):
data = request.GET.copy()
data.setdefault('some_field', 'some_value')
f = YourFilterSet(data, queryset=YourModel.objects.all())
...
editar:
Na verdade, você é capaz de fornecer um formulário básico para FilterSet.Meta
, que é então subdividido internamente. Portanto, clean_<field name>
é possível.
class MyForm(forms.Form):
clean_some_field(self, value):
...
class MyFilterSet(FilterSet):
class Meta:
model = MyModel
form = MyForm
fields = ['some_field']
Eu uso um FilterView. Substituir get_filterset_kwargs funciona para mim:
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
Editar: Ao usar, por exemplo, paginação, isso não é aplicado (os dados b / c não são Nenhum). Algo assim pode funcionar:
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
Usar __init__
funcionou para mim. (Isso é com djangorestframework-filters
, mas acho que é o mesmo que baunilha 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)
o método com __init__
não é recomendado e a solução alternativa documentada no link não funcionou para mim ... https://django-filter.readthedocs.io/en/master/guide/tips.html #using -initial-values-as-defaults
get_filterset_kwargs
nos FilterView
funcionou para mim.
o método com
__init__
não é recomendado
Fornecer valores de formulário / filtro padrão em geral não é recomendado, pois é uma prática ruim que pode ter efeitos confusos / adversos. Implementar via __init__
ou qualquer outro método está bom (desde que você esteja bem com os efeitos).
Eu uso um FilterView. Substituir get_filterset_kwargs funciona para mim:
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
Editar: Ao usar, por exemplo, paginação, isso não é aplicado (os dados b / c não são Nenhum). Algo assim pode funcionar:
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
Você fez meu dia!
Comentários muito úteis
Eu uso um FilterView. Substituir get_filterset_kwargs funciona para mim:
Editar: Ao usar, por exemplo, paginação, isso não é aplicado (os dados b / c não são Nenhum). Algo assim pode funcionar: