Как применить фильтр django только в том случае, если оба поля имеют значение

У меня есть простой интерфейс фильтров django, например, такой enter image description here

Вот как я написал фильтры, но, конечно, это неправильно, потому что он добавляет фильтр, даже когда я выбираю только одно поле. Также я использую один и тот же 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.

Вы можете выполнить следующие шаги, чтобы получить желаемый результат.

  1. объедините tipo_oid и identification в один фильтр, затем проверьте, есть ли у обоих значения
  2. .
  3. Используйте 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>
Вернуться на верх