2

I am PATCHing a model using DRF, and the call is, for some reason, wiping a ManyToMany field. Why is this?

I have a Feature model:

class Feature(CommonInfo):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=50)
    parent = models.ForeignKey("Feature", blank=True, null=True, related_name='children')
    tags = models.ManyToManyField("Tag")
    level = models.IntegerField()
    box_image = ImageField()
    background_image = ImageField()

...and a serializer:

class FeatureSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.ReadOnlyField(source='user.username') 
    children = serializers.HyperlinkedRelatedField(read_only=True, view_name='feature-detail', many=True)
    level = serializers.ReadOnlyField()

    def get_fields(self, *args, **kwargs):
        user = self.context['request'].user
        fields = super(FeatureSerializer, self).get_fields(*args, **kwargs)
        fields['parent'].queryset = fields['parent'].queryset.filter(user=user)
        return fields

    class Meta:
        model = Feature

...and a viewset:

class FeatureViewSet(viewsets.ModelViewSet):
    serializer_class = FeatureSerializer

    def get_queryset(self):
        return self.request.user.feature_set.order_by('level', 'name')

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

This gives an output for GET /api/features/5/:

{
    "url": "http://localhost:8001/api/features/5/", 
    "user": "andrew", 
    "children": [], 
    "level": 1, 
    "created_at": "2015-02-03T15:11:00.191909Z", 
    "modified_at": "2015-02-03T15:20:02.038402Z", 
    "name": "My Astrantia major 'Claret' plant", 
    "box_image": "http://localhost:8001/media/Common_Knapweed13315723294f5e2e6906593_PF07bKi.jpg", 
    "background_image": null, 
    "parent": "http://localhost:8001/api/features/1/", 
    "tags": [
        "http://localhost:8001/api/tags/256/"
    ]
}

Suppose I want to run a PATCH call to update name:

import requests
r = requests.patch("http://localhost:8001/api/features/5/", 
                data={'name':'New name'}, 
                auth=('user', 'password'))
r.json()

This successfully updates the object, but the result also wipes the tags from the object:

{
    "url": "http://localhost:8001/api/features/5/", 
    "user": "andrew", 
    "children": [], 
    "level": 1, 
    "created_at": "2015-02-03T15:11:00.191909Z", 
    "modified_at": "2015-02-03T16:12:48.055527Z", 
    "name": "New name", 
    "box_image": "http://localhost:8001/media/Common_Knapweed13315723294f5e2e6906593_PF07bKi.jpg", 
    "background_image": null, 
    "parent": "http://localhost:8001/api/features/1/", 
    "tags": []
}
awidgery
  • 1,896
  • 1
  • 22
  • 36

0 Answers0