Причина сбоя фильтрации обратного отношения, когда поле m2m использует строковый класс?

Я столкнулся со странной проблемой, используя Django 2.2 и пытаясь отфильтровать обратное отношение, которое было определено с помощью строковой ссылки на класс. Проблема исчезает, если я передаю сам класс, т.е.

ЭТО ПРОВАЛ:

class Whatever(models.Model):
   providers = models.ManyToManyField('Relation', related_name='dependants')

ЭТО РАБОТАЕТ:

from models import Relation

class Whatever(models.Model):
   providers = models.ManyToManyField(Relation, related_name='dependants')

Обратите внимание, что разница только в том, объявлено ли поле m2m с помощью строки или класса модели.

Когда у меня есть внешняя модель в виде строки и я вызываю:

Relation.objects.filter(dependants=1)

Ошибка, которую я получаю:

FieldError: Cannot resolve keyword 'dependants' into field. Choices are: ...

Ни один из перечисленных вариантов не является dependants, в основном он недоступен.

Хотя это работает:

r = Relation.objects.first()
r.dependants

Использование импортированного класса модели решает мою конкретную проблему, но преимущество использования строкового класса для разрешения циклических зависимостей теряется. На случай, если это произойдет снова, может ли кто-нибудь пролить свет на то, почему это может произойти? Это известная ошибка, решенная в более поздних версиях Django или известное ограничение использования строк для указания классов?

Примечание, я попытался решить эту проблему следующим образом:

  • Упрощение обеих моделей, чтобы не было специальных менеджеров или других хаков кверисетов
  • .
  • Полная квалификация строки имени модели, например 'appname.Relation'
  • переименование как поля, так и связанного_имени в случае некоторого внутреннего конфликта
  • перестройка и запуск миграций
  • изменение запроса на Relation.objects.filter(dependants__id=1)

Я думаю, что вы получаете эту ошибку, потому что ваши два класса моделей не находятся в одном и том же приложении django. Но вы можете использовать строковую ссылку, но вы должны использовать строковую точечную нотацию, например 'app_label.model_class_name'

Вернуться на верх