解析 ManyToMany 关系时 django Prefetch() 的字段错误

Field error for django Prefetch() while resolving ManyToMany relations

这是我的模型:

class Element(models.Model):
    name = models.CharField(max_length=255)
    creator = models.ForeignKey(User, related_name='element_creator', on_delete=CASCADE)
    element_type = models.ForeignKey('ElementType', on_delete=CASCADE)
    create_date = models.DateTimeField(auto_now_add=True)
    modif_date = models.DateTimeField()
    description = models.TextField(blank=True, null=True)

    class Meta:
        managed = True


class ElementWorkingSet(models.Model):
    name = models.CharField(max_length=255)
    owner = models.ForeignKey(User, on_delete=CASCADE)
    create_date = models.DateTimeField(auto_now_add=True)
    modif_date = models.DateTimeField(auto_now=True)
    project = models.ForeignKey(Project, on_delete=CASCADE)
    active = models.BooleanField(default=True)

    elements = models.ManyToManyField(Element,
                                      through='ElementSet2Element',
                                      through_fields=('element_working_set', 'elements'),
                                      )

    class Meta:
        managed = True


class ElementSet2Element(models.Model):
    element_working_set = models.ForeignKey('ElementWorkingSet',
                                            on_delete=CASCADE)
    elements = models.ForeignKey(Element, on_delete=CASCADE)
    active = models.IntegerField()
    element_owner = models.ForeignKey(User, on_delete=CASCADE)
    approver = models.ForeignKey(User, null=True, related_name='+', on_delete=CASCADE)

    class Meta:
        managed = True

我正在提取 ElementWorkingSet 列表,并希望显示 ElementSet2Element table 中具有 element_ownerapprover 的子元素。

起初,我在不使用 prefetch_related 的情况下执行许多关系,但结果证明效率极低。在我需要 element_ownerapprover 之前,响应时间还不错。但是提取这些字段使它变得非常慢。

我正在尝试修改我的查询,以使用以下查询执行更高效的查询:

query = ElementWorkingSet.objects.filter(
            project__id=project_id, active=True).select_related(
        'owner'
        ).prefetch_related(
            Prefetch(
                'elements',
                queryset=ElementSet2Element.objects.select_related(
                    'elements',
                    'approver',
                    'element_owner'
                ),
            ),
        )

问题是,Django returns 以下错误:

Cannot resolve keyword 'elementworkingset' into field. Choices are: active, approver, approver_id, id, element_owner, element_owner_id, element_working_set, element_working_set_id, elements, elements_id

我没有在任何地方使用 elementworkingset 作为变量。它实际上并没有发生在我的项目中的任何地方。调试后我注意到,它来自 ElementWorkingSet 型号名称。

我不知道为什么会这样,也不知道我能做些什么来解决它。我正在使用 Django 1.9 和 Python 3.6 以及 MySQL 数据库。

这里的问题是你声明了

elements = models.ManyToManyField(
                          Element,
                          through='ElementSet2Element',
                          through_fields=('element_working_set', 'elements'))`

这是完全正确的,但是,当您将 'elements' 传递给 Prefetch 时, 它确定这是与 Element 模型的关系,而不是您预期的 ElementSet2Element(是的,它做的事情非常聪明)。因此,Element 的向后字段名称是 elementworkingset,因为您尚未在 models.ManyToManyField (docs) 中通过 related_query_namerelated_name 声明其他字段。然后你传递 ElementSet2Element 查询集,django 尝试在其中找到 elementworkingset。由于您在 ElementSet2Element 中没有这样的字段,它失败了。

因此,您应该将 'elementset2element_set' 传递给 Prefetch

而不是 'elements'