我有一个模型BookSerializer
的串行器Book
和一个嵌套的PageSerializer
模型Page
。更新Book
实例包括删除其所有Page
实例,然后创建这些Page
实例,可能有或没有这种涉及页面的新数据或没有或没有现有数据的更新。>
但是我的Book
模型具有一个约束,其中每个Book
实例每个最多只能有100
个页面。验证检查是在PageSerializer
的{{1}}方法中完成的。我还有另一个理由在这里这样做:
validate
序列化程序或说def validate(self, attrs):
#some logic here
raise some error if book instance already has 100 pages or if it will have more than 100 pages when combined with new pages when added.
的更新方法定义为:
BookSerializer
因此,发送给更新的数据已经得到验证,可以在def update(self, instance, validated_data):
...
...
方法内以validated_data
的方式访问。
现在,这是问题所在。嵌套的序列化器update
具有PageSerializer
方法,该方法检查该validate
实例中已有多少页并针对它们进行验证。
让Book
是已经拥有B
页的Book
的实例。如果我尝试对100
进行审核,而没有进行任何更改,则仍会在B
中检查发送的数据是否经过验证,将其页面数据传递给BookSerializer
,然后最终传递PageSerializer
到validated_data
方法。
我的问题是:
update(self, instance, val;idated_data)
发送的页面的数据之前,如何删除B
的所有页面?答案 0 :(得分:0)
我建议您使用BookSerializer的update(**kwargs)
方法删除页面。在PageSerializer
的验证方法中,您应该验证收到的数据(您不应将现有的页面视为要删除所有页面的顺序)。仅完全覆盖现有书籍的页面就是这种情况。但是,当您要更新它们时,还应该返回id
页(您应该在id
中添加PageSerializer
,以便嵌套的序列化程序可以标识您正在更新的实例)。因此,需要进行验证才能更新。
请求正文应如下所示:
{
'book_title': 'TITLE'
'pages':[
{'id': 3, 'title': 'TITLE', 'body': 'BODY'},
{'title': 'TITLE', 'body': 'BODY'}, ...
]
....
}
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
fields =['id', .....]
class Book(serializers.ModelSerializer):
pages = PageSerializer(many=True)
class Meta:
model = Book
fields = ['id', 'pages', ....]
def validate_pages(self, values): # here values will be as [{...},{...},..]
obj_list = list()
for value in values:
pk = value.pop('id', None)
if pk:
try:
page = Page.objects.get(pk=pk)
for k, v in value.items():
setattr(page, key, value)
obj_list.append(page)
except Page.DoesNotExists():
# handle by yourself, skip or raise error
else:
obj_list.append(Page(**value))
# here you can validate length also
return obj_list
在create(self, validated_data)
和update(self, instance, validated_data)
中,您将页面作为对象列表。因此,您可以使用以下方法删除:
pages = validated_data['pages']
page_ids = [page.pk for page in pages if page.pk] # it get all ids from list
if page_ids:
Page.objects.filter(book=instance).exclude(pk__in=page_ids).delete() it can be applicable only for updating
使用批量或迭代进行简单创建。