Python 如何在Django RESTful API中序列化多个关系中的数据列表并正确创建嵌套对象?
我认为这是一个愚蠢的问题,但有几天我无法处理它。。。我有两个模型:书和作者。书可以有很多作者,作者也可以有很多书。我正在发布一本新书,我正在传递一个“标题”和一个作者列表(RESTfulAPI要求我传递一个字典列表,如下面的示例所示)。我想从这个列表中创建新的作者,但不覆盖旧作者,也不复制他们 models.py:Python 如何在Django RESTful API中序列化多个关系中的数据列表并正确创建嵌套对象?,python,django,rest,serialization,many-to-many,Python,Django,Rest,Serialization,Many To Many,我认为这是一个愚蠢的问题,但有几天我无法处理它。。。我有两个模型:书和作者。书可以有很多作者,作者也可以有很多书。我正在发布一本新书,我正在传递一个“标题”和一个作者列表(RESTfulAPI要求我传递一个字典列表,如下面的示例所示)。我想从这个列表中创建新的作者,但不覆盖旧作者,也不复制他们 models.py: class Authors(models.Model): name = models.CharField(max_length=50, blank=True) class
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)
serielizers.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
views.py:
class BooksList(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
URL.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'),
])
a我收到一个新书对象,数据库中有两位作者,但他们没有关联。我得到的答案是这样的:
{
"title": "Anything",
"authors": [{"name":"First Guy"},{"name":"Second Guy"}],
}
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": "Anything",
"authors": [{"name":"First Guy"},{"name":"Second Guy"}],
}
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"
]
}
为什么他们不相关,我在书中没有看到他们。作者?我要求的方法是错误的吗?当我通过管理面板执行此操作时,我可以将“Authors”与“Book”连接起来,它通过这种方式工作,但当然它应该通过API调用工作。我尝试了几十种配置,括号的组合,其他类型的关系,不同的参数,读了很多od文章/文档/youtube等,我无法入睡,因为这。。。因为我很笨,我还没有找到“更新方法”,所以如果有人能解释这两种方法就好了。谢谢你的建议 问题出在
BookSerializer
中的create
方法中。创建实例时不能直接分配多对多相关对象,即Authors.objects.create(book=book,**autor)
要将作者
对象与书籍
相关联,您需要像这样做:
def创建(自我验证的_数据):
authors\u data=validated\u data.pop(‘authors’)
book=book.objects.create(**已验证的_数据)
对于作者中的autor\u数据:
author\u instance=Authors.objects.create(**autor)
book.authors.add(author\u实例)
#或author\u instance.book\u set.add(book)
回执
ooo谢谢-现在,作者列表与书籍相关,但当作者在数据库中时,它会复制他。我是否应该使用某种形式的“如果”语句?@noumen您必须以某种方式确定即将到来的作者,可能的解决方案是在您的请求正文中发送一个id
,并检查DB中是否存在该作者。但是,我建议您不要创建作者
对象,而是发送现有作者的id-s并将其设置为图书