Search code examples
djangodjango-rest-frameworkdjango-filter

Django Rest Framework - Default filter if not sent


I have a Property model which has a lot of fields, but I am interested in the is_shared one

class Property(models.Model):
    ....
    is_shared = models.BooleanField(blank=True, null=True)

I also have a pretty standard, out of the box, viewset, serializer and a filter for this model.

I want my filter to work so if the is_shared query parameter is NOT sent, it will return properties with is_shared=False

For that, I have the following filter method:

class PropertyFilter(dj_filters.FilterSet):
    is_shared = dj_filters.BooleanFilter(method='filter_by_is_shared')

    @staticmethod
    def filter_by_is_shared(queryset, name, value):
        return queryset if value else queryset.filter(is_shared=False)

This works well if True or False are sent in the request, but if is_shared isn't sent at all it won't work.

I've tried adding this to the serializer without luck.

class PropertySerializer(serializers.ModelSerializer):

    class Meta:
        model = Property
        fields = ['is_shared']
        extra_kwargs = {
            'is_shared': {'default': False}
        }

I've also updated the request before the filter_queryset method in the ViewSet to trick the filter, but it doesn't get called anyway:

request.data.update({"is_shared": self.request.GET.get('is_shared')})

How can I achieve so if the is_shared query parameter is not sent, I treat it as if it was false?


Solution

  • I think you need to update request.GET instead of request.data. The only things that prevents you doing it is that request.GET is a QueryDict object which is immutable.

    This hack should work but I'm not sure if it can cause any unexpected consequences:

    request.GET._mutable = True
    request.GET.update({'is_shared': request.GET.get('is_shared', False)})