在 Django 中优化查询,prefact_related 用于反向链接的对象

Optimizing queries in Django, prefact_related for objects that are reversely linked

在我的 django 项目中,我有 3 个模型,针对此示例进行了简化:Contact、WorkRelation 和 Group 对象。

联系

class Contact(BaseModel):
    title = models.CharField(max_length=30, blank=True)
    initials = models.CharField(max_length=10, blank=True)
    first_name = models.CharField(max_length=30, blank=True)
    prefix = models.CharField(max_length=20, blank=True)
    surname = models.CharField(max_length=30)

    def get_workrelations(self):
        workrelations = apps.get_model('groups', 'WorkRelation')
        return workrelations.objects.filter(contact=self)

    def get_organisations(self):
        output = ""
        strings = []
        wr = self.get_workrelations()
        for relation in wr:
            group = relation.group
            name = group.name
            strings.append(s)
        if len(strings) > 0:
            output = ", ".join(strings)
        return output

工作关系

class WorkRelation(BaseModel):
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    function = models.CharField(max_length=40, blank=True)
    email_address = models.EmailField()
    phone_number = models.CharField(max_length=13, blank=True)
    description = models.TextField(max_length=400, blank=True)

class Group(BaseModel):
    group_type = models.ForeignKey(GroupType, on_delete=models.CASCADE)
    name = models.CharField(max_length=60, unique=True)
    street_name = models.CharField(max_length=40, blank=True)
    house_number = models.CharField(max_length=10, blank=True)

此设置的问题是,当我想在大型联系人集上调用 get_organisations() 时,它会变得非常慢。例如:当尝试列出我所有的联系人(我的演示集有 600 个)并调用 get_organisations() 时,大约需要 1250 个查询。

我发现您可以使用 prefetch_data() 来防止这种情况发生,但不知何故我无法在我的设置中使用它。我试图替换我对

的查询
queryset = Contact.objects.prefetch_related('workrelation_set')

但这并没有加快速度(与我的推测相反)。你们知道是否有可能加快速度吗?

将您的 get_organisations 代码更改为:

def get_organisations(self):
    return ', '.join(
        workrelation.group.name for workrelation
        in self.workrelation_set.all()
    )

并使用此查询获取联系人对象:

Contact.objects.prefetch_related('workrelation_set__group')

这将 return 单个查询的结果。