You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何mypy结合django-stubs无法推断Django CharField选项类型?

Django模型字段与枚举类型的mypy类型不兼容问题原因分析

问题场景

模型定义

from django.db import models

class MyChoice(models.TextChoices):
    FOO = "foo", _("foo")
    BAR = "bar", _("bar")
    BAZ = "baz", _("baz")

class MyModel(models.Model):
    my_field = models.CharField(choices=MyChoice.choices, max_length=64)

函数调用与mypy错误

def use_choice(choice: MyChoice) -> None:
    pass

def call_use_choice(model: MyModel) -> None:
    use_choice(model.my_field)

# error: Argument 1 to "use_choice" has incompatible type "str"; expected "MyChoice"  [arg-type]

环境配置

pyproject.toml:

[tool.poetry.dependencies]
python = ">=3.10,<3.11"
Django = "^3.2.8"

[tool.poetry.dependencies]
mypy = "^1.1.1"
django-stubs = "^1.16.0"

mypy.ini:

[mypy]
python_version = 3.10
ignore_missing_imports = True
plugins =
    mypy_django_plugin.main

[mypy.plugins.django-stubs]
django_settings_module = "config.settings"

问题原因

  • Django字段的存储本质:models.CharField搭配TextChoices时,数据库中存储的是枚举的字符串值(比如"foo"),而非MyChoice枚举类的实例。当你从model.my_field取值时,得到的是原始字符串,不是MyChoice.FOO这类枚举对象。
  • django-stubs的类型推断逻辑:django-stubs对带choices的CharField,类型推断仍然是str,不会自动映射为对应的枚举类型。这是因为Django运行时并不会自动将数据库返回的字符串转换为枚举实例,类型工具也不会做这个隐式转换假设。
  • 类型不匹配:函数use_choice的参数要求是MyChoice枚举实例,但传入的model.my_field是字符串类型,因此mypy会检测到类型不兼容的错误。

内容的提问来源于stack exchange,提问作者tinom9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:33:30