#python #django #forms #django-queryset
#python #джанго #формы #django-набор запросов #django
Вопрос:
У меня есть этот механизм фильтрации, который работает, однако он не очень элегантный. Должен быть лучший способ написать это. Любые рекомендации были бы с благодарностью приняты.
Пользователь может выбирать из нескольких фильтров для фильтрации списка:
forms.py
class FilterForm(forms.Form):
def __init__(self, *args, **kwargs):
super(FilterForm, self).__init__(*args, **kwargs)
self.fields['group'].widget.attrs["onchange"] = mark_safe('this.form.submit();')
self.fields['location'].widget.attrs["onchange"] = mark_safe('this.form.submit();')
self.fields['host'].widget.attrs["onchange"] = mark_safe('this.form.submit();')
self.fields['exchange'].widget.attrs["onchange"] = mark_safe('this.form.submit();')
group = forms.ModelChoiceField(queryset=Group.objects.all().order_by('name'), )
location = forms.ModelChoiceField(queryset=Location.objects.all().order_by('name'), )
host = forms.ModelChoiceField(queryset=Host.objects.all().order_by('name'), )
exchange = forms.ModelChoiceField(queryset=Exchange.objects.all().order_by('name'), )
views.py
initial = {}
#check for filtering
if 'group' in request.POST:
if request.POST['group']:
initial['group'] = request.POST['group']
obj = Group.objects.get(pk=request.POST['group'])
selectForm.fields['job'].queryset = selectForm.fields['job'].queryset.filter(group=obj)
if 'host' in request.POST:
if request.POST['host']:
initial['host'] = request.POST['host']
obj = Host.objects.get(pk=request.POST['host'])
selectForm.fields['job'].queryset = selectForm.fields['job'].queryset.filter(host=obj)
if 'location' in request.POST:
if request.POST['location']:
initial['location'] = request.POST['location']
obj = Location.objects.get(pk=request.POST['location'])
selectForm.fields['job'].queryset = selectForm.fields['job'].queryset.filter(colo=obj)
if 'exchange' in request.POST:
if request.POST['exchange']:
initial['exchange'] = request.POST['exchange']
obj = Exchange.objects.get(pk=request.POST['exchange'])
selectForm.fields['job'].queryset = selectForm.fields['job'].queryset.filter(exchange=obj)
filterForm.initial = initial
Ответ №1:
initial = dict(request.POST)
# The dictionary key is the field name retrieved from the POST request
# The first list item is the model to query
# The second list item is the "jobs" field to query
dict_models = {'group': [Group, 'group']],
'host': [Host, 'host'],
'location': [Location, 'colo'],
'exchange': [Exchange, 'exchange'],
}
#check for filtering
for k, v in dict_models.items():
if initial.get(k, None):
obj = v[0].objects.get(pk=initial[k])
kwargs = v[1]
for key in kwargs.keys:
kwargs[key] = obj
selectForm.fields['job'].queryset = selectForm.fields['job'].queryset.filter(**kwargs)
filterForm.initial = initial
Комментарии:
1. я не женат на fKey colo. Я переименовал его в своей модели в location. Спасибо!
Ответ №2:
вы могли бы попробовать что-то вроде (непроверенное)
options = {'group':Group, 'host':Host, 'location':Location, 'exchange':Exchange}
for key, modelclass in options.items():
value = request.POST.get(key, None)
if value:
initial[key] = value
obj = modelclass.objects.get(pk=value)
filter = {}
filter[key] = obj
selectForm.fields['job'].queryset = selectForm.fields['job'].queryset.filter(**filter)
Комментарии:
1. Я не думаю, что это сработает для поля location. Для фильтра требуется filter(colo=obj), а не location=obj
2. dam не заметил, что ‘colo’ отличается.
3. Такое странное название для поля fkey местоположения
4. Это сработало отлично (после того, как я изменил FKey на ‘location’). Спасибо!!