【发布时间】:2015-08-20 07:50:30
【问题描述】:
我的 Django 模型中有一个 ItemCollection 和 Items,我希望能够通过 UI 从集合中删除 Items。在 REST PUT 请求中,我为每个项目添加了一个额外的布尔字段 deleted,以表明应该删除一个项目。
处理这个问题的正确方法似乎是在序列化器的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"
}
【问题讨论】:
-
为每个需要删除的嵌套模块执行单独的 HTTP
DELETE是否可以接受?如果您使用serializers.HyperlinkedModelSerializer作为序列化程序的基类,每个子项都会有一个您可以轻松使用DELETE的URL。 -
这是一个有趣的探索角度。虽然,主要问题是
validated_data中缺少有关需要删除哪些项目的信息。 -
我的意思是,在客户端,不要在子项上设置标志
delete,只需对该对象执行 HTTPDELETE并将其从容器中删除。您不会在 Django 内部执行DELETE(如果我可以假设您是在暗示这种方法。) -
啊,我误会了。不错的方法,tx!
标签: django django-rest-framework