无法在 Django Rest Framework 序列化程序的 validated_data 中获取非模型字段
Unable to get a non-model field in the validated_data of a Django Rest Framework serializer
我的 Django 模型中有一个 ItemCollection 和 Items,我希望能够通过 UI 从集合中删除 Items。在 REST PUT 请求中,我为每个项目添加了一个额外的布尔字段 deleted
以表示应删除一个项目。
正确的处理方式似乎是在 Serializer 的 update
方法中。
我的问题是这个非模型 deleted
字段在验证期间被删除,因此它不再可用。添加 deleted
作为 SerializerMethodField
没有帮助。现在我从 Serializer 的 initial_data
属性得到我的 deleted
信息,但感觉不对。
我当前的示例代码如下。有人知道更好的方法吗?
型号:
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"
}
您可以通过覆盖 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
然后你可以在create
或update
中随意处理它。
如果您正在执行 PUT 请求,您的视图可能正在调用 self.perform_update(serializer)
。为
更改它
serializer.save(<my_non_model_field>=request.data.get('<my_non_model_field>', <default_value>)
所有 kwargs
都传递给 validated_data 到您的序列化程序。
确保正确转换传入值(布尔值、整数等)
我的 Django 模型中有一个 ItemCollection 和 Items,我希望能够通过 UI 从集合中删除 Items。在 REST PUT 请求中,我为每个项目添加了一个额外的布尔字段 deleted
以表示应删除一个项目。
正确的处理方式似乎是在 Serializer 的 update
方法中。
我的问题是这个非模型 deleted
字段在验证期间被删除,因此它不再可用。添加 deleted
作为 SerializerMethodField
没有帮助。现在我从 Serializer 的 initial_data
属性得到我的 deleted
信息,但感觉不对。
我当前的示例代码如下。有人知道更好的方法吗?
型号:
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"
}
您可以通过覆盖 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
然后你可以在create
或update
中随意处理它。
如果您正在执行 PUT 请求,您的视图可能正在调用 self.perform_update(serializer)
。为
serializer.save(<my_non_model_field>=request.data.get('<my_non_model_field>', <default_value>)
所有 kwargs
都传递给 validated_data 到您的序列化程序。
确保正确转换传入值(布尔值、整数等)