Как применить фильтр django только в том случае, если оба поля имеют значение
У меня есть простой интерфейс фильтров django, например, такой
Вот как я написал фильтры, но, конечно, это неправильно, потому что он добавляет фильтр, даже когда я выбираю только одно поле. Также я использую один и тот же FilterSet для обоих полей.
tipo_oid = filters.ChoiceFilter(label='Tipo Identificativo',
choices = TipoOid.objects.all().values_list("id","denominazione").exclude(annullato=True).filter(id__in=[2,3,12,22,9,49]).order_by('denominazione'),
method='filter_ide')
identificativo = filters.CharFilter(label='Identificativo', method='filter_ide')
def filter_ide(self, queryset, name, value):
if name == 'tipo_oid':
filtroPfIdInPfIde = PfIdentificativi.objects.filter(pf_id=OuterRef('id')).filter(tipo_oid=value).exclude(annullato=True)
queryset = queryset.filter(Exists(filtroPfIdInPfIde))
if name =='identificativo':
filtroIdeInPfIde = PfIdentificativi.objects.filter(pf_id=OuterRef('id')).filter(identificativo=value).exclude(annullato=True)
queryset = queryset.filter(Exists(filtroIdeInPfIde))
Мне нужно игнорировать, если только одно из полей имеет значение, и применять filter() к набору запросов только один раз и только в том случае, если оба поля имеют значение.
Как бы вы это сделали? Даже если бы я использовал два отдельных фильтра, результат был бы не таким, как мне хотелось бы. Думаю, я мог бы просто сделать это в viewSet, но это не то, что я хочу, потому что я хочу сделать это в Filter.
Вы можете выполнить следующие шаги, чтобы получить желаемый результат.
- объедините tipo_oid и identification в один фильтр, затем проверьте, есть ли у обоих значения .
- Используйте self.data для доступа к значениям обоих фильтров внутри метода
Также лучше создать отдельный класс для этого.
class MyFilterSet(filters.FilterSet):
tipo_oid = filters.ChoiceFilter(
label='Tipo Identificativo',
choices=TipoOid.objects.all()
.values_list("id", "denominazione")
.exclude(annullato=True)
.filter(id__in=[2, 3, 12, 22, 9, 49])
.order_by('denominazione')
)
identificativo = filters.CharFilter(label='Identificativo')
def filter_queryset(self, queryset):
tipo_oid = self.data.get('tipo_oid')
identificativo = self.data.get('identificativo')
if tipo_oid and identificativo:
filtroPfIdInPfIde = PfIdentificativi.objects.filter(
pf_id=OuterRef('id'), tipo_oid=tipo_oid, identificativo=identificativo
).exclude(annullato=True)
queryset = queryset.filter(Exists(filtroPfIdInPfIde))
return queryset
используйте django form.
# forms.py
from django import forms
class ChoiceForm(forms.Form):
tipo_oid = forms.ModelChoiceField(
label='Tipo Identificativo',
choices=TipoOid.objects.all().exclude(annullato=True).filter(id__in=[2,3,12,22,9,49]).order_by('denominazione'),
required=True,
)
identificativo = forms.ModelChoiceField(
label='Identificativo',
choices=PfIdentificativi.objects.all().exclude(annullato=True).filter(id__in=[2,3,12,22,9,49]).order_by('denominazione'),
required=True,
)
# views.py
from path.to.forms.py import ChoiceForm
...
if reqeust.method == 'POST':
form = ChoiceForm(reqeust.POST)
if form.is_valid():
# valid action
else:
# invalid action
if request.method == 'GET':
form = ChoiceForm()
context['form'] = form
return render(request, '{template}', context)
# template
<body>
...
{# rendering form object #}
{{ form }}
...
</body>