أعزائي،
هل هناك خيار لتعيين حقل المرشح الافتراضي والقيمة لاستخدامهما إذا لم يتم العثور على معلمة أحددها في Meta.fields في كائن الطلب؟
إذا لم يكن هناك مثل هذا الخيار ، فماذا تقترح كأفضل طريقة للقيام بذلك؟
يعتبر،
أندريوس
مرحبًا @ andrius-senulis. تم إنشاء مرشح django أعلى نماذج 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). قد ينجح شيء مثل هذا:
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 # استخدام-القيم الأولية-كإعدادات افتراضية
get_filterset_kwargs
في FilterView
بالنسبة لي.
الطريقة مع
__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). قد ينجح شيء مثل هذا:
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
انت صنعت يومي!
التعليق الأكثر فائدة
أنا استخدم FilterView. يعمل تجاوز get_filterset_kwargs بالنسبة لي:
تحرير: عند استخدام ترقيم الصفحات على سبيل المثال ، لا يتم تطبيق ذلك (لا يتم تطبيق بيانات b / c). قد ينجح شيء مثل هذا: