如何为SQLAlchemy中继承的Column类启用类型提示?
解决SQLAlchemy自定义非空列的类型提示问题
你的问题根源是自定义NotNullColumn没有继承SQLAlchemy Column的泛型特性——SQLAlchemy 2.0的Column是泛型类(Column[T]),T对应字段的Python类型,而你的实现丢失了这个泛型参数,导致mypy无法推断具体类型。
修正后的NotNullColumn代码
from typing import TypeVar, Generic from sqlalchemy import Column # 定义类型变量,用于传递泛型参数 T = TypeVar("T") class NotNullColumn(Column[T], Generic[T]): def __init__(self, *args, **kwargs): # 强制设置nullable=False,覆盖传入的参数 super().__init__(*args, **kwargs, nullable=False) @property def _constructor(self): # 返回自身类,确保链式调用时保留非空约束和类型信息 return NotNullColumn
关键修改点
- 添加泛型支持:通过
TypeVar和Generic让NotNullColumn继承Column[T],使其能像原生Column一样携带具体类型参数(比如Boolean对应bool)。 - 修正构造器返回值:原代码返回
Column会导致链式操作丢失自定义类特性,现在返回NotNullColumn,保证类型提示和约束的一致性。
模型中的正确使用
修改后,NotNullColumn的类型提示会和原生Column完全一致:
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, Text, func from sqlalchemy.orm import relationship, Mapped from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Notification(Base): __tablename__ = "core_notification" id: Mapped[int] = Column(Integer, primary_key=True, autoincrement=True) user_id: Mapped[int] = Column(ForeignKey("auth_user.id", ondelete="CASCADE")) user: Mapped["User"] = relationship("User", backref="notifications") message: Mapped[str | None] = Column(Text) sent_at: Mapped[datetime] = Column(DateTime, default=func.now()) # 现在mypy会正确识别status的类型为Column[bool] status: Mapped[bool] = NotNullColumn(Boolean)
如果不使用Mapped(旧版标注方式),同样能获得正确的类型提示:
status = NotNullColumn(Boolean) # mypy推断为NotNullColumn[bool]
此时给status赋值布尔值不会触发mypy错误,同时数据库字段会强制非空。
内容的提问来源于stack exchange,提问作者Miradil Zeynalli
相关产品推荐
相关产品推荐

