python - 如何在 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 等,因此我无法入睡......而且因为我被困住了,我仍然没有'不要进入“更新方法”,所以如果有人能解释这两者会很好。谢谢指教!
解决方案
问题出在你的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
推荐阅读
- python - 带有烧瓶的 rets-python 不能作为 json 返回
- javascript - 返回错误和抛出错误的区别
- oop - 可以用来自另一个聚合的不可变数据组成一个聚合吗?
- asp.net-core - 如何从 .net core 2.0 Web 应用程序的配置文件中获取 .net core 标准类库中的连接字符串?
- python - 如何在熊猫数据框中查找具有正值和负值的行
- c# - C#:如何在 EF .Where() 或 Select() 查询中引用动态对象属性?
- python - ValueError:检查输入时出错:预期 cu_dnnlstm_22_input 具有 3 个维度,但得到的数组具有形状 (2101, 17)
- html - 如何获取 Github Pages 自动颁发的 HTTPS 证书的私钥
- php - 使用带有标题的php强制下载时如何向用户发送消息
- text - Flutter的TextBaseline枚举中的字母和表意之间有什么区别