如何使用 Django Rest Framework 反序列化嵌套对象
How to deserialize nested objects with Django Rest Framework
假设我有这样的 Django 模型:
class Book(models.Model):
title = models.CharField(max_length=150)
author = models.CharField(max_length=150)
class Chapter(models.Model):
book = models.ForeignKey(Book, related_name='chapters')
title = models.CharField(max_length=150)
page_num = models.IntegerField()
和 Django Rest Framework 类 像这样:
class ChapterSerializer(serializers.ModelSerializer):
class Meta:
model = Chapter
fields = ('id', 'title', 'page_num')
class BookSerializer(serializers.ModelSerializer):
chapters = ChapterSerializer(many=True)
class Meta:
model = Book
fields = ('id', 'title', 'author', 'chapters')
def create(validated_data):
chapters = validated_data.pop('chapters')
book = Book(**validated_data)
book.save()
serializer = ChapterSerializer(data=chapters, many=True)
if serializer.is_valid(raise_exception=True):
chapters = serializer.save()
class BookCreate(generics.CreateAPIView):
serializer = BookSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
# Do some other stuff
我 POST 一些 JSON 像这样:
{
title: "Test book",
author: "Test author",
chapters: [
{title: "Test chapter 1", page_num: 1},
{title: "Test chapter 2", page_num: 5}
]
}
我得到一个异常,因为 chapter
没有与之关联的 book
。如果我将 book
添加为 ChapterSerializer
的字段之一,那么 JSON 将无法验证,因为 BookCreate
中的 BookSerializer
将无法验证,因为它将需要章节的书籍 ID,但尚未创建书籍。我该如何解决这种情况?
有没有办法让 BookSerializer
验证其自己的字段而不验证其 chapter
的字段?
您可以在 .save
上 pass additional arguments。所以我认为你只需要将新创建的书籍实例传递给 serializer
,例如
def create(validated_data):
chapters = validated_data.pop('chapters')
book = Book(**validated_data)
book.save()
serializer = ChapterSerializer(data=chapters, many=True)
if serializer.is_valid(raise_exception=True):
chapters = serializer.save(book=book)
我认为,您不应该在序列化程序的 create()
方法中创建另一个序列化程序,因为这是多余的。如果您将其定义为该字段引用的模型的序列化程序,则序列化程序已完成验证:
class BookSerializer(serializers.ModelSerializer):
# here you define the serializer to validate your input
chapters = ChapterSerializer(many=True)
相反,您可以只创建对象,数据已经通过调用初始序列化程序的 is_valid()
进行了验证。无论如何你都需要将这本书传递给 create()
方法:
def create(validated_data):
chapters_data = validated_data.pop('chapters')
book = Book.objects.create(**validated_data)
for chapter_data in chapters_data:
Chapter.objects.create(book=book, **chapter_data)
假设我有这样的 Django 模型:
class Book(models.Model):
title = models.CharField(max_length=150)
author = models.CharField(max_length=150)
class Chapter(models.Model):
book = models.ForeignKey(Book, related_name='chapters')
title = models.CharField(max_length=150)
page_num = models.IntegerField()
和 Django Rest Framework 类 像这样:
class ChapterSerializer(serializers.ModelSerializer):
class Meta:
model = Chapter
fields = ('id', 'title', 'page_num')
class BookSerializer(serializers.ModelSerializer):
chapters = ChapterSerializer(many=True)
class Meta:
model = Book
fields = ('id', 'title', 'author', 'chapters')
def create(validated_data):
chapters = validated_data.pop('chapters')
book = Book(**validated_data)
book.save()
serializer = ChapterSerializer(data=chapters, many=True)
if serializer.is_valid(raise_exception=True):
chapters = serializer.save()
class BookCreate(generics.CreateAPIView):
serializer = BookSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
# Do some other stuff
我 POST 一些 JSON 像这样:
{
title: "Test book",
author: "Test author",
chapters: [
{title: "Test chapter 1", page_num: 1},
{title: "Test chapter 2", page_num: 5}
]
}
我得到一个异常,因为 chapter
没有与之关联的 book
。如果我将 book
添加为 ChapterSerializer
的字段之一,那么 JSON 将无法验证,因为 BookCreate
中的 BookSerializer
将无法验证,因为它将需要章节的书籍 ID,但尚未创建书籍。我该如何解决这种情况?
有没有办法让 BookSerializer
验证其自己的字段而不验证其 chapter
的字段?
您可以在 .save
上 pass additional arguments。所以我认为你只需要将新创建的书籍实例传递给 serializer
,例如
def create(validated_data):
chapters = validated_data.pop('chapters')
book = Book(**validated_data)
book.save()
serializer = ChapterSerializer(data=chapters, many=True)
if serializer.is_valid(raise_exception=True):
chapters = serializer.save(book=book)
我认为,您不应该在序列化程序的 create()
方法中创建另一个序列化程序,因为这是多余的。如果您将其定义为该字段引用的模型的序列化程序,则序列化程序已完成验证:
class BookSerializer(serializers.ModelSerializer):
# here you define the serializer to validate your input
chapters = ChapterSerializer(many=True)
相反,您可以只创建对象,数据已经通过调用初始序列化程序的 is_valid()
进行了验证。无论如何你都需要将这本书传递给 create()
方法:
def create(validated_data):
chapters_data = validated_data.pop('chapters')
book = Book.objects.create(**validated_data)
for chapter_data in chapters_data:
Chapter.objects.create(book=book, **chapter_data)