使用来自JSON的数据使用DRF Serializer更新对象

时间:2018-05-03 10:37:08

标签: django serialization django-rest-framework

我使用来自多个对象的数据获得JSON响应,通过序列化程序运行所有内容并调用serializer.save()来创建新对象但不更新现有对象。

视图

data = JSONParser().parse(request)
serializer = CellCESaveSerializer(data=data, many = True, context = {'descriptoridlist' : descriptoridlist}, partial=True)
if serializer.is_valid():
    serializer.save()
    return JsonResponse(serializer.data, safe=False)

序列化程序

class StringArrayField(ListField):
    """
    String representation of an array field.
    """
    def to_representation(self, obj):
        obj = super().to_representation(obj)
        # convert list to string
        return ",".join([str(element) for element in obj])

    def to_internal_value(self, data):
        data = data.rstrip(",")  # Needed because of JSON response
        data = data.split(",")  # Split string to list
        data = [int(i) for i in data] # convert str to int
        did = self.context['descriptoridlist']
        x = (did,data)   # Create Array
        return super().to_internal_value(x)

class CellCESaveSerializer(serializers.ModelSerializer):
    row = serializers.SlugRelatedField(slug_field="name",queryset=Descriptor.objects.all() ) # foreignkey mit namen
    val = StringArrayField()   

    class Meta:
        model = CellCE
        fields = ('row','val')

如何在不创建新对象的情况下更新现有对象?

编辑1:

添加@neverwalkaloner更改后,我意识到我需要使用ListSerializer来更新多个对象。我在DRF documentation的帮助下调整了我的代码。 (我将序列化程序更改为ListSerializer,添加了id字段和更新方法。)

串行器:

class CellCESaveSerializer(serializers.ListSerializer):
    row = serializers.SlugRelatedField(slug_field="name",queryset=Descriptor.objects.all()) # foreignkey mit namen
    val = StringArrayField()
    id = serializers.IntegerField()


    class Meta:
        model = CellCE
        fields = ('row','val')

    def update(self, instance, validated_data):
        CellCE_mapping = {CellCE.id: CellCE for CellCE in instance}
        data_mapping = {item['id']: item for item in validated_data}

        # Perform creations and updates.
        ret = []
        for CellCE_id, data in data_mapping.items():
            CellCE = CellCE_mapping.get(CellCE_id, None)
            if CellCE is None:
                ret.append(self.child.create(data))
            else:
                ret.append(self.child.update(CellCE, data))

        # Perform deletions.
        for CellCE_id, CellCE in CellCE_mapping.items():
            if CellCE_id not in data_mapping:
                CellCE.delete()

        return ret

我收到错误:

AssertionError: `child` is a required argument.

我缺少什么?

2 个答案:

答案 0 :(得分:0)

序列化程序的save()方法检查序列化程序的self.instance是否为空。如果self.instance为空save(),则会调用create()方法,否则会调用update()方法。

因此要使用序列化程序更新实例,您需要传递它的第一个参数更新对象:

obj = CellCE.objects.get(id='some_id') # Object wich will be updated
serializer = CellCESaveSerializer(obj, data=data, many = True, context = {'descriptoridlist' : descriptoridlist}, partial=True)
if serializer.is_valid():
    serializer.save()
    return JsonResponse(serializer.data, safe=False)

答案 1 :(得分:0)

不需要使用ListSerializer,因为当你传递“many = True”时,它也使用ListSerializer类。如果要更新一次对象,请包含“id”字段并在输入数据中传递其值。

相关问题