本文阅读量 次
1. SQLModel¶
1.1 定义结构¶
1.2 插入数据¶
commit 之后 refresh
session commit 数据已经编辑为过期,如果想要获取最新数据,需要
- 显示刷新:
session.refresh(hero_1)
- 显示访问对象中的属性:
hero_name = hero_1.name
, 这个会触发底层执行一次 SQL 获取操作
1.3 查询数据¶
1.3.1 精确根据主键 id 查询¶
使用 get()
- 前提是该字段必须是
primary=True
- 如果该 id 指定数据不存在,则会抛异常
1.3.2 只查询指定列¶
[TODO]
1.3.3 一个条件¶
with Session(engine) as session:
statement = select(Hero).where(Hero.name == "Spider-Boy")
hero = session.exec(statement).first()
print(hero)
session.exec(select(Hero).where(Hero.id == user_id)).all()
1.3.4 多个条件¶
一个 where
中多个条件
with Session(engine) as session:
statement = select(Hero).where(Hero.name == "Spider-Boy", Hero.age > 18)
hero = session.exec(statement).first()
print(hero)
使用多次 where
with Session(engine) as session:
statement = select(Hero).where(Hero.name == "Spider-Boy").where(Hero.age > 18)
hero = session.exec(statement).first()
print(hero)
1.3.4.1 多个条件但是 or 语义¶
使用 or_
from sqlmodel import Field, Session, SQLModel, create_engine, or_, select
def select_heroes():
with Session(engine) as session:
statement = select(Hero).where(or_(Hero.age <= 35, Hero.age > 90))
results = session.exec(statement)
for hero in results:
print(hero)
1.3.4.2 如何动态生成查询条件¶
[TODO]
where
中比较用的字段名字要是用类下的字段,而不是实例下的;即要使用大写的 Hero
而不是示例级的 hero
1.3.5 只查询一行¶
两种方式: result.first()
或 result.one()
数据情况 | one() | first() |
---|---|---|
有且仅有一行满足条件的数据 | 正常返回 | 正常返回 |
没有满足条件的数据 | 抛异常 | None |
有多条满足条件的数据 | 抛异常 | 返回第一条 |
statement = select(Hero)
result = session.exec(statement)
obj = result.first()
[TODO] 需要看下这里的
first()
是limit 1
了,还是查会了所有数据,只交给调用方一个,如果是后者,则会有性能问题
1.3.6 指定 offset 和 limit¶
在 select()
后增加 limit(n)
和 offset(n)
def select_heroes():
with Session(engine) as session:
statement = select(Hero).offset(3).limit(3)
results = session.exec(statement)
heroes = results.all()
print(heroes)
[TODO]
1.4 更新数据¶
1.5 删除数据¶
1.5.1 先查后删除¶
def delete_heroes():
with Session(engine) as session:
statement = select(Hero).where(Hero.name == "Spider-Youngster")
results = session.exec(statement)
hero = results.one()
print("Hero: ", hero)
session.delete(hero)
session.commit()
1.5.2 直接条件删除¶
[TODO]
1.6 索引¶
1.6.1 声明索引¶
单字段索引
使用 Field(index=True)
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)
复合索引
1.6.1.1 索引声明时指定索引类型¶
1.6.1.2 索引声明时指定索引名字¶
1.6.2 索引声明时指定字段顺序¶
默认 SQLModel(SQLAlchemy) 会自动创建索引名字,规则是
索引声明如何携带额外参数
1.7 关联关系¶
1.7.1 关系声明¶
1.7.1.1 1-m/m-1 关系¶
1.7.1.2 m-n 关系¶
class HeroTeamLink(SQLModel, table=True):
team_id: int | None = Field(default=None, foreign_key="team.id", primary_key=True)
hero_id: int | None = Field(default=None, foreign_key="hero.id", primary_key=True)
class Team(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str = Field(index=True)
headquarters: str
heroes: list["Hero"] = Relationship(back_populates="teams", link_model=HeroTeamLink)
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)
teams: list[Team] = Relationship(back_populates="heroes", link_model=HeroTeamLink)
1.7.1.3 声明关系但不用外键¶
1.7.1.4 关系表的额外字段¶
class HeroTeamLink(SQLModel, table=True):
team_id: int | None = Field(default=None, foreign_key="team.id", primary_key=True)
hero_id: int | None = Field(default=None, foreign_key="hero.id", primary_key=True)
is_training: bool = False
team: "Team" = Relationship(back_populates="hero_links")
hero: "Hero" = Relationship(back_populates="team_links")