Karim N Gorjux
Karim N Gorjux

Reputation: 3033

Django Rest Framework filtering a many to many field

I would like to filter a serialization of a many to many field, but I don't need to create a view or a generic view as explained here because I need to use the data in another view.

The code is pretty simple. The locations in the model si a manytomany field.

class ServiceSerializer(serializers.ModelSerializer):
    locations = LocationSerializer(many=True)
    # [...]
    class Meta:
        model = Service

And the LocationSerializer is:

class LocationSerializer(serializers.ModelSerializer):
    # [...]
    class Meta:
        model = LocationAddress
        # [...]

I would like to get the locations serialized but only based on a boolean field in the model. active=True. How I can do that?

Upvotes: 0

Views: 1386

Answers (1)

Kevin Brown-Silva
Kevin Brown-Silva

Reputation: 41691

If you do not need the locations field within the serializer to be writable, you may benefit from just dropping to a SerializerMethodField. The other option is to dynamically remove the locations field when you are serializing an individual object, which will create inconsistent output if multiple objects are returned that do not have the same active flag.

To do it with a SerializerMethodField, you would just add a new method on the ServiceSerializer.

class ServiceSerializer(serializers.ModelSerializer):
    locations = SerializerMethodField("get_locations")
    # [...]
    class Meta:
        model = Service

    def get_locations(self, obj):
        if obj.active:
            return LocationSerializer(obj.locations.all(), many=True)

        return None

This will make locations read-only, which may not be what you are hoping for. It will also means that locations will return null when it's not active, and you may have been looking to remove the key entirely.

The other option is to just drop the key entirely in the to_representation (to_native in DRF 2.x) method.

class ServiceSerializer(serializers.ModelSerializer):
    locations = LocationSerializer(many=True)
    # [...]
    class Meta:
        model = Service

    def to_representation(self, obj):
        rep = super(ServiceSerializer, self).to_representation(obj)

        del rep["locations"]

        return rep

Upvotes: 2

Related Questions