Django-filter: Filtragem padrão quando nenhum parâmetro de filtro é passado na solicitação.GET

Criado em 6 nov. 2015  ·  6Comentários  ·  Fonte: carltongibson/django-filter

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

Comentários muito úteis

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

Todos 6 comentários

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!

Esta página foi útil?
0 / 5 - 0 avaliações