How to apply a django filter only if both field have a value
I have a simple django filters interface like this
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.
- combine tipo_oid and identification into a single filter then check if both have values
- 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