Python Django Rest框架-高效检索反向外键上的相关字段
我有以下代表用户工作组的模型。每个工作组有一名组长和成员:Python Django Rest框架-高效检索反向外键上的相关字段,python,django,performance,orm,django-rest-framework,Python,Django,Performance,Orm,Django Rest Framework,我有以下代表用户工作组的模型。每个工作组有一名组长和成员: class WorkingGroup(models.Model): group_name = models.CharField(max_length=255) leader = models.ForeignKey(User, null=True, on_delete=models.SET_NULL) class WorkingGroupMember(models.Model): group = models.F
class WorkingGroup(models.Model):
group_name = models.CharField(max_length=255)
leader = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
class WorkingGroupMember(models.Model):
group = models.ForeignKey(WorkingGroup, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
在DRF中,我希望高效地检索所有组(有几百个),作为以下json对象的数组:
{
'id': <the_group_id>
'group_name': <the_group_name>
'leader': <id_of_leader>
'members': [<id_of_member_1>, <id_of_member_2>, ...]
}
因此,在我看来,我可以这样做:
groups = WorkingGroup.objects.all().prefetch_related('workinggroupmember_set')
group_serializer = WorkingGroupSerializer(groups, many=True)
这是可行的,并给出了期望的结果,但是我发现它的伸缩性并不好,因为预取
workinggroupmember\u set
似乎没有在get\u members
方法中使用(Silky显示了一个获取所有WorkingGroup
对象的查询,然后是get\u members
方法中每个workinggroupmember\u set
调用的查询)。是否有一种方法可以在序列化程序中设置成员
字段,以便在不使用SerializerMethodField
的情况下获取工作组成员集的扁平/单字段版本?或者有其他方法可以让我正确使用预回迁吗?这里的问题是您正在执行的值列表
fall
使您的prefetch\u related
无效。当前无法使用值\u列表进行预取参见。您可以做的是将其转换为python代码而不是SQL
class WorkingGroupSerializer(serializers.ModelSerializer):
members = serializers.SerializerMethodField()
class Meta:
model = WorkingGroup
fields = ('id', 'group_name', 'leader', 'members',)
def get_members(self, obj):
return [wgm.user_id for wgm in obj.workinggroupmember_set.all()]
在最近一个使用DRF v3.9.1和django 2.1的项目中,我需要递归地公开一个对象的所有子对象,方法是只直接连接到父对象,而父对象可能有多个子对象
以前,如果我请求对象的“树”,我会得到:
{
"uuid": "b85385c0e0a84785b6ca87ce50132659",
"name": "a",
"parent": null
}
通过应用如下所示的序列化,我得到:
{
"uuid": "b85385c0e0a84785b6ca87ce50132659",
"name": "a",
"parent": null
"children": [
{
"uuid": "efd26a820b4e4f7c8e56c812a7791fcb",
"name": "aa",
"parent": "b85385c0e0a84785b6ca87ce50132659"
"children": [
{
"uuid": "ca2441fc7abf49b6aa1f3ebbc2dae251",
"name": "aaa",
"parent": "efd26a820b4e4f7c8e56c812a7791fcb"
"children": [],
}
],
},
{
"uuid": "40e09c85775d4f1a8578bba9c812df0e",
"name": "ab",
"parent": "b85385c0e0a84785b6ca87ce50132659"
"children": [],
}
],
}
下面是递归对象的models.py
:
类类别定义(BaseModelClass):
name=models.CharField(最大长度=100)
parent=models.ForeignKey('self',related_name='children',
在_delete=models.CASCADE上,
空=真,空=真)
要获取外键中的所有反向对象,请将字段应用于序列化程序类:
class DeepCategorySerializer(serializers.ModelSerializer):
children=serializers.SerializerMethodField()
类元:
模型=模型。类别定义
字段='\uuuu所有\uuuu'
def get_子项(自身、obj):
将[DeepCategorySerializer().返回到对象children.all()中cat的_表示(cat)]
然后将此序列化程序应用于DRF视图函数或泛型类,例如:
re_path(r'categories/(?P<pk>[\w\d]{32})/',
generics.RetrieveUpdateDestroyAPIView.as_view(
queryset=models.CategoryDefinition.objects.all(),
serializer_class=serializers.DeepCategorySerializer),
name='category-update'),
re_路径(r'categories/(?P[\w\d]{32})/,
generics.RetrieveUpdatedStroyapiView.as_视图(
queryset=models.CategoryDefinition.objects.all(),
serializer_class=serializers.DeepCategorySerializer),
name='category-update'),
你愿意改变你的模式吗?如果是的话,一个解决方案可能是完全摆脱工作组成员
,并在用户
中添加一个名为成员
的多个字段
,直接在工作组
下。是的,这肯定是一种可能性。实际上,这种关系更像是一种关系-对于多个through,其中WorkingGroupMember具有应用程序/api其他区域中使用的其他字段,但对于此特定端点,我们只需要该组中的用户。AManyToManyField
将只创建一个透明的“through模型”这与您的WorkingGroupMember
模型完全相同。您的ManyToManyField
可能会使用WorkingGroupMember
作为其直通模型,您会发现自己也处于相同的情况。太棒了!感谢您指出这个问题-我已经在DRF文档中查找了这不起作用的原因,结果是原来是django的问题。你的修复效果很好。
re_path(r'categories/(?P<pk>[\w\d]{32})/',
generics.RetrieveUpdateDestroyAPIView.as_view(
queryset=models.CategoryDefinition.objects.all(),
serializer_class=serializers.DeepCategorySerializer),
name='category-update'),