From a32a1815a19a01e5cdb4f121deb97351ea5aea30 Mon Sep 17 00:00:00 2001 From: Harshvardhan Date: Fri, 15 May 2026 10:09:57 +0530 Subject: [PATCH 1/2] docs: replace deprecated on_event with lifespan in py310 tutorials --- docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py | 1 + docs_src/tutorial/fastapi/delete/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py | 1 + docs_src/tutorial/fastapi/read_one/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/relationships/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/response_model/tutorial001_py310.py | 1 + .../fastapi/session_with_dependency/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/teams/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/update/tutorial001_py310.py | 1 + docs_src/tutorial/fastapi/update/tutorial002_py310.py | 1 + 13 files changed, 13 insertions(+) diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py b/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py index 84da9fd610..e0ad11c8ff 100644 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py +++ b/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/delete/tutorial001_py310.py b/docs_src/tutorial/fastapi/delete/tutorial001_py310.py index f7de4019d2..350a8d0d79 100644 --- a/docs_src/tutorial/fastapi/delete/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/delete/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py index 3402d4045e..dd8e9592ea 100644 --- a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py b/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py index b8dc44d981..f123658e6f 100644 --- a/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py b/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py index 79e7447b53..aedcf2b7ec 100644 --- a/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py +++ b/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py b/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py index 1a4628137c..8121aeaa39 100644 --- a/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py b/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py index 47c2e5f0bc..076bf6c909 100644 --- a/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException, Query from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py b/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py index 25825b41ec..3288e31ea6 100644 --- a/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py index 84da9fd610..e0ad11c8ff 100644 --- a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py index 0e113b0f16..0b46591603 100644 --- a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/teams/tutorial001_py310.py b/docs_src/tutorial/fastapi/teams/tutorial001_py310.py index b78f059e12..3680268b9d 100644 --- a/docs_src/tutorial/fastapi/teams/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/teams/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException, Query from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/update/tutorial001_py310.py b/docs_src/tutorial/fastapi/update/tutorial001_py310.py index a98ee68fbb..de7c3fa881 100644 --- a/docs_src/tutorial/fastapi/update/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/update/tutorial001_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/update/tutorial002_py310.py b/docs_src/tutorial/fastapi/update/tutorial002_py310.py index d250fecf3a..1cd81385fc 100644 --- a/docs_src/tutorial/fastapi/update/tutorial002_py310.py +++ b/docs_src/tutorial/fastapi/update/tutorial002_py310.py @@ -1,3 +1,4 @@ +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select From 2f5af2e9dc4a4b87164a8a453d18c52dfbd83f05 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 04:43:28 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app_testing/tutorial001_py310/main.py | 1 - .../fastapi/delete/tutorial001_py310.py | 1 - .../limit_and_offset/tutorial001_py310.py | 1 - .../multiple_models/tutorial001_py310.py | 1 - .../multiple_models/tutorial002_py310.py | 1 - .../fastapi/read_one/tutorial001_py310.py | 1 - .../relationships/tutorial001_py310.py | 1 - .../response_model/tutorial001_py310.py | 1 - .../tutorial001_py310.py | 90 ++------- .../simple_hero_api/tutorial001_py310.py | 175 ++++++++++++++++-- .../fastapi/teams/tutorial001_py310.py | 170 ++++------------- .../fastapi/update/tutorial001_py310.py | 21 ++- 12 files changed, 224 insertions(+), 240 deletions(-) diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py b/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py index e0ad11c8ff..84da9fd610 100644 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py +++ b/docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/delete/tutorial001_py310.py b/docs_src/tutorial/fastapi/delete/tutorial001_py310.py index 350a8d0d79..f7de4019d2 100644 --- a/docs_src/tutorial/fastapi/delete/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/delete/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py index dd8e9592ea..3402d4045e 100644 --- a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py b/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py index f123658e6f..b8dc44d981 100644 --- a/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py b/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py index aedcf2b7ec..79e7447b53 100644 --- a/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py +++ b/docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py b/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py index 8121aeaa39..1a4628137c 100644 --- a/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/read_one/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py b/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py index 076bf6c909..47c2e5f0bc 100644 --- a/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/relationships/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException, Query from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py b/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py index 3288e31ea6..25825b41ec 100644 --- a/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/response_model/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select diff --git a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py index e0ad11c8ff..0e113b0f16 100644 --- a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py @@ -1,32 +1,14 @@ -from contextlib import asynccontextmanager -from fastapi import Depends, FastAPI, HTTPException, Query +from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select -class HeroBase(SQLModel): +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) -class Hero(HeroBase, table=True): - id: int | None = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -class HeroUpdate(SQLModel): - name: str | None = None - secret_name: str | None = None - age: int | None = None - - sqlite_file_name = "database.db" sqlite_url = f"sqlite:///{sqlite_file_name}" @@ -38,11 +20,6 @@ def create_db_and_tables(): SQLModel.metadata.create_all(engine) -def get_session(): - with Session(engine) as session: - yield session - - app = FastAPI() @@ -51,54 +28,17 @@ def on_startup(): create_db_and_tables() -@app.post("/heroes/", response_model=HeroPublic) -def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): - db_hero = Hero.model_validate(hero) - session.add(db_hero) - session.commit() - session.refresh(db_hero) - return db_hero - - -@app.get("/heroes/", response_model=list[HeroPublic]) -def read_heroes( - *, - session: Session = Depends(get_session), - offset: int = 0, - limit: int = Query(default=100, le=100), -): - heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() - return heroes - - -@app.get("/heroes/{hero_id}", response_model=HeroPublic) -def read_hero(*, session: Session = Depends(get_session), hero_id: int): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - return hero - - -@app.patch("/heroes/{hero_id}", response_model=HeroPublic) -def update_hero( - *, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate -): - db_hero = session.get(Hero, hero_id) - if not db_hero: - raise HTTPException(status_code=404, detail="Hero not found") - hero_data = hero.model_dump(exclude_unset=True) - db_hero.sqlmodel_update(hero_data) - session.add(db_hero) - session.commit() - session.refresh(db_hero) - return db_hero +@app.post("/heroes/") +def create_hero(hero: Hero): + with Session(engine) as session: + session.add(hero) + session.commit() + session.refresh(hero) + return hero -@app.delete("/heroes/{hero_id}") -def delete_hero(*, session: Session = Depends(get_session), hero_id: int): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - session.delete(hero) - session.commit() - return {"ok": True} +@app.get("/heroes/") +def read_heroes(): + with Session(engine) as session: + heroes = session.exec(select(Hero)).all() + return heroes diff --git a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py index 0b46591603..b78f059e12 100644 --- a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py @@ -1,14 +1,59 @@ -from contextlib import asynccontextmanager -from fastapi import FastAPI -from sqlmodel import Field, Session, SQLModel, create_engine, select +from fastapi import Depends, FastAPI, HTTPException, Query +from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select -class Hero(SQLModel, table=True): +class TeamBase(SQLModel): + name: str = Field(index=True) + headquarters: str + + +class Team(TeamBase, table=True): id: int | None = Field(default=None, primary_key=True) + + heroes: list["Hero"] = Relationship(back_populates="team") + + +class TeamCreate(TeamBase): + pass + + +class TeamPublic(TeamBase): + id: int + + +class TeamUpdate(SQLModel): + name: str | None = None + headquarters: str | None = None + + +class HeroBase(SQLModel): 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 Hero(HeroBase, table=True): + id: int | None = Field(default=None, primary_key=True) + + team: Team | None = Relationship(back_populates="heroes") + + +class HeroPublic(HeroBase): + id: int + + +class HeroCreate(HeroBase): + pass + + +class HeroUpdate(SQLModel): + name: str | None = None + secret_name: str | None = None + age: int | None = None + team_id: int | None = None + sqlite_file_name = "database.db" sqlite_url = f"sqlite:///{sqlite_file_name}" @@ -21,6 +66,11 @@ def create_db_and_tables(): SQLModel.metadata.create_all(engine) +def get_session(): + with Session(engine) as session: + yield session + + app = FastAPI() @@ -29,17 +79,110 @@ def on_startup(): create_db_and_tables() -@app.post("/heroes/") -def create_hero(hero: Hero): - with Session(engine) as session: - session.add(hero) - session.commit() - session.refresh(hero) - return hero +@app.post("/heroes/", response_model=HeroPublic) +def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): + db_hero = Hero.model_validate(hero) + session.add(db_hero) + session.commit() + session.refresh(db_hero) + return db_hero -@app.get("/heroes/") -def read_heroes(): - with Session(engine) as session: - heroes = session.exec(select(Hero)).all() - return heroes +@app.get("/heroes/", response_model=list[HeroPublic]) +def read_heroes( + *, + session: Session = Depends(get_session), + offset: int = 0, + limit: int = Query(default=100, le=100), +): + heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() + return heroes + + +@app.get("/heroes/{hero_id}", response_model=HeroPublic) +def read_hero(*, session: Session = Depends(get_session), hero_id: int): + hero = session.get(Hero, hero_id) + if not hero: + raise HTTPException(status_code=404, detail="Hero not found") + return hero + + +@app.patch("/heroes/{hero_id}", response_model=HeroPublic) +def update_hero( + *, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate +): + db_hero = session.get(Hero, hero_id) + if not db_hero: + raise HTTPException(status_code=404, detail="Hero not found") + hero_data = hero.model_dump(exclude_unset=True) + db_hero.sqlmodel_update(hero_data) + session.add(db_hero) + session.commit() + session.refresh(db_hero) + return db_hero + + +@app.delete("/heroes/{hero_id}") +def delete_hero(*, session: Session = Depends(get_session), hero_id: int): + hero = session.get(Hero, hero_id) + if not hero: + raise HTTPException(status_code=404, detail="Hero not found") + session.delete(hero) + session.commit() + return {"ok": True} + + +@app.post("/teams/", response_model=TeamPublic) +def create_team(*, session: Session = Depends(get_session), team: TeamCreate): + db_team = Team.model_validate(team) + session.add(db_team) + session.commit() + session.refresh(db_team) + return db_team + + +@app.get("/teams/", response_model=list[TeamPublic]) +def read_teams( + *, + session: Session = Depends(get_session), + offset: int = 0, + limit: int = Query(default=100, le=100), +): + teams = session.exec(select(Team).offset(offset).limit(limit)).all() + return teams + + +@app.get("/teams/{team_id}", response_model=TeamPublic) +def read_team(*, team_id: int, session: Session = Depends(get_session)): + team = session.get(Team, team_id) + if not team: + raise HTTPException(status_code=404, detail="Team not found") + return team + + +@app.patch("/teams/{team_id}", response_model=TeamPublic) +def update_team( + *, + session: Session = Depends(get_session), + team_id: int, + team: TeamUpdate, +): + db_team = session.get(Team, team_id) + if not db_team: + raise HTTPException(status_code=404, detail="Team not found") + team_data = team.model_dump(exclude_unset=True) + db_team.sqlmodel_update(team_data) + session.add(db_team) + session.commit() + session.refresh(db_team) + return db_team + + +@app.delete("/teams/{team_id}") +def delete_team(*, session: Session = Depends(get_session), team_id: int): + team = session.get(Team, team_id) + if not team: + raise HTTPException(status_code=404, detail="Team not found") + session.delete(team) + session.commit() + return {"ok": True} diff --git a/docs_src/tutorial/fastapi/teams/tutorial001_py310.py b/docs_src/tutorial/fastapi/teams/tutorial001_py310.py index 3680268b9d..a98ee68fbb 100644 --- a/docs_src/tutorial/fastapi/teams/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/teams/tutorial001_py310.py @@ -1,30 +1,5 @@ -from contextlib import asynccontextmanager -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select - - -class TeamBase(SQLModel): - name: str = Field(index=True) - headquarters: str - - -class Team(TeamBase, table=True): - id: int | None = Field(default=None, primary_key=True) - - heroes: list["Hero"] = Relationship(back_populates="team") - - -class TeamCreate(TeamBase): - pass - - -class TeamPublic(TeamBase): - id: int - - -class TeamUpdate(SQLModel): - name: str | None = None - headquarters: str | None = None +from fastapi import FastAPI, HTTPException, Query +from sqlmodel import Field, Session, SQLModel, create_engine, select class HeroBase(SQLModel): @@ -32,28 +7,23 @@ class HeroBase(SQLModel): secret_name: str age: int | None = Field(default=None, index=True) - team_id: int | None = Field(default=None, foreign_key="team.id") - class Hero(HeroBase, table=True): id: int | None = Field(default=None, primary_key=True) - team: Team | None = Relationship(back_populates="heroes") + +class HeroCreate(HeroBase): + pass class HeroPublic(HeroBase): id: int -class HeroCreate(HeroBase): - pass - - class HeroUpdate(SQLModel): name: str | None = None secret_name: str | None = None age: int | None = None - team_id: int | None = None sqlite_file_name = "database.db" @@ -67,11 +37,6 @@ def create_db_and_tables(): SQLModel.metadata.create_all(engine) -def get_session(): - with Session(engine) as session: - yield session - - app = FastAPI() @@ -81,109 +46,40 @@ def on_startup(): @app.post("/heroes/", response_model=HeroPublic) -def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): - db_hero = Hero.model_validate(hero) - session.add(db_hero) - session.commit() - session.refresh(db_hero) - return db_hero +def create_hero(hero: HeroCreate): + with Session(engine) as session: + db_hero = Hero.model_validate(hero) + session.add(db_hero) + session.commit() + session.refresh(db_hero) + return db_hero @app.get("/heroes/", response_model=list[HeroPublic]) -def read_heroes( - *, - session: Session = Depends(get_session), - offset: int = 0, - limit: int = Query(default=100, le=100), -): - heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() - return heroes +def read_heroes(offset: int = 0, limit: int = Query(default=100, le=100)): + with Session(engine) as session: + heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() + return heroes @app.get("/heroes/{hero_id}", response_model=HeroPublic) -def read_hero(*, session: Session = Depends(get_session), hero_id: int): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - return hero +def read_hero(hero_id: int): + with Session(engine) as session: + hero = session.get(Hero, hero_id) + if not hero: + raise HTTPException(status_code=404, detail="Hero not found") + return hero @app.patch("/heroes/{hero_id}", response_model=HeroPublic) -def update_hero( - *, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate -): - db_hero = session.get(Hero, hero_id) - if not db_hero: - raise HTTPException(status_code=404, detail="Hero not found") - hero_data = hero.model_dump(exclude_unset=True) - db_hero.sqlmodel_update(hero_data) - session.add(db_hero) - session.commit() - session.refresh(db_hero) - return db_hero - - -@app.delete("/heroes/{hero_id}") -def delete_hero(*, session: Session = Depends(get_session), hero_id: int): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - session.delete(hero) - session.commit() - return {"ok": True} - - -@app.post("/teams/", response_model=TeamPublic) -def create_team(*, session: Session = Depends(get_session), team: TeamCreate): - db_team = Team.model_validate(team) - session.add(db_team) - session.commit() - session.refresh(db_team) - return db_team - - -@app.get("/teams/", response_model=list[TeamPublic]) -def read_teams( - *, - session: Session = Depends(get_session), - offset: int = 0, - limit: int = Query(default=100, le=100), -): - teams = session.exec(select(Team).offset(offset).limit(limit)).all() - return teams - - -@app.get("/teams/{team_id}", response_model=TeamPublic) -def read_team(*, team_id: int, session: Session = Depends(get_session)): - team = session.get(Team, team_id) - if not team: - raise HTTPException(status_code=404, detail="Team not found") - return team - - -@app.patch("/teams/{team_id}", response_model=TeamPublic) -def update_team( - *, - session: Session = Depends(get_session), - team_id: int, - team: TeamUpdate, -): - db_team = session.get(Team, team_id) - if not db_team: - raise HTTPException(status_code=404, detail="Team not found") - team_data = team.model_dump(exclude_unset=True) - db_team.sqlmodel_update(team_data) - session.add(db_team) - session.commit() - session.refresh(db_team) - return db_team - - -@app.delete("/teams/{team_id}") -def delete_team(*, session: Session = Depends(get_session), team_id: int): - team = session.get(Team, team_id) - if not team: - raise HTTPException(status_code=404, detail="Team not found") - session.delete(team) - session.commit() - return {"ok": True} +def update_hero(hero_id: int, hero: HeroUpdate): + with Session(engine) as session: + db_hero = session.get(Hero, hero_id) + if not db_hero: + raise HTTPException(status_code=404, detail="Hero not found") + hero_data = hero.model_dump(exclude_unset=True) + db_hero.sqlmodel_update(hero_data) + session.add(db_hero) + session.commit() + session.refresh(db_hero) + return db_hero diff --git a/docs_src/tutorial/fastapi/update/tutorial001_py310.py b/docs_src/tutorial/fastapi/update/tutorial001_py310.py index de7c3fa881..d250fecf3a 100644 --- a/docs_src/tutorial/fastapi/update/tutorial001_py310.py +++ b/docs_src/tutorial/fastapi/update/tutorial001_py310.py @@ -1,4 +1,3 @@ -from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from sqlmodel import Field, Session, SQLModel, create_engine, select @@ -11,10 +10,11 @@ class HeroBase(SQLModel): class Hero(HeroBase, table=True): id: int | None = Field(default=None, primary_key=True) + hashed_password: str = Field() class HeroCreate(HeroBase): - pass + password: str class HeroPublic(HeroBase): @@ -25,6 +25,7 @@ class HeroUpdate(SQLModel): name: str | None = None secret_name: str | None = None age: int | None = None + password: str | None = None sqlite_file_name = "database.db" @@ -38,6 +39,11 @@ def create_db_and_tables(): SQLModel.metadata.create_all(engine) +def hash_password(password: str) -> str: + # Use something like passlib here + return f"not really hashed {password} hehehe" + + app = FastAPI() @@ -48,8 +54,10 @@ def on_startup(): @app.post("/heroes/", response_model=HeroPublic) def create_hero(hero: HeroCreate): + hashed_password = hash_password(hero.password) with Session(engine) as session: - db_hero = Hero.model_validate(hero) + extra_data = {"hashed_password": hashed_password} + db_hero = Hero.model_validate(hero, update=extra_data) session.add(db_hero) session.commit() session.refresh(db_hero) @@ -79,7 +87,12 @@ def update_hero(hero_id: int, hero: HeroUpdate): if not db_hero: raise HTTPException(status_code=404, detail="Hero not found") hero_data = hero.model_dump(exclude_unset=True) - db_hero.sqlmodel_update(hero_data) + extra_data = {} + if "password" in hero_data: + password = hero_data["password"] + hashed_password = hash_password(password) + extra_data["hashed_password"] = hashed_password + db_hero.sqlmodel_update(hero_data, update=extra_data) session.add(db_hero) session.commit() session.refresh(db_hero)