无法在Django Rest Framework序列化程序的validated_data中获取非模型字段

时间:2015-06-05 11:19:34

标签: django django-rest-framework

我的Django模型中有一个ItemCollection和Items,我希望能够通过UI从集合中删除Items。在REST PUT请求中,我为每个Item添加一个额外的布尔字段deleted,以表示应该删除一个Item。

处理此问题的正确方法似乎是在Serializer的update方法中。 我的问题是这个非模型deleted字段在验证期间被删除,因此它不再可用。将deleted添加为SerializerMethodField无济于事。现在我从序列化程序的deleted属性中获取initial_data信息,但这感觉不对。

我目前的示例代码如下。有人知道更好的方法吗?

型号:

    class ItemCollection(models.Model):
        description = models.CharField(max_length=256)


    class Item(models.Model):
        collection = models.ForeignKey(ItemCollection, related_name="items")

串行器:

    from django.shortcuts import get_object_or_404
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import serializers
    from models import Item, ItemCollection


    class ItemSerializer(serializers.ModelSerializer):

        class Meta:
            model = Item


    class ItemCollectionSerializer(serializers.ModelSerializer):

        items = ItemSerializer(many=True, read_only=False)

        class Meta:
            model = ItemCollection

        def update(self, instance, validated_data):
            instance.description = validated_data['description']
            for item, item_obj in zip(
                   self.initial_data['items'], validated_data['items']):
                if item['delete']:
                    instance.items.filter(id=item['id']).delete()
            return instance


    class ItemCollectionView(APIView):

        def get(self, request, ic_id):
            item_collection = get_object_or_404(ItemCollection, pk=ic_id)
            serialized = ItemCollectionSerializer(item_collection).data
            return Response(serialized)

        def put(self, request, ic_id):
            item_collection = get_object_or_404(ItemCollection, pk=ic_id)
            serializer = ItemCollectionSerializer(
               item_collection, data=request.data)
            if serializer.is_valid(raise_exception=True):
                serializer.save()
            return Response(serializer.data)

PUT请求中的json示例:

    {
        "id": 2,
        "items": [
            {
                "id": 3,
                "collection": 2,
                "delete": true
            }
        ],
        "description": "mycoll"
    }

2 个答案:

答案 0 :(得分:18)

您可以通过覆盖to_internal_value fn:

来添加非模型字段
def to_internal_value(self, data):
    internal_value = super(MySerializer, self).to_internal_value(data)
    my_non_model_field_raw_value = data.get("my_non_model_field")
    my_non_model_field_value = ConvertRawValueInSomeCleverWay(my_non_model_field_raw_value)
    internal_value.update({
        "my_non_model_field": my_non_model_field_value
    })
    return internal_value

然后,您可以根据需要在createupdate处理它。

答案 1 :(得分:0)

如果您正在执行PUT请求,则您的视图可能正在调用$line。更改为

self.perform_update(serializer)

所有serializer.save(<my_non_model_field>=request.data.get('<my_non_model_field>', <default_value>) 都向下传递到validated_data到序列化器。 确保正确转换传入的值(转换为布尔值,转换为int等)