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