#python #django #django-orm #type-hinting #prefetch
#python #django #django-orm #подсказка типа #предварительная выборка
Вопрос:
Допустим, у меня есть следующие модели Django:
class Toolbox(models.Model):
name = models.CharField(max_length=255)
tools = models.ManyToManyField("Tool")
class Tool(models.Model):
class Size(models.TextChoices):
SMALL = "S"
MEDIUM = "M"
LARGE = "L"
name = models.CharField(max_length=255)
size = models.CharField(max_length=10, choices=Size.choices)
У меня есть функция для получения всех небольших инструментов для каждого набора инструментов. Это @queries_disabled()
происходит из django-zen-queries, чтобы убедиться, что небольшие инструменты были предварительно выбраны и избежать проблем с производительностью N 1.
@queries_disabled()
def get_toolbox_to_small_tools_mappings(toolboxes: list[Toolbox]) -> dict:
return {toolbox: toolbox.small_tools for toolbox in toolboxes}
Проблема в том, что мой редактор (PyCharm) выдает предупреждение:
Неразрешенная ссылка на атрибут ‘small_tools’ для класса ‘Toolbox’
Я могу исправить это, изменив подсказку типа аргумента:
def get_toolbox_to_small_tools_mappings(toolboxes: list[Toolbox] | QuerySet): ...
Мне это кажется немного странным. Есть ли лучший способ исправить это?
Более того, я хотел бы предоставить полезное сообщение об ошибке вызывающей функции, если они забудут выполнить предварительную выборку этих данных. Прямо сейчас сообщение об ошибке:
Ошибка атрибута: объект «Toolbox» не имеет атрибута «small_tools»
Как я могу предоставить более явное сообщение об ошибке, в котором говорится что-то вроде:
Объект «Toolbox» не имеет атрибута «small_tools». Вы должны выполнить предварительную выборку этого поля.
Комментарии:
1. Из любопытства, почему это кажется хакерским? Наборы инструментов будут здесь набором запросов, верно?
2. Мне не нравится
Union
здесь. Я бы предпочел сделать что-то вродеQuerySet[Toolbox]
. Но это кажется невозможным, основываясь на моих исследованиях.3. Да, не без django-заглушек. WRT сообщение об ошибке, не могли бы вы перехватить AttributeError и создать собственное исключение?
4. Похоже , что примечания из django-stubs — это то, что мне здесь нужно