Generic类类型提示问题:Mypy报attr-defined错误(Type[ModelType]无id属性)
解决Mypy报错:"Type[ModelType]" has no attribute "id"
问题原因
你定义的ModelType绑定了Base,但Mypy无法确认所有Base的子类都包含id类属性(即模型的表字段)。虽然你的实际业务模型都有id字段,但类型检查器没有这个明确信息,因此抛出attr-defined错误。
解决方案
方案1:给ModelType添加带id的Protocol约束
创建一个Protocol协议,明确要求类必须具备id属性,再让ModelType绑定到这个Protocol:
from typing import TypeVar, Generic, Protocol, Type from sqlalchemy.ext.declarative import Base from pydantic import BaseModel from sqlalchemy.orm import Session class HasId(Protocol): id: int # 可根据实际场景调整类型,比如SQLAlchemy的`Mapped[int]` ModelType = TypeVar("ModelType", bound=HasId) # 替换原有的bound=Base CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel) UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel) class BaseOperations(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): __abstract__ = True def __init__(self, model: Type[ModelType], db_session: Session): self.model = model self.db_session = db_session # 其余方法保持不变
方案2:让基类明确声明id属性
如果你的Base是SQLAlchemy的声明式基类,可以创建一个带id的抽象基类,让所有业务模型继承它,同时让ModelType绑定这个新基类:
from sqlalchemy import Column, Integer from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class BaseWithId(Base): __abstract__ = True id = Column(Integer, primary_key=True) # 调整ModelType的绑定目标 ModelType = TypeVar("ModelType", bound=BaseWithId)
方案3:类型断言(临时 workaround)
如果不想修改基类或协议,可以在使用self.model.id时用cast强制类型转换,但这会绕过类型检查,仅作为临时解决手段:
from typing import cast def get_by_id(self, id_: int) -> ModelType | None: if hasattr(self, "deleted"): return ( self.db_session.query(self.model) .filter(~self.deleted) .filter(cast(Type[HasId], self.model).id == id_) .first() ) return self.db_session.query(self.model).filter(cast(Type[HasId], self.model).id == id_).first()
额外说明
优先选择方案1或2,它们能让类型系统正确识别代码结构,避免后续类型问题。如果使用SQLAlchemy 2.0+,建议结合DeclarativeBase和Mapped定义模型,类型提示会更精准:
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column class Base(DeclarativeBase): pass class BaseWithId(Base): __abstract__ = True id: Mapped[int] = mapped_column(primary_key=True)
内容的提问来源于stack exchange,提问作者Asad Amir Khwaja
相关产品推荐
相关产品推荐

