You could put all the database Models in a single Python module (a single Python file), for example `models.py`:
-```Python
-{!./docs_src/tutorial/code_structure/tutorial001/models.py!}
-```
+{* ./docs_src/tutorial/code_structure/tutorial001_py310/models.py *}
This way, you wouldn't have to deal with circular imports for other models.
Then you could put the code creating the **engine** and the function to create all the tables (if you are not using migrations) in another file `database.py`:
-```Python
-{!./docs_src/tutorial/code_structure/tutorial001/database.py!}
-```
+{* ./docs_src/tutorial/code_structure/tutorial001_py310/database.py *}
This file would also be imported by your application code, to use the shared **engine** and to get and call the function `create_db_and_tables()`.
Finally, you could put the code to create the **app** in another file `app.py`:
-```Python hl_lines="3-4"
-{!./docs_src/tutorial/code_structure/tutorial001/app.py!}
-```
+{* ./docs_src/tutorial/code_structure/tutorial001_py310/app.py hl[3:4] *}
Here we import the models, the engine, and the function to create all the tables and then we can use them all internally.
Using that trick of `TYPE_CHECKING` we can "import" the `Team` in `hero_model.py`:
-```Python hl_lines="1 5-6 16"
-{!./docs_src/tutorial/code_structure/tutorial002/hero_model.py!}
-```
+{* ./docs_src/tutorial/code_structure/tutorial002_py310/hero_model.py hl[1,5:6,16] *}
Have in mind that now we *have* to put the annotation of `Team` as a string: `"Team"`, so that Python doesn't have errors at runtime.
We use the same trick in the `team_model.py` file:
-```Python hl_lines="1 5-6 14"
-{!./docs_src/tutorial/code_structure/tutorial002/team_model.py!}
-```
+{* ./docs_src/tutorial/code_structure/tutorial002_py310/team_model.py hl[1,5:6,14] *}
Now we get editor support, autocompletion, inline errors, and **SQLModel** keeps working. 🎉
Now, just for completeness, the `app.py` file would import the models from both modules:
-```Python hl_lines="4-5 10 12-14"
-{!./docs_src/tutorial/code_structure/tutorial002/app.py!}
-```
+{* ./docs_src/tutorial/code_structure/tutorial002_py310/app.py hl[4:5,10,12:14] *}
And of course, all the tricks with `TYPE_CHECKING` and type annotations in strings are **only needed in the files with circular imports**.
+++ /dev/null
-from sqlmodel import Session
-
-from .database import create_db_and_tables, engine
-from .models import Hero, Team
-
-
-def create_heroes():
- with Session(engine) as session:
- team_z_force = Team(name="Z-Force", headquarters="Sister Margaret's Bar")
-
- hero_deadpond = Hero(
- name="Deadpond", secret_name="Dive Wilson", team=team_z_force
- )
- session.add(hero_deadpond)
- session.commit()
-
- session.refresh(hero_deadpond)
-
- print("Created hero:", hero_deadpond)
- print("Hero's team:", hero_deadpond.team)
-
-
-def main():
- create_db_and_tables()
- create_heroes()
-
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-from sqlmodel import SQLModel, create_engine
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-engine = create_engine(sqlite_url)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
+++ /dev/null
-from typing import List, Optional
-
-from sqlmodel import Field, Relationship, SQLModel
-
-
-class Team(SQLModel, table=True):
- id: Optional[int] = Field(default=None, primary_key=True)
- name: str = Field(index=True)
- headquarters: str
-
- heroes: List["Hero"] = Relationship(back_populates="team")
-
-
-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)
-
- team_id: Optional[int] = Field(default=None, foreign_key="team.id")
- team: Optional[Team] = Relationship(back_populates="heroes")
+++ /dev/null
-from sqlmodel import Session
-
-from .database import create_db_and_tables, engine
-from .hero_model import Hero
-from .team_model import Team
-
-
-def create_heroes():
- with Session(engine) as session:
- team_z_force = Team(name="Z-Force", headquarters="Sister Margaret's Bar")
-
- hero_deadpond = Hero(
- name="Deadpond", secret_name="Dive Wilson", team=team_z_force
- )
- session.add(hero_deadpond)
- session.commit()
-
- session.refresh(hero_deadpond)
-
- print("Created hero:", hero_deadpond)
- print("Hero's team:", hero_deadpond.team)
-
-
-def main():
- create_db_and_tables()
- create_heroes()
-
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-from sqlmodel import SQLModel, create_engine
-
-sqlite_file_name = "database.db"
-sqlite_url = f"sqlite:///{sqlite_file_name}"
-
-engine = create_engine(sqlite_url)
-
-
-def create_db_and_tables():
- SQLModel.metadata.create_all(engine)
+++ /dev/null
-from typing import TYPE_CHECKING, Optional
-
-from sqlmodel import Field, Relationship, SQLModel
-
-if TYPE_CHECKING:
- from .team_model import Team
-
-
-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)
-
- team_id: Optional[int] = Field(default=None, foreign_key="team.id")
- team: Optional["Team"] = Relationship(back_populates="heroes")
+++ /dev/null
-from typing import TYPE_CHECKING, List, Optional
-
-from sqlmodel import Field, Relationship, SQLModel
-
-if TYPE_CHECKING:
- from .hero_model import Hero
-
-
-class Team(SQLModel, table=True):
- id: Optional[int] = Field(default=None, primary_key=True)
- name: str = Field(index=True)
- headquarters: str
-
- heroes: List["Hero"] = Relationship(back_populates="team")
import pytest
from sqlmodel import create_engine
-from tests.conftest import PrintMock, needs_py39, needs_py310
+from tests.conftest import PrintMock, needs_py310
expected_calls = [
[
@pytest.fixture(
name="modules",
params=[
- "tutorial001",
- pytest.param("tutorial001_py39", marks=needs_py39),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_py310", marks=needs_py310),
],
)
import pytest
from sqlmodel import create_engine
-from ...conftest import PrintMock, needs_py39, needs_py310
+from ...conftest import PrintMock, needs_py310
expected_calls = [
[
@pytest.fixture(
name="modules",
params=[
- "tutorial002",
- pytest.param("tutorial002_py39", marks=needs_py39),
+ pytest.param("tutorial002_py39"),
pytest.param("tutorial002_py310", marks=needs_py310),
],
)