Django REST - 用于替换嵌套对象的PATCH

时间:2016-03-23 17:49:14

标签: python django django-rest-framework

我尝试使用PATCH请求替换另一个测试对象。对于我的实验,我使用Postman。我发送带参数user_status和值的PATCH请求:

  

{" id":1," status_type":{" id":2," name":" new_status_type_name& #34;},   " name":" new_status_name"}

我写了更新我的ResultSerializer的更新方法,但它没有用。现在我正在调试它,我发现变量validated_data并不包含我的新user_status。 user_status是一个空的OrderedDict:

ipdb> validated_data['user_status']
OrderedDict()

我检查了我的请求,我发现user_status是一个包含一个元素的列表 - 字符串。

ipdb> self.context['request'].data
<QueryDict: {'user_status': ['{"id": 1, "status_type": {"id": 2, "name": "new_status_type_name"}, "name": "new_status_name"}']}>

如何互相替换嵌套对象?谢谢你的帮助。

我有下一个模特:

class UserStatus(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(unique=True, max_length=255)
    status_type = models.ForeignKey('StatusType', blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user_status'

    def __str__(self):
        return self.name


class StatusType(models.Model):
    id = models.SmallIntegerField(primary_key=True)
    name = models.CharField(unique=True, max_length=256)

    class Meta:
        managed = False
        db_table = 'status_type'

    def __unicode__(self):
        return self.name

class Result(models.Model):
    id = models.BigIntegerField(primary_key=True)
    user_status = models.ForeignKey('UserStatus', blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'result'

串行器:

class UserStatusSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField()
    name = serializers.CharField()
    status_type = StatusTypeSerializer()

    class Meta:
        model = app.models.UserStatus


class StatusTypeSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField()
    name = serializers.CharField()

    class Meta:
        model = app.models.StatusType


class ResultSerializer(serializers.ModelSerializer):
    user_status = UserStatusSerializer(many=False)

    def update(self, instance, validated_data, *args, **kwargs):
        import ipdb; ipdb.set_trace()
        instance.user_status = validated_data.get('user_status', instance.user_status)
        instance.save()
        return instance

    class Meta:
        model = app.models.Result

查看:

class StatusTypeViewSet(viewsets.ModelViewSet):
    queryset = app.models.StatusType.objects.all()
    serializer_class = app.serializers.StatusTypeSerializer


class UserStatusViewSet(viewsets.ModelViewSet):
    queryset = app.models.UserStatus.objects.all()
    serializer_class = app.serializers.UserStatusSerializer


class ResultViewSet(viewsets.ModelViewSet):
    queryset = app.models.Result.objects.all()
    serializer_class = app.serializers.ResultSerializer

1 个答案:

答案 0 :(得分:0)

阅读本文后Please. Don't Patch Like An Idiot. 我知道我应该使用列表进行修补,但是Django REST并不想使用list,只能使用对象。好的,现在我使用下一个dict进行路径化:

{"op": "update", "field": "user_status_id", "new_value": 2}

以及发送此列表的下一个代码:

import json
import requests

payload = json.dumps({"op": "update", "field": "user_status_id", "new_value": 2})
headers = {'content-type': "application/json"}
response = requests.patch(url, data=payload, headers=headers)

然后我更改了serializers.py和views.py。我将只显示主代码而不检查和其他stufs :)。 views.py(添加方法perform_update):

class ResultViewSet(viewsets.ModelViewSet):
    queryset = app.models.Result.objects.all()
    serializer_class = app.serializers.ResultSerializer

    def perform_update(self, serializer):
        new_value = self.request.data.get('new_value')
        user_status_ins = app.models.UserStatus.objects.get(id=new_value)
        serializer.save(user_status=user_status_ins)

serializers.py(添加方法update):

class ResultSerializer(serializers.ModelSerializer):
    user_status = UserStatusSerializer(many=False)

    def update(self, instance, validated_data, *args, **kwargs):
        for field in validated_data.keys():
            setattr(instance, field, validated_data.get(field))
        instance.save()
        return instance

    class Meta:
        model = app.models.Result

如果您找到了更好的解决方案,请告诉我。