When using django-filters with django rest framework, the default query filtering form will add all query params for all fields, and the empty fields end up as empty strings passed to the backend. Empty strings are not None, so the status = self.request.query_params.get('status', None) will still add the empty string to the variable, and this will make its way to the queryset.filter function. This is very bad when the field being filtered is not a string.
So my question is am I doing something wrong? Is there a way to check for empty string params? I'm not sure if I'm even doing filtering right (I'm probably filtering twice for no reason, but I wanted django-filters in there because of the built in integration with django-rest-frameworks browseable API.
My workaround is the ternary operator checking for the empty string after the call to query_params.get
Below is my view code for the API:
class JobList(generics.ListCreateAPIView):
serializer_class = JobCreateSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
filter_backends = (filters.OrderingFilter, DjangoFilterBackend)
filterset_fields = ('status', 'success', 'worker_id', 'owner', 'job_type')
ordering_fields = ('priority', 'submitted', 'assigned', 'completed')
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
def get(self, request, format=None):
# IMPORTANT: use self.get_queryset() any place you want filtering to be enabled
# for built in filtering or ordering you must call self.filter_queryset
jobs = self.filter_queryset(self.get_queryset())
serializer = JobSerializer(jobs, context={'request': request}, many=True)
return Response(serializer.data)
def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
queryset = Job.objects.all()
status = self.request.query_params.get('status', None)
status = status if not status == '' else None
success = self.request.query_params.get('success', None)
success = success if not success == '' else None
worker_id = self.request.query_params.get('worker_id', None)
worker_id = worker_id if not worker_id == '' else None
owner_id = self.request.query_params.get('owner', None)
owner_id = owner_id if not owner_id == '' else None
job_type = self.request.query_params.get('job_type', None)
job_type = job_type if not job_type == '' else None
if status is not None:
queryset = queryset.filter(status=status)
if success is not None:
queryset = queryset.filter(success=success)
if worker_id is not None:
queryset = queryset.filter(worker_id=worker_id)
if owner_id is not None:
queryset = queryset.filter(owner=owner_id)
if job_type is not None:
queryset = queryset.filter(job_type=job_type)
return queryset