首页 > 解决方案 > 如何在 Django RESTful API 中序列化多对多关系中的数据列表并正确创建嵌套对象?

问题描述

我认为这是一个愚蠢的问题,但几天来我无法处理它......我有两个模型:书籍和作者。书可以有很多作者,而作者可以有很多书。我正在发布一本新书,并且我正在传递一个“标题”和一个作者列表(我需要通过一个字典列表来满足宁静的 API 要求,如下例所示)。我想从此列表中创建新作者,但不覆盖旧作者,也不复制它们。

模型.py:

class Authors(models.Model):
    name = models.CharField(max_length=50, blank=True)

class Book(models.Model):
    title = models.CharField(max_length=60, blank=False, null=False)
    authors = models.ManyToManyField(Authors)

序列化器.py:

class AuthorsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Authors
        fields = '__all__'

class BookSerializer(serializers.ModelSerializer):
    authors = AuthorsSerializer(many=True)
    class Meta:
        model = Book
        fields = ['id', 'title', 'authors']
        depth = 1

    def create(self, validated_data):
        authors_data = validated_data.pop('authors')
        book = Book.objects.create(**validated_data)
        for autor in authors_data:
            Authors.objects.create(book=book, **autor)
        return book

视图.py:

class BooksList(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

网址.py:

book_list = BooksList.as_view({
    'get': 'list',
    'post': 'create',
})

book_detail = BookDetails.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'})

authors_list = AuthorsList.as_view({
    'get': 'list',
    'post': 'create'})


urlpatterns = format_suffix_patterns([
    path('books/', book_list, name='book_list'),
    path('books/<int:pk>', book_detail, name='book_detail'),
    path('authors/', authors_list, name='authors_list'),
])

当我在 RESTful API 中的 webbrowser 中发布一个新对象时,如下所示:

{
    "title": "Anything",
    "authors": [{"name":"First Guy"},{"name":"Second Guy"}],
}

a'正在接收一个新的 Book 对象和数据库中的两个作者,但它们不相关。我得到这样的答案:

HTTP 201 Created
Allow: GET, POST, PUT, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 8,
    "title": "Anything",
    "authors": [],
}

当我获取作者列表时,他们是这样的:

   {
        "id": 8,
        "name": "First Guy"
    },
    {
        "id": 9,
        "name": "Second Guy"
    }
]

我想收到的观点是:

{
"title": "Anyting",
"authors": [
          "First Guy",
          "Second Guy"
        ]
}

为什么它们不相关,我在 book.authors 中看不到它们?我请求 GET 方法错误吗?当我通过管理面板执行此操作时,我可以将“作者”与“书”连接起来,它以这种方式工作,但当然它应该通过 API 调用工作。我已经尝试了几十种配置,括号组合,其他类型的关系,不同的论点,阅读了许多 od 文章/文档/youtube 等,因此我无法入睡......而且因为我被困住了,我仍然没有'不要进入“更新方法”,所以如果有人能解释这两者会很好。谢谢指教!

标签: pythondjangorestserializationmany-to-many

解决方案


问题出在你的create方法中BookSerializer。多对多相关对象在创建实例时不能直接赋值,即Authors.objects.create(book=book, **autor).

为了将Author对象与关联Book,您需要这样做:

def create(self, validated_data):
    authors_data = validated_data.pop('authors')
    book = Book.objects.create(**validated_data)
    for autor in authors_data:
        author_instance = Authors.objects.create(**autor)
        book.authors.add(author_instance)
        # or author_instance.book_set.add(book)
    return book

推荐阅读