使用 django-rest-framework 3.0 并具有以下简单模型:
class Book(models.Model):
title = models.CharField(max_length=50)
class Page(models.Model):
book = models.ForeignKey(Books, related_name='related_book')
text = models.CharField(max_length=500)
并给出此JSON请求:
{
"book_id":1,
"pages":[
{
"page_id":2,
"text":"loremipsum"
},
{
"page_id":4,
"text":"loremipsum"
}
]
}
如何编写嵌套的序列化程序来处理此JSON,并为page
给定的每个序列号book
创建一个新页面或更新(如果存在)。
class RequestSerializer(serializers.Serializer):
book_id = serializers.IntegerField()
page = PageSerializer(many=True)
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
我知道用实例化序列化程序instance
会更新当前序列化程序,但是如何在create
嵌套序列化程序的方法中使用它呢?
首先,您要支持创建新的图书实例还是仅更新现有的图书实例?
如果您只想创建新的图书实例,则可以执行以下操作…
class PageSerializer(serializers.Serializer):
text = serializers.CharField(max_length=500)
class BookSerializer(serializers.Serializer):
page = PageSerializer(many=True)
title = serializers.CharField(max_length=50)
def create(self, validated_data):
# Create the book instance
book = Book.objects.create(title=validated_data['title'])
# Create or update each page instance
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=book)
page.save()
return book
请注意,我 没有
在book_id
此处添加。在创建图书实例时,我们不会包含图书ID。当我们更新图书实例时,通常会将图书ID包含在URL中,而不是包含在请求数据中。
如果你想支持创建和书籍实例的更新,那么你需要考虑一下你要如何处理未包含在请求页面,但 在 当前与书实例相关联。
您可能会选择静默忽略那些页面并保持原样,或者想引发验证错误,或者想要删除它们。
假设您要删除请求中未包含的所有页面。
def create(self, validated_data):
# As before.
...
def update(self, instance, validated_data):
# Update the book instance
instance.title = validated_data['title']
instance.save()
# Delete any pages not included in the request
page_ids = [item['page_id'] for item in validated_data['pages']]
for page in instance.books:
if page.id not in page_ids:
page.delete()
# Create or update page instances that are in the request
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=instance)
page.save()
return instance
您也可能 只 希望支持书籍更新,而不希望支持创建,在这种情况下, 仅 包含update()
方法。
您还可以通过多种方式减少查询数量,例如。使用批量创建/删除操作,但以上操作将以非常简单的方式完成工作。
如您所见,在处理嵌套数据时,您可能想要的行为类型有些微妙,因此,请仔细考虑在各种情况下期望的行为。
另请注意,我Serializer
在上面的示例中一直使用而不是ModelSerializer
。在这种情况下,仅将所有字段显式包括在serializer类中,而不是依赖ModelSerializer
默认情况下自动生成的一组字段,会更简单。
问题内容: 我正在编写一个食谱管理器作为课程的示例项目。除了使用一些非常基本的功能之外,我对DRF并没有太多的经验。目的是: 创建具有相关成分的新配方。在创建配方对象的同时创建成分对象。 models.py: serializers.py 这样可以在数据库中成功创建配方对象和配料对象,但不会将配料列表与配方相关联。我认为这是因为运行时字典中的成分被删除了,所以当我使用创建新的配方时,没有相关的成分
问题内容: 我有一个带有自我参照字段的模型,称为parent。模型: 序列化器: 现在,我要序列化区域的父级及其父级及其父级,直到父级为none。我发现了针对孩子而不是父母的递归序列化方法。我怎样才能做到这一点? 问题答案: 尝试在此处使用SerializerMethodField: 我不确定DRF是否有内置方法,但是您可以使用查询来获取所需的方法。
问题内容: 我使用的是Django Rest Framework,其中有以下两个序列化器: ServiceType模型如下所示: 我想通过更改相关服务(例如删除其中的一些服务)来更新现有实例。为此,我正在这样做: 我面临的问题是没有提供该字段-这意味着我得到了-尽管我在 字段中明确添加了该字段。 编辑 这是我发布的一个示例性请求(来自Chrome): 我在做什么错以及如何使用嵌套序列化程序获取对象
问题内容: 在Django Rest Framework中,当一个序列化器嵌套在另一个序列化器中时,如何过滤它? 我的过滤器被强加在DRF视图集中,但是当您从另一个序列化器内部调用序列化器时,嵌套序列化器的视图集将永远不会被调用,因此嵌套结果看起来是未经过滤的。 我尝试在原始视图集上添加过滤器,但是它似乎无法过滤嵌套结果,因为嵌套结果被称为单独的预提取查询。(您看到嵌套的序列化程序是反向查找。)
问题内容: 我曾经使用 allow_add_remove = True ,它在Django rest 2.0中可用,用于编写可嵌套的序列化程序,但在3.0中不可用,我很难实现它。 我想做这样的事情 现在我不知道如何在DRF 3.0中实现allow_add_remove行为 我很困惑,我需要重写UserSerializer和方法吗 或者我需要为每个模型创建单独的IdeaListSerializer
考虑: 如果我们序列化Foo(),输出是: 我想要: 最干净的方法是什么?