Django-filter: Filtrado predeterminado cuando no se pasaron parámetros de filtro en la solicitud.

Creado en 6 nov. 2015  ·  6Comentarios  ·  Fuente: carltongibson/django-filter

Estimados,

¿Existe una opción para establecer el campo de filtro predeterminado y el valor para usar si no se ha encontrado ningún parámetro que defino en Meta.fields en el objeto de solicitud?

Si no existe esa opción, ¿cuál sugeriría como la mejor manera de hacerlo?

Saludos,
Andrius

Comentario más útil

Yo uso FilterView. Anular get_filterset_kwargs funciona para mí:

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: cuando se usa, por ejemplo, la paginación, esto no se aplica (los datos b / c no son Ninguno). Algo como esto podría 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 comentarios

Hola @ andrius-senulis. django-filter está construido sobre los formularios normales de django, por lo que esta pregunta se puede resumir en "¿Cómo proporciono valores de campo predeterminados para formularios enlazados?" Según esta respuesta SO, puede agregar un método clean_<field_name> a su formulario para proporcionar un valor predeterminado. Desafortunadamente, la clase de formulario subyacente no está expuesta directamente, por lo que no puede subclasificarla y agregar ese método (ver editar). Dicho esto, los filtros tienen un campo de formulario subyacente, por lo que puede subclasificar el campo y anular su método clean() . Esto es un poco engorroso. p.ej,

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')
    ...

Un método más sencillo sería simplemente inspeccionar los datos entrantes y establecer un valor predeterminado.

def your_view(request):
    data = request.GET.copy()
    data.setdefault('some_field', 'some_value')

    f = YourFilterSet(data, queryset=YourModel.objects.all())
    ...

editar:
De hecho, puede proporcionar un formulario base al FilterSet.Meta , que luego se subclasifica internamente. Entonces, clean_<field name> es posible.

class MyForm(forms.Form):
    clean_some_field(self, value):
        ...

class MyFilterSet(FilterSet):
    class Meta:
        model = MyModel
        form = MyForm
        fields = ['some_field']

Yo uso FilterView. Anular get_filterset_kwargs funciona para mí:

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: cuando se usa, por ejemplo, la paginación, esto no se aplica (los datos b / c no son Ninguno). Algo como esto podría 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__ funcionó para mí. (Esto es con djangorestframework-filters , pero creo que es lo mismo que vainilla 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)

el método con __init__ no se recomienda y la solución alternativa documentada en el enlace no funcionó para mí ... https://django-filter.readthedocs.io/en/master/guide/tips.html #utilizando -valores-iniciales-como-valores-predeterminados
get_filterset_kwargs en el FilterView funcionó para mí.

no se recomienda el método con __init__

En general, no se recomienda proporcionar valores predeterminados de formulario / filtro, ya que es una mala práctica que puede tener efectos confusos / adversos. Implementar a través de __init__ o cualquier otro método está bien (dado que está de acuerdo con los efectos).

Yo uso FilterView. Anular get_filterset_kwargs funciona para mí:

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: cuando se usa, por ejemplo, la paginación, esto no se aplica (los datos b / c no son Ninguno). Algo como esto podría 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

¡Me has alegrado el día!

¿Fue útil esta página
0 / 5 - 0 calificaciones