有效检索反向外键上的相关字段

有效检索反向外键上的相关字段

本文介绍了Django Rest Framework-有效检索反向外键上的相关字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代表用户工作组的模型。每个工作组都有一个领导者和成员:

I have the following models that represent a working group of users. Each working group has a leader and members:

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对象的数组:

In DRF, I want to efficiently retrieve all groups (there are several hundred) as an array of the following json objects:

{
    'id': <the_group_id>
    'group_name': <the_group_name>
    'leader': <id_of_leader>
    'members': [<id_of_member_1>, <id_of_member_2>, ...]
}

为此,我设置了以下序列化器:

To do so, I have set up the following serializer:

class WorkingGroupSerializer(serializers.ModelSerializer):
    members = serializers.SerializerMethodField()
    class Meta:
        model = WorkingGroup
        fields = ('id', 'group_name', 'leader', 'members',)

    def get_members(self, obj):
        return obj.workinggroupmember_set.all().values_list('user_id', flat=True)

因此,在我看来,我可以执行以下操作:

So that in my view, I can do something like:

groups = WorkingGroup.objects.all().prefetch_related('workinggroupmember_set')
group_serializer = WorkingGroupSerializer(groups, many=True)

这可行,并给出了预期的结果,但是我发现它根本无法很好地扩展,因为预取 workinggroupmember_set 不eem可以在 get_members 方法中使用(Silky正在显示一个查询,以获取所有 WorkingGroup 对象,然后在 get_members 方法中对每个 workinggroupmember_set 调用的查询)。有没有一种方法可以在序列化程序中设置 members 字段来获取 workinggroupmember_set 的扁平/单字段版本,而无需使用 SerializerMethodField ?还是其他可以让我正确使用预取的方式?

This works, and gives the desired result, however I am finding it does not scale well at all, as the prefetching workinggroupmember_set does not seem to be used inside of the get_members method (Silky is showing a single query to grab all WorkingGroup objects, and then a query for each workinggroupmember_set call in the get_members method). Is there a way to set up the members field in the serializer to grab a flattened/single field version of workinggroupmember_set without using a SerializerMethodField? Or some other way of doing this that lets me properly use prefetch?

推荐答案

问题在这里,您正在执行全部上的> values_list ,这会使您的 prefetch_related 无效。当前无法使用 values_list 进行预取,请参见。您可以做的是将其转换为python代码,而不是SQL

Problem here that you are doing values_list on top of all which nullifies your prefetch_related. There is currently no way to do prefetch with values_list see https://code.djangoproject.com/ticket/26565. What you can do is to transition this into python code instead of 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()]

这篇关于Django Rest Framework-有效检索反向外键上的相关字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 04:39