Django: typehinting обратных / related_name / ForeignKey отношений
Допустим, у нас есть следующие модели:
class Site(models.Model):
# This is djangos build-in Site Model
pass
class Organization(models.Model):
site = models.OneToOneField(Site)
А если я использую это где-то в каком-то другом классе:
organization = self.site.organization
Тогда mypy жалуется:
Site has no attribute "organization"
Как я могу сделать так, чтобы mypy был счастлив здесь?
Я только немного знаю английский, и я не знаю, что это правда. Но вы можете добавить
site = models.OneToOneField(Site, on_delete=models.CASCADE)
Вам необходимо установить атрибут related_name
:
class Organization(models.Model):
site = models.OneToOneField(Site, related_name="organization")
Django добавляет обратные связи во время выполнения, которые не улавливаются mypy
, который делает только статический анализ.
Чтобы сделать mypy
счастливым (и заставить его работать с автозаполнением вашего редактора), вам нужно добавить явную подсказку типа к Site
:
class Site(models.Model):
organization: "Organization"
class Organization(models.Model):
site = models.OneToOneField(Site)
Использование кавычек вокруг типа необходимо, поскольку мы делаем переднюю ссылку на Organization
до того, как он был определен.
Для внешних ключей и отношений "многие-ко-многим" можно сделать то же самое, но используя вместо этого подсказку типа QuerySet
:
class Organization(models.Model):
site = models.OneToOneField(Site)
employees: models.QuerySet["Employee"]
class Employee(models.Model):
organization = models.ForeignKey(
Organization,
on_delete=models.CASCADE,
related_name="employees",
)
EDIT: Существует пакет django-stubs, который предназначен для интеграции с mypy
, однако лично я его не использовал. Он может обеспечить решение этой проблемы без необходимости явного добавления подсказок типов в модели.