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

SQLAlchemy模型字段类型标注及关联关系类型疑问

SQLAlchemy模型类型标注指南

一、基础字段的类型标注

SQLAlchemy 2.0+官方推荐使用Mapped和mapped_column组合做类型标注,这能准确映射数据库列对应的Python类型,同时让类型检查工具(如mypy、Pyright)正确识别字段的实际取值类型,而非Column对象本身。

修正你的Email模型示例:

from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import String, ForeignKey
import uuid
from sqlalchemy.dialects.postgresql import UUID

class Email(Model):
    __tablename__ = 'emails'

    name: Mapped[str] = mapped_column(String, nullable=False)
    sender: Mapped[str] = mapped_column(String, default=default_sender, nullable=False)
    subject: Mapped[str] = mapped_column(String, nullable=False)
    html: Mapped[str] = mapped_column(String, nullable=False)
    template_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey('templates.id'),
        index=True,
    )
  • Mapped[T]中的T就是你实际存取时用到的Python基础类型(如str、uuid.UUID)
  • mapped_column是Column的类型安全封装,用来定义数据库列的属性

二、可空字段的标注方式

正确写法是Mapped[Optional[T]],因为nullable=True表示字段取值可以为None,而非整个列对象为None。

示例:

# 可空的字符串字段
description: Mapped[Optional[str]] = mapped_column(String, nullable=True)
  • 不要用Optional[Column[str]],这会被类型检查器误解为"列对象本身可能不存在",不符合ORM模型的定义逻辑。

三、关联关系的类型标注

关联关系的标注要根据lazy参数的取值调整,不同lazy会返回不同类型的结果:

1. 默认lazy='select'(即时加载)

  • 一对多关系:返回列表,标注为Mapped[list[关联模型]]
  • 一对一关系:返回单个对象(或None),标注为Mapped[Optional[关联模型]](如果可空)

示例:

class Foo(Model):
    # 一对多关联Bar
    bars: Mapped[list[Bar]] = relationship('Bar', order_by=Bar.created_at.desc())

2. lazy='dynamic'(动态查询)

此时访问关联属性会返回一个Query对象(同步)或AsyncQuery(异步),需要标注对应的查询类型:

from sqlalchemy.orm import Query

class Foo(Model):
    # ...其他字段
    bar: Mapped[Query[Bar]] = relationship(
        'Bar',
        order_by="desc(Bar.created_at)",
        lazy='dynamic',
    )

异步场景替换为AsyncQuery:

from sqlalchemy.ext.asyncio import AsyncQuery

class Foo(Model):
    bar: Mapped[AsyncQuery[Bar]] = relationship(
        'Bar',
        order_by="desc(Bar.created_at)",
        lazy='dynamic',
    )

3. lazy='joined'/'selectin'等其他加载方式

这类加载方式最终返回实体对象/列表,标注方式和默认lazy='select'一致,因为它们只是加载策略不同,返回值类型不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 09:15:34