From: Yurii Motov Date: Wed, 24 Dec 2025 21:32:20 +0000 (+0100) Subject: Update `docs_src/tutorial/fastapi` X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d603cc19ddd517f060f0a125d596fdc2177a25e8;p=thirdparty%2Ffastapi%2Fsqlmodel.git Update `docs_src/tutorial/fastapi` --- diff --git a/docs/tutorial/fastapi/tests.md b/docs/tutorial/fastapi/tests.md index ed4f91bc..f7fd92c9 100644 --- a/docs/tutorial/fastapi/tests.md +++ b/docs/tutorial/fastapi/tests.md @@ -14,7 +14,7 @@ We will use the application with the hero models, but without team models, and w Now we will see how useful it is to have this session dependency. ✨ -{* ./docs_src/tutorial/fastapi/app_testing/tutorial001/main.py ln[0] *} +{* ./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py ln[0] *} ## File Structure @@ -53,16 +53,16 @@ $ pip install requests pytest Let's start with a simple test, with just the basic test code we need the check that the **FastAPI** application is creating a new hero correctly. ```{ .python .annotate } -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_001.py[ln:1-7]!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_001.py[ln:1-7]!} # Some code here omitted, we will see it later 👈 -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_001.py[ln:20-24]!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_001.py[ln:20-24]!} # Some code here omitted, we will see it later 👈 -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_001.py[ln:26-32]!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_001.py[ln:26-32]!} # Code below omitted 👇 ``` -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_001.md!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/annotations/en/test_main_001.md!} /// tip @@ -103,14 +103,14 @@ We will override it to use a different **session** object just for the tests. That way we protect the production database and we have better control of the data we are testing. ```{ .python .annotate hl_lines="4 9-10 12 19" } -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_002.py[ln:1-7]!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_002.py[ln:1-7]!} # Some code here omitted, we will see it later 👈 -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_002.py[ln:15-32]!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_002.py[ln:15-32]!} # Code below omitted 👇 ``` -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_002.md!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/annotations/en/test_main_002.md!} /// tip @@ -131,10 +131,10 @@ sqlite:///testing.db So, the testing database will be in the file `testing.db`. ``` { .python .annotate hl_lines="4 8-11 13 16 33"} -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_003.py!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_003.py!} ``` -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_003.md!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/annotations/en/test_main_003.md!} ### Import Table Models @@ -187,12 +187,12 @@ Let's update our code to use the in-memory database. We just have to change a couple of parameters in the **engine**. ```{ .python .annotate hl_lines="3 9-13"} -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_004.py[ln:1-13]!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/test_main_004.py[ln:1-13]!} # Code below omitted 👇 ``` -{!./docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_004.md!} +{!./docs_src/tutorial/fastapi/app_testing/tutorial001_py310/annotations/en/test_main_004.md!} /// tip @@ -235,10 +235,10 @@ You can read more about them in the SQLAlchemy documentation about Using a Memory Database in Multiple Threads - - /// diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_005.md b/docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_005.md deleted file mode 100644 index 126e1f17..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_005.md +++ /dev/null @@ -1,41 +0,0 @@ -1. Import `pytest`. - -2. Use the `@pytest.fixture()` decorator on top of the function to tell pytest that this is a **fixture** function (equivalent to a FastAPI dependency). - - We also give it a name of `"session"`, this will be important in the testing function. - -3. Create the fixture function. This is equivalent to a FastAPI dependency function. - - In this fixture we create the custom **engine**, with the in-memory database, we create the tables, and we create the **session**. - - Then we `yield` the `session` object. - -4. The thing that we `return` or `yield` is what will be available to the test function, in this case, the `session` object. - - Here we use `yield` so that **pytest** comes back to execute "the rest of the code" in this function once the testing function is done. - - We don't have any more visible "rest of the code" after the `yield`, but we have the end of the `with` block that will close the **session**. - - By using `yield`, pytest will: - - * run the first part - * create the **session** object - * give it to the test function - * run the test function - * once the test function is done, it will continue here, right after the `yield`, and will correctly close the **session** object in the end of the `with` block. - -5. Now, in the test function, to tell **pytest** that this test wants to get the fixture, instead of declaring something like in FastAPI with: - - ```Python - session: Session = Depends(session_fixture) - ``` - - ...the way we tell pytest what is the fixture that we want is by using the **exact same name** of the fixture. - - In this case, we named it `session`, so the parameter has to be exactly named `session` for it to work. - - We also add the type annotation `session: Session` so that we can get autocompletion and inline error checks in our editor. - -6. Now in the dependency override function, we just return the same `session` object that came from outside it. - - The `session` object comes from the parameter passed to the test function, and we just re-use it and return it here in the dependency override. diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_006.md b/docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_006.md deleted file mode 100644 index d44a3b67..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/annotations/en/test_main_006.md +++ /dev/null @@ -1,23 +0,0 @@ -1. Create the new fixture named `"client"`. - -2. This **client fixture**, in turn, also requires the **session fixture**. - -3. Now we create the **dependency override** inside the client fixture. - -4. Set the **dependency override** in the `app.dependency_overrides` dictionary. - -5. Create the `TestClient` with the **FastAPI** `app`. - -6. `yield` the `TestClient` instance. - - By using `yield`, after the test function is done, pytest will come back to execute the rest of the code after `yield`. - -7. This is the cleanup code, after `yield`, and after the test function is done. - - Here we clear the dependency overrides (here it's only one) in the FastAPI `app`. - -8. Now the test function requires the **client fixture**. - - And inside the test function, the code is quite **simple**, we just use the `TestClient` to make requests to the API, check the data, and that's it. - - The fixtures take care of all the **setup** and **cleanup** code. diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py deleted file mode 100644 index f0a25594..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/main.py +++ /dev/null @@ -1,105 +0,0 @@ -from typing import List, Optional - -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -app = FastAPI() - - -@app.on_event("startup") -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.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} diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_extra_coverage.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_extra_coverage.py deleted file mode 100644 index 1d8153ab..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_extra_coverage.py +++ /dev/null @@ -1,38 +0,0 @@ -from fastapi.testclient import TestClient -from sqlalchemy import Inspector, inspect -from sqlmodel import Session, create_engine - -from . import main as app_mod -from .test_main import client_fixture, session_fixture - -assert client_fixture, "This keeps the client fixture used below" -assert session_fixture, "This keeps the session fixture used by client_fixture" - - -def test_startup(): - app_mod.engine = create_engine("sqlite://") - app_mod.on_startup() - insp: Inspector = inspect(app_mod.engine) - assert insp.has_table(str(app_mod.Hero.__tablename__)) - - -def test_get_session(): - app_mod.engine = create_engine("sqlite://") - for session in app_mod.get_session(): - assert isinstance(session, Session) - assert session.bind == app_mod.engine - - -def test_read_hero_not_found(client: TestClient): - response = client.get("/heroes/9000") - assert response.status_code == 404 - - -def test_update_hero_not_found(client: TestClient): - response = client.patch("/heroes/9000", json={"name": "Very-Rusty-Man"}) - assert response.status_code == 404 - - -def test_delete_hero_not_found(client: TestClient): - response = client.delete("/heroes/9000") - assert response.status_code == 404 diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py deleted file mode 100644 index 435787c7..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py +++ /dev/null @@ -1,125 +0,0 @@ -import pytest -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine -from sqlmodel.pool import StaticPool - -from .main import Hero, app, get_session - - -@pytest.fixture(name="session") -def session_fixture(): - engine = create_engine( - "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool - ) - SQLModel.metadata.create_all(engine) - with Session(engine) as session: - yield session - - -@pytest.fixture(name="client") -def client_fixture(session: Session): - def get_session_override(): - return session - - app.dependency_overrides[get_session] = get_session_override - client = TestClient(app) - yield client - app.dependency_overrides.clear() - - -def test_create_hero(client: TestClient): - response = client.post( - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpond" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] is not None - - -def test_create_hero_incomplete(client: TestClient): - # No secret_name - response = client.post("/heroes/", json={"name": "Deadpond"}) - assert response.status_code == 422 - - -def test_create_hero_invalid(client: TestClient): - # secret_name has an invalid type - response = client.post( - "/heroes/", - json={ - "name": "Deadpond", - "secret_name": {"message": "Do you wanna know my secret identity?"}, - }, - ) - assert response.status_code == 422 - - -def test_read_heroes(session: Session, client: TestClient): - hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") - hero_2 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48) - session.add(hero_1) - session.add(hero_2) - session.commit() - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200 - - assert len(data) == 2 - assert data[0]["name"] == hero_1.name - assert data[0]["secret_name"] == hero_1.secret_name - assert data[0]["age"] == hero_1.age - assert data[0]["id"] == hero_1.id - assert data[1]["name"] == hero_2.name - assert data[1]["secret_name"] == hero_2.secret_name - assert data[1]["age"] == hero_2.age - assert data[1]["id"] == hero_2.id - - -def test_read_hero(session: Session, client: TestClient): - hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") - session.add(hero_1) - session.commit() - - response = client.get(f"/heroes/{hero_1.id}") - data = response.json() - - assert response.status_code == 200 - assert data["name"] == hero_1.name - assert data["secret_name"] == hero_1.secret_name - assert data["age"] == hero_1.age - assert data["id"] == hero_1.id - - -def test_update_hero(session: Session, client: TestClient): - hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") - session.add(hero_1) - session.commit() - - response = client.patch(f"/heroes/{hero_1.id}", json={"name": "Deadpuddle"}) - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpuddle" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] == hero_1.id - - -def test_delete_hero(session: Session, client: TestClient): - hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") - session.add(hero_1) - session.commit() - - response = client.delete(f"/heroes/{hero_1.id}") - - hero_in_db = session.get(Hero, hero_1.id) - - assert response.status_code == 200 - - assert hero_in_db is None diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_001.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_001.py deleted file mode 100644 index 3ae40773..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_001.py +++ /dev/null @@ -1,32 +0,0 @@ -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine - -from .main import app, get_session # (1)! - - -def test_create_hero(): - engine = create_engine( - "sqlite:///testing.db", connect_args={"check_same_thread": False} - ) - SQLModel.metadata.create_all(engine) - - with Session(engine) as session: - - def get_session_override(): - return session - - app.dependency_overrides[get_session] = get_session_override - - client = TestClient(app) # (2)! - - response = client.post( # (3)! - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - app.dependency_overrides.clear() - data = response.json() # (4)! - - assert response.status_code == 200 # (5)! - assert data["name"] == "Deadpond" # (6)! - assert data["secret_name"] == "Dive Wilson" # (7)! - assert data["age"] is None # (8)! - assert data["id"] is not None # (9)! diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_002.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_002.py deleted file mode 100644 index 727580b6..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_002.py +++ /dev/null @@ -1,32 +0,0 @@ -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine - -from .main import app, get_session # (1)! - - -def test_create_hero(): - engine = create_engine( - "sqlite:///testing.db", connect_args={"check_same_thread": False} - ) - SQLModel.metadata.create_all(engine) - - with Session(engine) as session: - - def get_session_override(): # (2)! - return session # (3)! - - app.dependency_overrides[get_session] = get_session_override # (4)! - - client = TestClient(app) - - response = client.post( - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - app.dependency_overrides.clear() # (5)! - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpond" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] is not None diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_003.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_003.py deleted file mode 100644 index 465c5251..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_003.py +++ /dev/null @@ -1,33 +0,0 @@ -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine - -from .main import app, get_session # (1)! - - -def test_create_hero(): - engine = create_engine( # (2)! - "sqlite:///testing.db", connect_args={"check_same_thread": False} - ) - SQLModel.metadata.create_all(engine) # (3)! - - with Session(engine) as session: # (4)! - - def get_session_override(): - return session # (5)! - - app.dependency_overrides[get_session] = get_session_override # (4)! - - client = TestClient(app) - - response = client.post( - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - app.dependency_overrides.clear() - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpond" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] is not None - # (6)! diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_004.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_004.py deleted file mode 100644 index b770a9aa..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_004.py +++ /dev/null @@ -1,35 +0,0 @@ -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine -from sqlmodel.pool import StaticPool # (1)! - -from .main import app, get_session - - -def test_create_hero(): - engine = create_engine( - "sqlite://", # (2)! - connect_args={"check_same_thread": False}, - poolclass=StaticPool, # (3)! - ) - SQLModel.metadata.create_all(engine) - - with Session(engine) as session: - - def get_session_override(): - return session - - app.dependency_overrides[get_session] = get_session_override - - client = TestClient(app) - - response = client.post( - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - app.dependency_overrides.clear() - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpond" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] is not None diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_005.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_005.py deleted file mode 100644 index f653eef7..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_005.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest # (1)! -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine -from sqlmodel.pool import StaticPool - -from .main import app, get_session - - -@pytest.fixture(name="session") # (2)! -def session_fixture(): # (3)! - engine = create_engine( - "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool - ) - SQLModel.metadata.create_all(engine) - with Session(engine) as session: - yield session # (4)! - - -def test_create_hero(session: Session): # (5)! - def get_session_override(): - return session # (6)! - - app.dependency_overrides[get_session] = get_session_override - - client = TestClient(app) - - response = client.post( - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - app.dependency_overrides.clear() - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpond" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] is not None diff --git a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_006.py b/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_006.py deleted file mode 100644 index 8dbfd45c..00000000 --- a/docs_src/tutorial/fastapi/app_testing/tutorial001/test_main_006.py +++ /dev/null @@ -1,41 +0,0 @@ -import pytest -from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine -from sqlmodel.pool import StaticPool - -from .main import app, get_session - - -@pytest.fixture(name="session") -def session_fixture(): - engine = create_engine( - "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool - ) - SQLModel.metadata.create_all(engine) - with Session(engine) as session: - yield session - - -@pytest.fixture(name="client") # (1)! -def client_fixture(session: Session): # (2)! - def get_session_override(): # (3)! - return session - - app.dependency_overrides[get_session] = get_session_override # (4)! - - client = TestClient(app) # (5)! - yield client # (6)! - app.dependency_overrides.clear() # (7)! - - -def test_create_hero(client: TestClient): # (8)! - response = client.post( - "/heroes/", json={"name": "Deadpond", "secret_name": "Dive Wilson"} - ) - data = response.json() - - assert response.status_code == 200 - assert data["name"] == "Deadpond" - assert data["secret_name"] == "Dive Wilson" - assert data["age"] is None - assert data["id"] is not None diff --git a/docs_src/tutorial/fastapi/delete/tutorial001.py b/docs_src/tutorial/fastapi/delete/tutorial001.py deleted file mode 100644 index 977882c4..00000000 --- a/docs_src/tutorial/fastapi/delete/tutorial001.py +++ /dev/null @@ -1,98 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -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(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(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(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 - - -@app.delete("/heroes/{hero_id}") -def delete_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") - session.delete(hero) - session.commit() - return {"ok": True} diff --git a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py b/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py deleted file mode 100644 index ccf3d770..00000000 --- a/docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py +++ /dev/null @@ -1,67 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -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(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(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 diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial001.py b/docs_src/tutorial/fastapi/multiple_models/tutorial001.py deleted file mode 100644 index 42ac8051..00000000 --- a/docs_src/tutorial/fastapi/multiple_models/tutorial001.py +++ /dev/null @@ -1,60 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class Hero(SQLModel, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class HeroCreate(SQLModel): - name: str - secret_name: str - age: Optional[int] = None - - -class HeroPublic(SQLModel): - id: int - name: str - secret_name: str - age: Optional[int] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -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(): - with Session(engine) as session: - heroes = session.exec(select(Hero)).all() - return heroes diff --git a/docs_src/tutorial/fastapi/multiple_models/tutorial002.py b/docs_src/tutorial/fastapi/multiple_models/tutorial002.py deleted file mode 100644 index 79c71f1a..00000000 --- a/docs_src/tutorial/fastapi/multiple_models/tutorial002.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -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(): - with Session(engine) as session: - heroes = session.exec(select(Hero)).all() - return heroes diff --git a/docs_src/tutorial/fastapi/read_one/tutorial001.py b/docs_src/tutorial/fastapi/read_one/tutorial001.py deleted file mode 100644 index a3994517..00000000 --- a/docs_src/tutorial/fastapi/read_one/tutorial001.py +++ /dev/null @@ -1,67 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI, HTTPException -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -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(): - with Session(engine) as session: - heroes = session.exec(select(Hero)).all() - return heroes - - -@app.get("/heroes/{hero_id}", response_model=HeroPublic) -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 diff --git a/docs_src/tutorial/fastapi/relationships/tutorial001.py b/docs_src/tutorial/fastapi/relationships/tutorial001.py deleted file mode 100644 index 59b44730..00000000 --- a/docs_src/tutorial/fastapi/relationships/tutorial001.py +++ /dev/null @@ -1,199 +0,0 @@ -from typing import List, Optional - -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: Optional[int] = 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): - id: Optional[int] = None - name: Optional[str] = None - headquarters: Optional[str] = None - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - team_id: Optional[int] = Field(default=None, foreign_key="team.id") - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - team: Optional[Team] = Relationship(back_populates="heroes") - - -class HeroPublic(HeroBase): - id: int - - -class HeroCreate(HeroBase): - pass - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - team_id: Optional[int] = None - - -class HeroPublicWithTeam(HeroPublic): - team: Optional[TeamPublic] = None - - -class TeamPublicWithHeroes(TeamPublic): - heroes: List[HeroPublic] = [] - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -app = FastAPI() - - -@app.on_event("startup") -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=HeroPublicWithTeam) -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=TeamPublicWithHeroes) -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/response_model/tutorial001.py b/docs_src/tutorial/fastapi/response_model/tutorial001.py deleted file mode 100644 index 57d87383..00000000 --- a/docs_src/tutorial/fastapi/response_model/tutorial001.py +++ /dev/null @@ -1,46 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class Hero(SQLModel, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=Hero) -def create_hero(hero: Hero): - with Session(engine) as session: - session.add(hero) - session.commit() - session.refresh(hero) - return hero - - -@app.get("/heroes/", response_model=List[Hero]) -def read_heroes(): - with Session(engine) as session: - heroes = session.exec(select(Hero)).all() - return heroes diff --git a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py b/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py deleted file mode 100644 index f0a25594..00000000 --- a/docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py +++ /dev/null @@ -1,105 +0,0 @@ -from typing import List, Optional - -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -app = FastAPI() - - -@app.on_event("startup") -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.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} diff --git a/docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py b/docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py39.py similarity index 100% rename from docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py rename to docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py39.py diff --git a/docs_src/tutorial/fastapi/teams/tutorial001.py b/docs_src/tutorial/fastapi/teams/tutorial001.py deleted file mode 100644 index 49dd8306..00000000 --- a/docs_src/tutorial/fastapi/teams/tutorial001.py +++ /dev/null @@ -1,190 +0,0 @@ -from typing import List, Optional - -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: Optional[int] = 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: Optional[str] = None - headquarters: Optional[str] = None - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - team_id: Optional[int] = Field(default=None, foreign_key="team.id") - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - team: Optional[Team] = Relationship(back_populates="heroes") - - -class HeroPublic(HeroBase): - id: int - - -class HeroCreate(HeroBase): - pass - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - team_id: Optional[int] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -app = FastAPI() - - -@app.on_event("startup") -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.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/update/tutorial001.py b/docs_src/tutorial/fastapi/update/tutorial001.py deleted file mode 100644 index 6a02f6c0..00000000 --- a/docs_src/tutorial/fastapi/update/tutorial001.py +++ /dev/null @@ -1,87 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - - -class HeroCreate(HeroBase): - pass - - -class HeroPublic(HeroBase): - id: int - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -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(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(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(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/tutorial002.py b/docs_src/tutorial/fastapi/update/tutorial002.py deleted file mode 100644 index c8838aef..00000000 --- a/docs_src/tutorial/fastapi/update/tutorial002.py +++ /dev/null @@ -1,101 +0,0 @@ -from typing import List, Optional - -from fastapi import FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - secret_name: str - age: Optional[int] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Optional[int] = Field(default=None, primary_key=True) - hashed_password: str = Field() - - -class HeroCreate(HeroBase): - password: str - - -class HeroPublic(HeroBase): - id: int - - -class HeroUpdate(SQLModel): - name: Optional[str] = None - secret_name: Optional[str] = None - age: Optional[int] = None - password: Optional[str] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) - - -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() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -def create_hero(hero: HeroCreate): - hashed_password = hash_password(hero.password) - with Session(engine) as session: - 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) - return db_hero - - -@app.get("/heroes/", response_model=List[HeroPublic]) -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(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(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) - 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) - return db_hero diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py index 95be986f..71fc7231 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py @@ -5,7 +5,7 @@ from types import ModuleType import pytest -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @dataclass @@ -17,8 +17,7 @@ class Modules: @pytest.fixture( name="modules_path", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py index 1f360c6f..73bf080e 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py @@ -5,7 +5,7 @@ from types import ModuleType import pytest -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @dataclass @@ -17,8 +17,7 @@ class Modules: @pytest.fixture( name="modules_path", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) @@ -35,7 +34,7 @@ def load_modules(clear_sqlmodel, modules_path: str) -> Modules: app_mod = sys.modules[app_mod_path] importlib.reload(app_mod) else: - app_mod = importlib.import_module(app_mod_path) + app_mod = importlib.import_module(app_mod_path) # pragma: no cover test_mod = importlib.import_module(f"{modules_path}.test_main_002") return Modules(app=app_mod, test=test_mod) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py index 4911173b..41c4d573 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py @@ -5,7 +5,7 @@ from types import ModuleType import pytest -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @dataclass @@ -17,8 +17,7 @@ class Modules: @pytest.fixture( name="modules_path", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) @@ -35,7 +34,7 @@ def load_modules(clear_sqlmodel, modules_path: str) -> Modules: app_mod = sys.modules[app_mod_path] importlib.reload(app_mod) else: - app_mod = importlib.import_module(app_mod_path) + app_mod = importlib.import_module(app_mod_path) # pragma: no cover test_mod = importlib.import_module(f"{modules_path}.test_main_003") return Modules(app=app_mod, test=test_mod) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py index b3ca441d..ba3a61ad 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py @@ -5,7 +5,7 @@ from types import ModuleType import pytest -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @dataclass @@ -17,8 +17,7 @@ class Modules: @pytest.fixture( name="modules_path", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) @@ -35,7 +34,7 @@ def load_modules(clear_sqlmodel, modules_path: str) -> Modules: app_mod = sys.modules[app_mod_path] importlib.reload(app_mod) else: - app_mod = importlib.import_module(app_mod_path) + app_mod = importlib.import_module(app_mod_path) # pragma: no cover test_mod = importlib.import_module(f"{modules_path}.test_main_004") return Modules(app=app_mod, test=test_mod) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests005.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests005.py index cc550c40..5d704ffb 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests005.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests005.py @@ -3,9 +3,11 @@ import importlib import pytest from sqlmodel import Session -from docs_src.tutorial.fastapi.app_testing.tutorial001 import main as app_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main_005 as test_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001.test_main_005 import ( +from docs_src.tutorial.fastapi.app_testing.tutorial001_py39 import main as app_mod +from docs_src.tutorial.fastapi.app_testing.tutorial001_py39 import ( + test_main_005 as test_mod, +) +from docs_src.tutorial.fastapi.app_testing.tutorial001_py39.test_main_005 import ( session_fixture, ) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests006.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests006.py index 67c9ac6a..1d474a7e 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests006.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests006.py @@ -4,9 +4,11 @@ import pytest from fastapi.testclient import TestClient from sqlmodel import Session -from docs_src.tutorial.fastapi.app_testing.tutorial001 import main as app_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main_006 as test_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001.test_main_006 import ( +from docs_src.tutorial.fastapi.app_testing.tutorial001_py39 import main as app_mod +from docs_src.tutorial.fastapi.app_testing.tutorial001_py39 import ( + test_main_006 as test_mod, +) +from docs_src.tutorial.fastapi.app_testing.tutorial001_py39.test_main_006 import ( client_fixture, session_fixture, ) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py index 28959f79..c6d942ea 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py @@ -5,14 +5,13 @@ from types import ModuleType import pytest -from ....conftest import needs_py39, needs_py310 +from ....conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py index 1480a06f..ffbf7587 100644 --- a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py index dc3db8b5..cbc722c5 100644 --- a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py index 27629c89..d70dce32 100644 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py @@ -9,14 +9,13 @@ from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py index c840bde2..8d7c8064 100644 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py +++ b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py @@ -9,14 +9,13 @@ from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial002", - pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py index affea513..7ebbecd8 100644 --- a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py index 1d0446ed..cf24466c 100644 --- a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py index 186a1203..1ad004e9 100644 --- a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py index 184fb219..6e441ccc 100644 --- a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py index dba7bc38..b803cee2 100644 --- a/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py @@ -13,7 +13,7 @@ from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py index 2e7d66a0..3b028b7d 100644 --- a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py index b6ee2761..9bc54fbc 100644 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial001", - pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py index a9312651..ede67fe4 100644 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py +++ b/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py @@ -7,14 +7,13 @@ from fastapi.testclient import TestClient from sqlmodel import Session, create_engine from sqlmodel.pool import StaticPool -from tests.conftest import needs_py39, needs_py310 +from tests.conftest import needs_py310 @pytest.fixture( name="module", params=[ - "tutorial002", - pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], )