如何在Django Rest Framework中序列化三个具有多对多关系的模型
Posted
技术标签:
【中文标题】如何在Django Rest Framework中序列化三个具有多对多关系的模型【英文标题】:How to serialize three models with many to many relationships in Django Rest Framework 【发布时间】:2020-12-23 20:37:13 【问题描述】:我有三个基本模型:
class User(models.Model):
displayName= models.CharField(max_length=128)
class Cell(models.Model):
title = models.CharField(max_length=128)
class List(models.Model):
title = models.CharField(max_length=128)
以及它们之间的三个多对多关系:
class UserCell(models.Model):
user = models.ForeignKey(
User,
on_delete=models.CASCADE
)
cell = models.ForeignKey(
Cell,
on_delete=models.CASCADE
)
value = models.SmallIntegerField()
class Meta:
constraints = [
models.UniqueConstraint(
fields=['user', 'cell'],
name='unique_UserCell'
)
]
class UserList(models.Model):
user = models.ForeignKey(
User,
on_delete=models.CASCADE
)
target_list = models.ForeignKey(
List,
on_delete=models.CASCADE
)
last_updated = models.DateTimeField(default=timezone.now)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['user', 'target_list'],
name='unique_UserList'
)
]
class CellAssignment(models.Model):
target_list = models.ForeignKey(
List,
on_delete=models.CASCADE
)
cell = models.ForeignKey(
Cell,
on_delete=models.CASCADE
)
idx = models.SmallIntegerField()
class Meta:
ordering = ['idx']
constraints = [
models.UniqueConstraint(
fields=['target_list', 'idx'],
name='unique_cellAssignment'
)
]
我的视图有一个 List.id 和一个 User.id,我想以以下格式或类似格式返回数据:
"List.id": 2, "List.title": "The Big List of Cells", "List.created_date": "2020-10-02T18:14:02Z", "cells": ["target_list.id": 2, "Cell.id": 6, "CellAssignment.idx": 0, "Cell.title": "The first cell", "UserCell.value": 4, "target_list.id": 2, "Cell.id": 12, "CellAssignment.idx": 1, "Cell.title": "This is the second cell and so on", "UserCell.value": 9, ...]
是否可以通过嵌套序列化程序来做到这一点,或者我应该单独查询关系并在视图中加入数据?任何有关这两种方法之间性能差异的信息将不胜感激。
编辑 (12/24)。当前的序列化器:
class UserCellSerializer(serializers.ModelSerializer):
class Meta:
model = UserCell
fields = '__all__'
class CellSerializer(serializers.ModelSerializer):
class Meta:
model = Cell
fields = ['id', 'title']
class CellAssignmentSerializer(serializers.ModelSerializer):
cell_title = serializers.ReadOnlyField(source='cell.title')
cell_value = serializers.ReadOnlyField(source='cell.user_cell.value')
class Meta:
model = CellAssignment
#target_list and cell are not strictly needed below, as of now. good for debug tho.
fields = ['target_list', 'idx', 'alt_title', 'cell_title', 'cell_value']
class ListSerializer(serializers.ModelSerializer):
cell_details = CellAssignmentSerializer(read_only=True, many=True)
class Meta:
model = List
fields = ['id', 'title', 'created_date', 'cell_details']
【问题讨论】:
【参考方案1】:https://www.django-rest-framework.org/api-guide/relations/#nested-relationships
你可以制作嵌套序列化器。
-
为模型制作每个序列化程序。
使所有序列化程序嵌套。
首先,只需制作每个序列化程序,然后将它们全部合并为嵌套。 它应该可以工作。
更新,
cell = models.ForeignKey(
Cell,
on_delete=models.CASCADE,
related_name="user_cells"
)
然后,您可以像访问单元格一样访问 user_cell
cell_instance.user_cells.all()
或任何你想要的。
【讨论】:
感谢您的回复山姆。我确实知道我可以制作嵌套序列化程序。我已经将列表字段与单元格对象列表一起序列化。我坚持让 UserCell.value 与每个单元格协调。我还想知道,如果通过 id 手动连接表似乎更容易(就像通常使用关系 SQL 所做的那样),那么通过复杂的模型/序列化程序过程是否值得付出努力。 您可以使用反向foreign_key获取数据。使用related_name它可以让你得到UserCell数据。 是的,我认为related_name 将是关键。我已将它添加到单元格 ForeignKey 上的 UserCell:related_name='user_cell'
。对于以下序列化程序,显示了 cell_title 但未显示 cell_value:class CellAssignmentSerializer(serializers.ModelSerializer): cell_title = serializers.ReadOnlyField(source='cell.title') cell_value = serializers.ReadOnlyField(source='cell.user_cell.value')
似乎无法深入到相邻关系?
可以在调用 CellAssignmentSerializer 之前添加视图代码吗?
视图现在没有做任何工作,单元格分配实际上嵌套在 ListSerializer 中,many=True
。所以我只是通过 id 和targetList = List.objects.get(pk=pk)
获取我请求的列表,然后将其交给 ListSerializer:list_serializer = ListSerializer(targetList)
以上是关于如何在Django Rest Framework中序列化三个具有多对多关系的模型的主要内容,如果未能解决你的问题,请参考以下文章
如何在 django-rest-framework 中为 API 使用 TokenAuthentication
如何在 Django Rest Framework 中处理并行请求?
如何让 django-rest-framework-jwt 在注册时返回令牌?
如何在 Django 的单个 API 中获取访问令牌和刷新令牌(rest_framework_jwt)