【问题标题】:Type Hint for Django model with annotated field为带有注释字段的 Django 模型键入提示
【发布时间】:2022-01-10 17:50:15
【问题描述】:

假设我有以下 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)

我有一个功能可以为每个工具箱获取所有小工具。参数类型提示来自this SO answer

from django.db.models import QuerySet

def get_toolbox_to_small_tools_mappings(
    toolboxes: QuerySet | list[Toolbox],
) -> dict[Toolbox, list[Tool]]:
    return {toolbox: toolbox.small_tools for toolbox in toolboxes}

这里的想法是要求此函数的用户使用 prefetch_related() 预取此 small_tools 字段,以减少 db 命中次数并加快代码速度:

toolboxes = Toolbox.objects.prefetch_related(
    Prefetch(
        "tools",
        queryset=Tool.objects.filter(size=Tool.Size.SMALL),
        to_attr="small_tools",
    )
)
toolbox_to_small_tools_mappings = get_toolbox_to_small_tools_mappings(toolboxes)

这一切都很好,但 mypy 抱怨以下错误:

错误:“工具箱”没有属性“small_tools”[attr-defined]

有没有办法解决这个问题?

来自 django-subs (see here) 的 WithAnnotations[Model] 类型是一个选项,但它是 buggy

【问题讨论】:

    标签: python django type-hinting django-stubs


    【解决方案1】:

    我认为您最简单的解决方案是改用getattr

    from django.db.models import QuerySet
    
    def get_toolbox_to_small_tools_mappings(
        toolboxes: QuerySet | list[Toolbox],
    ) -> dict[Toolbox, list[Tool]]:
        return {toolbox: getattr(toolbox, "small_tools") for toolbox in toolboxes}
    

    这使事情变得简单,并保持相同的功能。我不喜欢这样做,但是当你开始在 Django 中做动态的事情时,它很快就会成为最简单的解决方案。

    【讨论】:

      猜你喜欢
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      • 2019-01-22
      • 2016-07-19
      • 2020-03-11
      • 2012-11-27
      • 1970-01-01
      相关资源
      最近更新 更多