How to apply a django filter only if both field have a value

I have a simple django filters interface like this enter image description here

This is how I wrote the filters, but of course it is wrong because it adds the filter even when i choose only one field. Also I'm sharing the same FilterSet for both.

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))

I need to ignore if only one of the fields have a value and to apply filter() to the queryset only once and only if both have a value.

How would you do that? Now even if I would use two separate filters, the result would not be the one I'd like. I think I could just do it in the viewSet, but it's not what I want because I want to do it in the Filter.

You can follow these steps to get the desired result.

  1. combine tipo_oid and identification into a single filter then check if both have values
  2. Use self.data to access both filter values within the method

Also better to create a separate class for that.

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
Вернуться на верх