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

时间:2018-03-25 11:09:09

标签: python django many-to-many django-orm prefetch

以下是我的模特:

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列表,并希望在element_owner表中显示带有approverElementSet2Element的子元素。

起初,我在不使用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返回以下错误:

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数据库。

1 个答案:

答案 0 :(得分:0)

这里的问题是您已声明

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

但是,当您将'elements'传递给Prefetch时,这是完全正确的, 它确定这是与Element模型的关系,而不是你想象的ElementSet2Element(是的,它确实很聪明)。因此,元素的后向字段名称为elementworkingset,因为您尚未在related_query_namedocs)中通过related_namemodels.ManyToManyField声明其他名称。然后你传递ElementSet2Element queryset,django尝试在其中找到elementworkingset。由于ElementSet2Element中没有此类字段,因此失败。

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

而不是Prefetch