无法在Django Rest Framework序列化程序的validated_data中获取非模型字段 [英] Unable to get a non-model field in the validated_data of a Django Rest Framework serializer

查看:1781
本文介绍了无法在Django Rest Framework序列化程序的validated_data中获取非模型字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



正确的处理方式似乎在Serializer的更新方法中。
我的问题是,这个非模型删除的字段在验证过程中被删除,所以它不再可用了。将删除作为 SerializerMethodField 没有帮助。现在我从序列化器的 initial_data 属性中获取了我的删除的信息,但这不是正确的。 p>

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



模型:

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


类项目(models.Model):
collection = models.ForeignKey( ItemCollection,related_name =items)

序列化器:



_ pre> 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
从模型导入项目,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']):
如果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响应(序列化)

def put(self,request,ic_id):
item_collection = get_object_or_404(ItemCollection,pk = ic_id)
serializer = ItemCollectionSerializer(
item_collection,data = request.data)
如果serializer.i s_valid(raise_exception = True):
serializer.save()
return响应(serializer.data)

另请参见PUT请求中的json示例:

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


解决方案

您可以通过覆盖 to_internal_value fn:



添加非模型字段$ _ code> 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_no n_model_field:my_non_model_field_value
})
return internal_value

然后你可以处理它但是您需要在创建更新


I have an ItemCollection and Items in my Django models and I want to be able to remove Items from the collection through the UI. In a REST PUT request I add an extra boolean field deleted for each Item to signal that an Item should be deleted.

The correct way to handle this seems to be in the update method of the Serializer. My problem is that this non-model deleted field gets removed during validation, so it is not available anymore. Adding deleted as a SerializerMethodField did not help. For now I get my deleted information from the initial_data attribute of the Serializer, but that does not feel right.

My current example code is below. Does anybody know a better approach?

Models:

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


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

Serializers:

    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)

And an example of the json in the PUT request:

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

解决方案

You can add non-model fields back by overwriting the 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

Then you can process it however you want in create or update.

这篇关于无法在Django Rest Framework序列化程序的validated_data中获取非模型字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆