Django-filter: request.GETでフィルターパラメーターが渡されなかった場合のデフォルトのフィルタリング

作成日 2015年11月06日  ·  6コメント  ·  ソース: carltongibson/django-filter

親愛なるみんな、

Meta.fieldsで定義したパラメーターがリクエストオブジェクトで見つからなかった場合に使用するデフォルトのフィルターフィールドと値を設定するオプションはありますか?

そのようなオプションがない場合、それを行うための最良の方法として何を提案しますか?

よろしく、
アンドリウス

最も参考になるコメント

FilterViewを使用しています。 get_filterset_kwargsをオーバーライドすると、次のように機能します。

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

編集:たとえばページ付けを使用する場合、これは適用されません(b / cデータはNoneではありません)。 このようなものが機能する可能性があります:

        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

全てのコメント6件

こんにちは@ andrius-senulis。 django-filterは通常のdjangoフォームの上に構築されているため、この質問は「バインドされたフォームにデフォルトのフィールド値を提供するにはどうすればよいですか?」に要約できます。 このSOの回答に従って、デフォルト値を提供するためにフォームにclean_<field_name>メソッドを追加できます。 残念ながら、基になるフォームクラスは直接公開されていないため、サブクラス化してそのメソッドを追加することはできません(編集を参照)。 とはいえ、フィルターには基になるフォームフィールドがあるため、フィールドをサブクラス化して、そのclean()メソッドをオーバーライドできます。 これは少し面倒です。 例えば、

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

より簡単な方法は、受信データを検査してデフォルト値を設定することです。

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

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

編集:
実際には、基本フォームをFilterSet.Metaに提供できます。これは、内部でサブクラス化されます。 したがって、 clean_<field name>が可能です。

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

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

FilterViewを使用しています。 get_filterset_kwargsをオーバーライドすると、次のように機能します。

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

編集:たとえばページ付けを使用する場合、これは適用されません(b / cデータはNoneではありません)。 このようなものが機能する可能性があります:

        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

__init__を使用することは私のために働いた。 (これはdjangorestframework-filtersですが、バニラ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)

__init__を使用する方法は推奨されておらず、リンクに記載されている回避策は機能しませんでした... https://django-filter.readthedocs.io/en/master/guide/tips.html #using -initial-values-as-defaults
get_filterset_kwargsFilterView私のために働きました。

__init__する方法はお勧めしません

一般に、デフォルトのフォーム/フィルター値を提供することは、混乱/悪影響をもたらす可能性がある悪い習慣であるため、お勧めできません。 __init__または他の方法で実装しても問題ありません(効果に問題がない場合)。

FilterViewを使用しています。 get_filterset_kwargsをオーバーライドすると、次のように機能します。

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

編集:たとえばページ付けを使用する場合、これは適用されません(b / cデータはNoneではありません)。 このようなものが機能する可能性があります:

        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

あなたは私の日を作りました!

このページは役に立ちましたか?
0 / 5 - 0 評価