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

如何在SQLModel中创建SQL视图?附Hero与Team关联表示例

在SQLModel中创建视图的实现方案

SQLModel本身未提供直接定义视图的API,但它基于SQLAlchemy构建,因此可以借助SQLAlchemy的CreateView对象实现视图创建。以下是针对你的Hero和Team表,创建展示英雄姓名及对应团队名称视图的具体步骤:

1. 定义视图对应的模型类

先定义一个与视图结构匹配的SQLModel类,无需设置table=True(它对应数据库视图而非物理表):

from sqlmodel import SQLModel, Field

class HeroTeamView(SQLModel):
    hero_name: str = Field(alias="name")
    team_name: str | None = Field(alias="team_name")

    class Config:
        orm_mode = True

2. 构建视图SQL并创建视图

导入SQLAlchemy工具后,在数据库初始化流程中添加视图创建逻辑:

from sqlalchemy import text
from sqlalchemy.sql.schema import CreateView

def create_db_and_tables():
    # 先创建物理表
    SQLModel.metadata.create_all(engine)
    
    # 定义视图查询语句,用LEFT JOIN保留无团队的英雄
    view_sql = text("""
        SELECT 
            hero.name,
            team.name AS team_name
        FROM hero
        LEFT JOIN team ON hero.team_id = team.id
    """)
    
    # 创建视图对象并绑定到metadata
    hero_team_view = CreateView(
        "hero_team_view",
        view_sql,
        metadata=SQLModel.metadata
    )
    
    # 执行视图创建
    with engine.connect() as conn:
        conn.execute(hero_team_view)
        conn.commit()

3. 查询视图数据

视图创建完成后,可像查询普通模型一样查询视图:

def query_hero_team_view():
    with Session(engine) as session:
        hero_teams = session.query(HeroTeamView).all()
        print("\n英雄与团队对应关系:")
        for item in hero_teams:
            print(f"英雄: {item.hero_name}, 所属团队: {item.team_name or '无'}")

完整修改后的代码

将上述逻辑整合到原代码中,完整代码如下:

from sqlmodel import Field, Session, SQLModel, create_engine
from sqlalchemy import text
from sqlalchemy.sql.schema import CreateView


class Team(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    headquarters: str


class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    secret_name: str
    age: int | None = Field(default=None, index=True)

    team_id: int | None = Field(default=None, foreign_key="team.id")


class HeroTeamView(SQLModel):
    hero_name: str = Field(alias="name")
    team_name: str | None = Field(alias="team_name")

    class Config:
        orm_mode = True


sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"

engine = create_engine(sqlite_url, echo=True)


def create_db_and_tables():
    SQLModel.metadata.create_all(engine)
    
    view_sql = text("""
        SELECT 
            hero.name,
            team.name AS team_name
        FROM hero
        LEFT JOIN team ON hero.team_id = team.id
    """)
    
    hero_team_view = CreateView(
        "hero_team_view",
        view_sql,
        metadata=SQLModel.metadata
    )
    
    with engine.connect() as conn:
        conn.execute(hero_team_view)
        conn.commit()


def create_heroes():
    with Session(engine) as session:
        team_preventers = Team(name="Preventers", headquarters="Sharp Tower")
        team_z_force = Team(name="Z-Force", headquarters="Sister Margaret's Bar")
        session.add(team_preventers)
        session.add(team_z_force)
        session.commit()

        hero_deadpond = Hero(
            name="Deadpond", secret_name="Dive Wilson", team_id=team_z_force.id
        )
        hero_rusty_man = Hero(
            name="Rusty-Man",
            secret_name="Tommy Sharp",
            age=48,
            team_id=team_preventers.id,
        )
        hero_spider_boy = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
        session.add(hero_deadpond)
        session.add(hero_rusty_man)
        session.add(hero_spider_boy)
        session.commit()

        session.refresh(hero_deadpond)
        session.refresh(hero_rusty_man)
        session.refresh(hero_spider_boy)

        print("Created hero:", hero_deadpond)
        print("Created hero:", hero_rusty_man)
        print("Created hero:", hero_spider_boy)


def query_hero_team_view():
    with Session(engine) as session:
        hero_teams = session.query(HeroTeamView).all()
        print("\n英雄与团队对应关系:")
        for item in hero_teams:
            print(f"英雄: {item.hero_name}, 所属团队: {item.team_name or '无'}")


def main():
    create_db_and_tables()
    create_heroes()
    query_hero_team_view()


if __name__ == "__main__":
    main()

关键说明

  • 视图创建需在物理表之后执行,避免表不存在的错误。
  • HeroTeamView类通过alias属性映射视图查询字段,orm_mode=True确保SQLModel能将查询结果转为模型实例。
  • 使用LEFT JOIN保证无团队的英雄也能被查询到,符合业务需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 09:23:14