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
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!
Komentar yang paling membantu
Saya menggunakan FilterView. Mengganti get_filterset_kwargs berfungsi untuk saya:
Sunting: Saat menggunakan misalnya pagination, ini tidak diterapkan (data b/c bukan None). Sesuatu seperti ini mungkin berhasil: