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

如何为Django自定义User模型管理器适配mypy类型检查?

自定义Django用户管理器的mypy类型兼容问题

环境与代码

我正在使用Django 4.1.7、django-stubs 1.16.0和mypy 1.1.1,为自定义User模型编写了如下用户管理器:

from django.contrib.auth.models import UserManager, AbstractUser
from django.db import models

class MyUserManager(UserManager):
    def delete_test_data(self):
        return self.filter(test_data=True).delete()

class User(AbstractUser):
    test_data = models.BooleanField()
    # 省略其他字段定义
    objects = MyUserManager()

功能运行正常,但执行mypy检查时出现如下错误:

models.py:32: error: Incompatible types in assignment (expression has type "MyUserManager[User]", base class "AbstractUser" defined the type as "UserManager[AbstractUser]")  [assignment]

问题分析

这不是操作错误,也不是mypy的Bug,核心原因是django-stubs的类型定义约束:AbstractUser的objects字段被标注为UserManager[AbstractUser],而你的MyUserManager[User]虽为子类实例,但mypy默认不允许这种协变类型赋值(UserManager的类型参数在部分场景下属于逆变类型)。

无需忽略错误的类型适配方法

方法一:使用泛型TypeVar绑定模型类型

通过泛型明确管理器与用户模型的关联关系,让mypy认可类型兼容性:

from django.contrib.auth.models import UserManager, AbstractUser
from django.db import models
from typing import TypeVar

# 定义绑定AbstractUser的类型变量
UserType = TypeVar("UserType", bound=AbstractUser)

class MyUserManager(UserManager[UserType]):
    def delete_test_data(self) -> tuple[int, dict[str, int]]:
        # 显式标注返回类型,匹配Django delete方法的返回格式
        return self.filter(test_data=True).delete()

class User(AbstractUser):
    test_data = models.BooleanField(default=False)
    # 用字符串引号避免循环引用,显式标注objects类型
    objects: MyUserManager["User"] = MyUserManager()

方法二:显式覆盖父类的类型注解

直接在User类中给objects字段添加精确类型标注,让mypy识别子类类型的兼容性:

from django.contrib.auth.models import UserManager, AbstractUser
from django.db import models

class MyUserManager(UserManager):
    def delete_test_data(self) -> tuple[int, dict[str, int]]:
        return self.filter(test_data=True).delete()

class User(AbstractUser):
    test_data = models.BooleanField(default=False)
    # 显式标注objects的类型
    objects: MyUserManager["User"] = MyUserManager()

以上两种方法都能解决类型不兼容问题,无需通过# type: ignore忽略错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:12:43