Home > OS >  How to exclude empty values when querying a DRF endpoint URL [Django]
How to exclude empty values when querying a DRF endpoint URL [Django]

Time:10-13

Similar to an exclude filter that looks like this:

MyObject.objects.exclude(my_field="")

I know that I can modify the view to exclude the value in the queryset but that's not dynamic:

def get_queryset(self):
    return Client.objects.exclude(my_field="")

But I'm looking for a less static way of querying via URL. So something like this:

/api/object?my_field__isempty=False

CodePudding user response:

@Hashem's answer is good, but you could also use Q statements

from django.db.models import Q
# Q allows for complex queries with:
#   & (AND)
#   | (OR)
#   ^ (XOR)

# Exclude method
ModelName.objects.exclude(Q(field_name__isnull=True) | Q(field_name__exact=''))

# Filter Method with ~ (NOT)
ModelName.objects.filter(~Q(field_name__isnull=True) & ~Q(field_name__exact=''))

Just throwing out another option, and knowing about Q statements is really beneficial
Docs: https://docs.djangoproject.com/en/4.1/topics/db/queries/#complex-lookups-with-q


Edit

Here's an extra tidbit, you'll find this handy, you can use pointers and filter by a dictionary. The dictionary can be created dynamically

filterDict = {'my_field':''}
Client.objects.exclude(**filterDict)

# Client.objects.exclude(**filterDict) === Client.objects.exclude(my_field=='')

I'm not sure how you are doing Views, but if you have a "normal" one with the request object you you can fetch the GET parameters as a QueryDict:

def myview_with_dynamic_pointer(request):
  print(request.GET)

  # Should work
  Client.objects.filter(**request.GET)

  # will work
  Client.objects.filter(**{k:v for k,v in request.GET.items()})

def myview_with_dynamic_Q(request):
  print(request.GET)

  from django.db.models import Q
  dynamicquery = Q()
  
  for key, value in request.GET.items():
    dynamicquery = dynamicquery & Q({k:v})

    # Can also do OR:
    # dynamicquery = dynamicquery | Q({k:v})

  Client.objects.filter(dynamicquery)

If you are using class based views, it'll be more like:

class MyListView(ListView):
  model = MyModel

  def get_queryset(self):
    print(self.request.GET)
    return self.model.objects.filter(**self.request.GET)

It might be a good idea to look over the GET before shoving it right into a filter.. Safety wise

CodePudding user response:

If I got you correctly, If you need to exclude null values and empty strings

ModelName.objects.exclude(field_name__isnull=True).exclude(field_name__exact='')

Or you can use one of them, this equal to

NOT field_name='' AND field_name IS NOT NULL
  • Related