Django-filter: Filtrage par défaut lorsqu'aucun paramètre de filtre n'est passé dans request.GET

Créé le 6 nov. 2015  ·  6Commentaires  ·  Source: carltongibson/django-filter

Chers tous,

Existe-t-il une option pour définir le champ de filtre par défaut et la valeur à utiliser si aucun paramètre que je définis dans les Meta.fields n'a été trouvé dans l'objet de demande ?

S'il n'y a pas une telle option, que suggéreriez-vous comme meilleure façon de le faire ?

Salutations,
Andrius

Commentaire le plus utile

J'utilise un FilterView. Remplacer get_filterset_kwargs fonctionne pour moi :

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

Modifier : lors de l'utilisation, par exemple, de la pagination, cela n'est pas appliqué (les données b/c ne sont pas None). Quelque chose comme ceci pourrait fonctionner:

        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

Tous les 6 commentaires

Salut @andrius-senulis. django-filter est construit au-dessus des formulaires django classiques, donc cette question peut être résumée en "Comment fournir des valeurs de champ par défaut pour les formulaires liés ?" Par cette réponse SO, vous pouvez ajouter une méthode clean_<field_name> à votre formulaire afin de fournir une valeur par défaut. Malheureusement, la classe de formulaire sous-jacente n'est pas directement exposée, vous ne pouvez donc pas la sous-classer et ajouter cette méthode (voir modifier). Cela dit, les filtres ont un champ de formulaire sous-jacent, vous pouvez donc sous-classer le champ et remplacer sa méthode clean() . C'est un peu encombrant. par exemple,

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

Une méthode plus simple serait de simplement inspecter les données entrantes et de définir une valeur par défaut.

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

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

Éditer:
Vous êtes en fait en mesure de fournir une forme de base au FilterSet.Meta , qui est ensuite sous- clean_<field name> est possible.

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

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

J'utilise un FilterView. Remplacer get_filterset_kwargs fonctionne pour moi :

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

Modifier : lors de l'utilisation, par exemple, de la pagination, cela n'est pas appliqué (les données b/c ne sont pas None). Quelque chose comme ceci pourrait fonctionner:

        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

L'utilisation de __init__ fonctionné pour moi. (C'est avec djangorestframework-filters , mais je pense que c'est la même chose que la vanille 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)

la méthode avec __init__ n'est pas recommandée et la solution de contournement documentée dans le lien n'a pas fonctionné pour moi ... https://django-filter.readthedocs.io/en/master/guide/tips.html # using-initial-values-as-defaults
get_filterset_kwargs dans le FilterView fonctionné pour moi.

la méthode avec __init__ n'est pas recommandée

Fournir des valeurs de formulaire/filtre par défaut en général n'est pas recommandé car c'est une mauvaise pratique qui peut avoir des effets déroutants/négatifs. L'implémentation via __init__ ou toute autre méthode convient (étant donné que vous êtes d'accord avec les effets).

J'utilise un FilterView. Remplacer get_filterset_kwargs fonctionne pour moi :

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

Modifier : lors de l'utilisation, par exemple, de la pagination, cela n'est pas appliqué (les données b/c ne sont pas None). Quelque chose comme ceci pourrait fonctionner:

        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

Tu as fait ma journée !

Cette page vous a été utile?
0 / 5 - 0 notes