Ошибка поля для django Prefetch() при разрешении отношений ManyToMany

Вот мои модели:

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 а также approver от ElementSet2Element Таблица.

Сначала я выполнял много отношений без использования prefetch_related, но это оказалось крайне неэффективным. До того времени, когда мне нужно было element_owner а также approverВремя отклика было приличным. Но извлечение этих полей сделало это очень медленно.

Я пытаюсь изменить свой запрос, чтобы выполнить более эффективный запрос, используя следующий запрос:

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 ответ

Решение

Проблема в том, что вы заявили

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

Это совершенно правильно, однако, когда вы проходите 'elements' в Prefetch, он определяет, что это отношение к модели Element, а не ElementSet2Element, как вы ожидали (да, это делает довольно умные вещи). Итак, обратное имя поля для элемента elementworkingsetпотому что вы не объявили другие через related_query_name или же related_name в вашем models.ManyToManyField ( документы). Тогда вы проходите ElementSet2Element queryset и django пытается найти elementworkingset в этом. Так как у вас нет такого поля в ElementSet2Element, это не удается.

Итак, вместо 'elements' ты должен пройти 'elementset2element_set' в Prefetch

Другие вопросы по тегам