Skip to main content
 首页 » 编程设计

python之Django Rest Framework-有效地检索反向外键的相关字段

2024年09月03日31dflying

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

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>, ...] 
} 

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

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) 

所以在我看来,我可以做类似的事情:

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

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

请您参考如下方法:

这里的问题是您在 all 之上执行 values_list,这会使您的 prefetch_related 无效。当前无法使用 values_list 进行预取,请参阅 https://code.djangoproject.com/ticket/26565 .你可以做的是将其转换为 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()]