Django-filter: Standardfilterung, wenn keine Filterparameter in request.GET . übergeben wurden

Erstellt am 6. Nov. 2015  ·  6Kommentare  ·  Quelle: carltongibson/django-filter

Hallo zusammen,

Gibt es eine Option, um das Standardfilterfeld und den zu verwendenden Wert festzulegen, wenn im Anforderungsobjekt kein Parameter gefunden wurde, den ich in den Meta.fields definiere?

Wenn es eine solche Option nicht gibt, was würden Sie als den besten Weg vorschlagen?

Grüße,
Andrius

Hilfreichster Kommentar

Ich verwende eine FilterView. Das Überschreiben von get_filterset_kwargs funktioniert bei mir:

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

Bearbeiten: Bei Verwendung von zB Paginierung wird dies nicht angewendet (b/c-Daten sind nicht None). So etwas könnte funktionieren:

        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

Alle 6 Kommentare

Hallo @andrius-senulis. django-filter baut auf regulären django-Formularen auf, daher kann diese Frage in "Wie stelle ich Standardfeldwerte für gebundene Formulare bereit?" zusammengefasst werden. Gemäß dieser SO- Antwort können Sie Ihrem Formular eine clean_<field_name> Methode hinzufügen, um einen Standardwert bereitzustellen. Leider wird die zugrunde liegende Formularklasse nicht direkt verfügbar gemacht, sodass Sie sie nicht unterklassen und diese Methode hinzufügen können (siehe Bearbeiten). Filter haben jedoch ein zugrunde liegendes Formularfeld, sodass Sie eine Unterklasse des Felds erstellen und seine Methode clean() überschreiben können. Dies ist ein wenig umständlich. z.B,

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

Eine einfachere Methode wäre, einfach die eingehenden Daten zu überprüfen und einen Standardwert festzulegen.

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

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

bearbeiten:
Sie sind tatsächlich in der Lage, FilterSet.Meta eine Basisform bereitzustellen, die dann intern in Unterklassen unterteilt wird. Also, clean_<field name> ist möglich.

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

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

Ich verwende eine FilterView. Das Überschreiben von get_filterset_kwargs funktioniert bei mir:

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

Bearbeiten: Bei Verwendung von zB Paginierung wird dies nicht angewendet (b/c-Daten sind nicht None). So etwas könnte funktionieren:

        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

Die Verwendung von __init__ hat bei mir funktioniert. (Dies ist mit djangorestframework-filters , aber ich denke, es ist dasselbe wie 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)

die Methode mit __init__ wird nicht empfohlen und der im Link dokumentierte Workaround hat bei mir nicht funktioniert ... https://django-filter.readthedocs.io/en/master/guide/tips.html #using -initial-values-as-defaults
get_filterset_kwargs im FilterView hat bei mir funktioniert.

die Methode mit __init__ wird nicht empfohlen

Die Bereitstellung von Standardformular-/Filterwerten im Allgemeinen wird nicht empfohlen, da dies eine schlechte Vorgehensweise ist, die verwirrende/nachteilige Auswirkungen haben kann. Die Implementierung über __init__ oder eine andere Methode ist in Ordnung (vorausgesetzt, Sie sind mit den Effekten einverstanden).

Ich verwende eine FilterView. Das Überschreiben von get_filterset_kwargs funktioniert bei mir:

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

Bearbeiten: Bei Verwendung von zB Paginierung wird dies nicht angewendet (b/c-Daten sind nicht None). So etwas könnte funktionieren:

        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

Du hast meinen Tag gerettet!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen