Django-filter: Pemfilteran default ketika tidak ada parameter filter yang diteruskan dalam request.GET

Dibuat pada 6 Nov 2015  ·  6Komentar  ·  Sumber: carltongibson/django-filter

Halo semuanya,

Apakah ada opsi untuk menyetel bidang filter default dan nilai yang akan digunakan jika tidak ada parameter yang saya tentukan di Meta.fields yang ditemukan di objek permintaan?

Jika tidak ada pilihan seperti itu, apa yang akan Anda sarankan sebagai cara terbaik untuk melakukannya?

Salam,
Andrius

Komentar yang paling membantu

Saya menggunakan FilterView. Mengganti get_filterset_kwargs berfungsi untuk saya:

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

Sunting: Saat menggunakan misalnya pagination, ini tidak diterapkan (data b/c bukan None). Sesuatu seperti ini mungkin berhasil:

        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

Semua 6 komentar

Hai @andrius-senulis. Django-filter dibangun di atas formulir Django biasa, jadi pertanyaan ini dapat diringkas menjadi "Bagaimana cara memberikan nilai bidang default untuk formulir terikat?" Per jawaban SO ini , Anda dapat menambahkan metode clean_<field_name> ke formulir Anda untuk memberikan nilai default. Sayangnya, kelas formulir yang mendasarinya tidak diekspos secara langsung, jadi Anda tidak dapat mensubklasifikasikannya dan menambahkan metode itu (lihat edit). Karena itu, filter memiliki bidang formulir yang mendasarinya, sehingga Anda dapat mensubklasifikasikan bidang tersebut dan mengganti metode clean() . Ini sedikit merepotkan. misalnya,

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

Metode yang lebih mudah adalah dengan hanya memeriksa data yang masuk dan menetapkan nilai default.

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

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

edit:
Anda sebenarnya dapat memberikan formulir dasar ke FilterSet.Meta , yang kemudian disubklasifikasikan secara internal. Jadi, clean_<field name> dimungkinkan.

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

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

Saya menggunakan FilterView. Mengganti get_filterset_kwargs berfungsi untuk saya:

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

Sunting: Saat menggunakan misalnya pagination, ini tidak diterapkan (data b/c bukan None). Sesuatu seperti ini mungkin berhasil:

        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

Menggunakan __init__ berhasil untuk saya. (Ini dengan djangorestframework-filters , tapi saya pikir sama dengan vanilla 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)

metode dengan __init__ tidak disarankan dan solusi yang didokumentasikan dalam tautan tidak berfungsi untuk saya ... https://django-filter.readthedocs.io/en/master/guide/tips.html #menggunakan -initial -values-as-defaults
get_filterset_kwargs di FilterView bekerja untuk saya.

metode dengan __init__ tidak disarankan

Memberikan nilai formulir/filter default secara umum tidak disarankan karena merupakan praktik buruk yang dapat menimbulkan efek membingungkan/merugikan. Menerapkan melalui __init__ atau metode lain apa pun tidak masalah (mengingat Anda setuju dengan efeknya).

Saya menggunakan FilterView. Mengganti get_filterset_kwargs berfungsi untuk saya:

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

Sunting: Saat menggunakan misalnya pagination, ini tidak diterapkan (data b/c bukan None). Sesuatu seperti ini mungkin berhasil:

        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

Anda membuat hari saya!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat