首页 > 解决方案 > Django Rest Framework-我可以在序列化程序的创建方法中允许 pk id 或完整对象吗?

问题描述

假设我有以下模型:

class Author(models.Model):
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)

class Book(models.Model):
    title = models.CharField(max_length=64)
    author = models.ForeignKeyField(Author, on_delete=models.CASCADE)

我有以下序列化程序:

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ('id', 'title', 'author')
        read_only_fields = ('id')

如果我然后查询我的书,一本书的数据如下所示:

{
    "id": 1,
    "title": "Book Title",
    "author": 4
}

这就是我想要的,因为我返回了一系列书籍以及一系列作者,并允许客户加入所有内容。这是因为我有很多作者在书中重复出现。

但是,我希望允许客户提交现有的作者 ID 以创建新书,或提交新作者的所有数据。例如:

现有作者的新书有效载荷:

{
    "title": "New Book!",
    "author": 7
}

或者,新作者的新书的有效载荷:

{
    "title": "New Book!",
    "author": {
        "first_name": "New",
        "last_name": "Author"
    }
}

但是第二个版本不会通过我的序列化程序中的数据验证步骤。有没有办法覆盖验证步骤,允许作者 ID 或完整对象?然后在我的序列化程序的创建方法中,我可以检查类型,或者创建一个新作者,获取它的 id,然后创建新书,或者只是附加现有的 id。想法?

标签: pythondjangoserializationdjango-rest-framework

解决方案


我相信不可能以您想要的方式(使用一个字段author)进行操作。

只是因为一个序列化程序无法为一个字段处理两种不同的类型。

注意:我可能对前面的陈述有误。

但是,以下是您的潜在解决方案。您只需要使用不同的字段名称来创建新作者。

class BookSerializer(serializers.ModelSerializer):
    author = serializers.PrimaryKeyRelatedField(
        required=False,
        queryset=Author.objects.all(),
    )

    author_add = AuthorSerializer(write_only=True, required=False)

    class Meta:
        model = Book
        fields = ('id', 'title', 'author', 'author_add')
        read_only_fields = ('id')

    def create(self, validated_data):
        author_add_data = validated_data.pop('author_add', None)

        if author_add is not None:
            validated_data['author'] = Author.objects.create(**author_add_data)

        return super().create(validated_data)

注意:您需要处理同时发送author和的情况author_add。如果两者都提供,可能会在验证步骤中添加检查并引发 ValidationError。

题外话提示:您不需要明确状态read_only_fields = ('id',)- 主键是只读的。


推荐阅读