kramer65
kramer65

Reputation: 53913

Why can't I filter on one new field in Django Rest Framework?

So I'm editing an existing codebase using Django Rest Framework, and I added a new field to a model:

class MyModel(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=150, null=True)
    the_new_field = models.IntegerField(null=True, default=None)

I've got a serializer, which is fairly basic:

class MyModelSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyModel
        fields = (
            'id',
            'name',
        )

So to the serializer I simply added the new field:

class MyModelSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyModel
        fields = (
            'id',
            'name',
            'the_new_field',
        )

I can call the endpoint using name using ?name=awesomename, which actually filters based on awesomename, but when I call the endpoint using ?the_new_field=123456 it simply returns all the records in the database.

What am I missing here? How can I make it filter based on this new field?

Upvotes: 0

Views: 441

Answers (1)

Bernardo Duarte
Bernardo Duarte

Reputation: 4264

You need something like django-filter. It will handle filtering for you, and it's simple to write as a serializer.

Here is how you can integrate with DRF. DRF also recommends using it in their docs. Or follow along:

Install django-filter with pip.

pip install django-filter

Then add django_filters to your INSTALLED_APPS.

INSTALLED_APPS = [
    ...
    'rest_framework',
    'django_filters',
]

If you want to use the django-filter backend by default, add it to the DEFAULT_FILTER_BACKENDS setting.

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
        ...
    ),
}

Or add the filter backend to an individual View or ViewSet.

from django_filters.rest_framework import DjangoFilterBackend

class YourView(generics.ListAPIView):
    ...
    filter_backends = [DjangoFilterBackend]

Then add the filter to your current view as follows:

class MyModelList(generics.ListAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['name', 'the_new_field']

Upvotes: 2

Related Questions