Let's say that each hero in the database will have an amount of money. We could make that field a `Decimal` type using the `condecimal()` function:
-//// tab | Python 3.10+
-
-```Python hl_lines="11"
-{!./docs_src/advanced/decimal/tutorial001_py310.py[ln:1-11]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="12"
-{!./docs_src/advanced/decimal/tutorial001.py[ln:1-12]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/advanced/decimal/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/advanced/decimal/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/advanced/decimal/tutorial001_py310.py ln[1:11] hl[11] *}
Here we are saying that `money` can have at most `5` digits with `max_digits`, **this includes the integers** (to the left of the decimal dot) **and the decimals** (to the right of the decimal dot).
When creating new models you can actually pass normal (`float`) numbers, Pydantic will automatically convert them to `Decimal` types, and **SQLModel** will store them as `Decimal` types in the database (using SQLAlchemy).
-//// tab | Python 3.10+
-
-```Python hl_lines="4-6"
-# Code above omitted π
-
-{!./docs_src/advanced/decimal/tutorial001_py310.py[ln:24-34]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="4-6"
-# Code above omitted π
-
-{!./docs_src/advanced/decimal/tutorial001.py[ln:25-35]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/advanced/decimal/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/advanced/decimal/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/advanced/decimal/tutorial001_py310.py ln[24:34] hl[25:27] *}
## Select Decimal data
Then, when working with Decimal types, you can confirm that they indeed avoid those rounding errors from floats:
-//// tab | Python 3.10+
-
-```Python hl_lines="15-16"
-# Code above omitted π
-
-{!./docs_src/advanced/decimal/tutorial001_py310.py[ln:37-50]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="15-16"
-# Code above omitted π
-
-{!./docs_src/advanced/decimal/tutorial001.py[ln:38-51]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/advanced/decimal/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/advanced/decimal/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/advanced/decimal/tutorial001_py310.py ln[37:50] hl[49:50] *}
## Review the results
But the same `id` field actually **can be `None`** in the Python code, so we declare the type with `int | None (or Optional[int])`, and set the default value to `Field(default=None)`:
-//// tab | Python 3.10+
-
-```Python hl_lines="4"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:4-8]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="4"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:6-10]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[4:8] hl[5] *}
Next, I'll show you a bit more about the synchronization of data between the database and the Python code.
When we create a new `Hero` instance, we don't set the `id`:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-6"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:21-24]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-6"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:23-26]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[21:24] hl[21:24] *}
### How `Optional` Helps
We can confirm that by printing our heroes before adding them to the database:
-//// tab | Python 3.10+
-
-```Python hl_lines="9-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:21-29]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:23-31]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[21:29] hl[27:29] *}
That will output:
We can verify by creating a session using a `with` block and adding the objects. And then printing them again:
-//// tab | Python 3.10+
-
-```Python hl_lines="19-21"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:21-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="19-21"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:23-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[21:39] hl[37:39] *}
This will, again, output the `id`s of the objects as `None`:
Then we can `commit` the changes in the session, and print again:
-//// tab | Python 3.10+
-
-```Python hl_lines="13 16-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:31-46]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13 16-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:33-48]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[31:46] hl[41,44:46] *}
And now, something unexpected happens, look at the output, it seems as if the `Hero` instance objects had no data at all:
To confirm and understand how this **automatic expiration and refresh** of data when accessing attributes work, we can print some individual fields (instance attributes):
-//// tab | Python 3.10+
-
-```Python hl_lines="21-23 26-28"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:31-56]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="21-23 26-28"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:33-58]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[31:56] hl[49:51,54:56] *}
Now we are actually accessing the attributes, because instead of printing the whole object `hero_1`:
You can do that too with `session.refresh(object)`:
-//// tab | Python 3.10+
-
-```Python hl_lines="30-32 35-37"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:31-65]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="30-32 35-37"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:33-67]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[31:65] hl[58:60,63:65] *}
When Python executes this code:
There are no surprises here, it still works:
-//// tab | Python 3.10+
-
-```Python hl_lines="40-42"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py[ln:31-70]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="40-42"
-# Code above omitted π
-
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py[ln:33-72]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/automatic_id_none_refresh/tutorial001_py310.py ln[31:70] hl[68:70] *}
And the output shows again the same data:
We will continue with the code in the previous example and we will add more things to it.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/create_tables/tutorial001_py310.py ln[0] *}
Make sure you remove the `database.db` file before running the examples to get the same results.
Let's start by creating two teams:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-9"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:29-35]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-9"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:31-37]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[29:35] hl[29:35] *}
This would hopefully look already familiar.
Let's not forget to add this function `create_heroes()` to the `main()` function so that we run it when calling the program from the command line:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:61-63]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:63-65]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[61:63] hl[63] *}
## Run it
As the `Hero` class model now has a field (column, attribute) `team_id`, we can set it by using the ID field from the `Team` objects we just created before:
-//// tab | Python 3.10+
-
-```Python hl_lines="12"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:29-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="12"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:31-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[29:39] hl[38] *}
We haven't committed this hero to the database yet, but there are already a couple of things to pay **attention** to.
Let's now create two more heroes:
-//// tab | Python 3.10+
-
-```Python hl_lines="14-20"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:29-50]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="14-20"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:31-52]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[29:50] hl[40:46] *}
When creating `hero_rusty_man`, we are accessing `team_preventers.id`, so that will also trigger a refresh of its data, generating an output of:
Now let's refresh and print those new heroes to see their new ID pointing to their teams:
-//// tab | Python 3.10+
-
-```Python hl_lines="26-28 30-32"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:29-58]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="26-28 30-32"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:31-60]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[29:58] hl[52:54,56:58] *}
If we execute that in the command line, it will output:
Import the things we need from `sqlmodel` and create a new `Team` model:
-//// tab | Python 3.10+
-
-```Python hl_lines="4-7"
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py[ln:1-7]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6-9"
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:1-9]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/create_tables/tutorial001_py310.py ln[1:7] hl[4:7] *}
This is very similar to what we have been doing with the `Hero` model.
This is the same model we have been using up to now, we are just adding the new column `team_id`:
-//// tab | Python 3.10+
-
-```Python hl_lines="16"
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py[ln:1-16]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="18"
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:1-18]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/create_tables/tutorial001_py310.py ln[1:16] hl[16] *}
Most of that should look familiar:
Now we can add the same code as before to create the engine and the function to create the tables:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-4 6 9-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py[ln:19-26]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-4 6 9-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:21-28]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/create_tables/tutorial001_py310.py ln[19:26] hl[19:20,22,25:26] *}
And as before, we'll call this function from another function `main()`, and we'll add that function `main()` to the main block of the file:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-4 7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py[ln:29-34]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-4 7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:31-36]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/create_tables/tutorial001_py310.py ln[29:34] hl[29:30,33:34] *}
## Run the Code
We will continue with the code in the previous example and we will add more things to it.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[0] *}
## `SELECT` Connected Data with SQL
So, we can pass the `Hero` and `Team` model classes. And we can also use both their columns in the `.where()` part:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial001_py310.py[ln:61-63]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial001.py[ln:63-65]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/select/tutorial001_py310.py ln[61:63] hl[63] *}
Notice that in the comparison with `==` we are using the class attributes for both `Hero.team_id` and `Team.id`.
And as we used `select` with two models, we will receive tuples of instances of those two models, so we can iterate over them naturally in a `for` loop:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial001_py310.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial001.py[ln:63-68]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/select/tutorial001_py310.py ln[61:66] hl[65] *}
For each iteration in the `for` loop we get a a tuple with an instance of the class `Hero` and an instance of the class `Team`.
As always, we must remember to add this new `select_heroes()` function to the `main()` function to make sure it is executed when we call this program from the command line.
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial001_py310.py[ln:69-72]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial001.py[ln:71-74]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial001.py!}
-```
-
-////
-
-///
-
+{* ./docs_src/tutorial/connect/select/tutorial001_py310.py ln[69:72] hl[72] *}
## Run the Program
And in SQLModel (actually SQLAlchemy), when using the `.join()`, because we already declared what is the `foreign_key` when creating the models, we don't have to pass an `ON` part, it is inferred automatically:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial002_py310.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial002.py[ln:63-68]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/select/tutorial002_py310.py ln[61:66] hl[63] *}
Also notice that we are still including `Team` in the `select(Hero, Team)`, because we still want to access that data.
`.join()` has a parameter we can use `isouter=True` to make the `JOIN` be a `LEFT OUTER JOIN`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial003_py310.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial003.py[ln:63-68]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/select/tutorial003_py310.py ln[61:66] hl[63] *}
And if we run it, it will output:
We could even add some additional `.where()` after `.join()` to filter the data more, for example to return only the heroes from one team:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial004_py310.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial004.py[ln:63-68]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/select/tutorial004_py310.py ln[61:66] hl[63] *}
Here we are **filtering** with `.where()` to get only the heroes that belong to the **Preventers** team.
By putting the `Team` in `select()` we tell **SQLModel** and the database that we want the team data too.
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial005_py310.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/select/tutorial005.py[ln:63-68]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial005_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/select/tutorial005.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/select/tutorial005_py310.py ln[61:66] hl[63] *}
And if we run that, it will output:
We will continue with the code from the previous chapter.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/update/tutorial001_py310.py ln[0] *}
## Break a Connection
We can simply set the `team_id` to `None`, and now it doesn't have a connection with the team:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/delete/tutorial001_py310.py[ln:29-30]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/connect/delete/tutorial001_py310.py[ln:66-70]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/delete/tutorial001.py[ln:31-32]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/connect/delete/tutorial001.py[ln:68-72]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/delete/tutorial001_py310.py ln[29:30,66:70] hl[66] *}
Again, we just **assign** a value to that field attribute `team_id`, now the value is `None`, which means `NULL` in the database. Then we `add()` the hero to the session, and then `commit()`.
We will continue with the code we used to create some heroes, and we'll update them.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[0] *}
## Assign a Team to a Hero
Doing it is just like updating any other field:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/update/tutorial001_py310.py[ln:29-30]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/connect/update/tutorial001_py310.py[ln:60-64]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/update/tutorial001.py[ln:31-32]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/connect/update/tutorial001.py[ln:62-66]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/update/tutorial001_py310.py ln[29:30,60:64] hl[60] *}
We can simply **assign** a value to that field attribute `team_id`, then `add()` the hero to the session, and then `commit()`.
As before, we'll continue from where we left off with the previous code.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial003_py310.py ln[0] *}
Remember to remove the `database.db` file before running the examples to get the same results.
We'll start by selecting the hero `"Spider-Youngster"` that we updated in the previous chapter, this is the one we will delete:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:70-75]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:72-77]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[70:75] hl[72] *}
As this is a new function `delete_heroes()`, we'll also add it to the `main()` function so that we call it when executing the program from the command line:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:90-98]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:92-100]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[90:98] hl[94] *}
That will print the same existing hero **Spider-Youngster**:
Now, very similar to how we used `session.add()` to add or update new heroes, we can use `session.delete()` to delete the hero from the session:
-//// tab | Python 3.10+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:70-77]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:72-79]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[70:77] hl[77] *}
## Commit the Session
This will save all the changes stored in the **session**, like the deleted hero:
-//// tab | Python 3.10+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:70-78]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:72-80]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[70:78] hl[78] *}
The same as we have seen before, `.commit()` will also save anything else that was added to the session. Including updates, or created heroes.
Because of that, the object still contains its attributes with the data in it, so we can print it:
-//// tab | Python 3.10+
-
-```Python hl_lines="13"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:70-80]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:72-82]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[70:80] hl[80] *}
This will output:
To confirm if it was deleted, now let's query the database again, with the same `"Spider-Youngster"` name:
-//// tab | Python 3.10+
-
-```Python hl_lines="15-17"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:70-84]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="15-17"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:72-86]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[70:84] hl[82:84] *}
Here we are using `results.first()` to get the first object found (in case it found multiple) or `None`, if it didn't find anything.
We'll do it by checking that the "first" item in the `results` is `None`:
-//// tab | Python 3.10+
-
-```Python hl_lines="19-20"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001_py310.py[ln:70-87]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="19-20"
-# Code above omitted π
-
-{!./docs_src/tutorial/delete/tutorial001.py[ln:72-89]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/delete/tutorial001_py310.py ln[70:87] hl[86:87] *}
This will output:
And if we actually find a hero, we just delete it with the **session**.
-//// tab | Python 3.10+
-
-```Python hl_lines="3-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py310.py[ln:89-97]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py39.py[ln:91-99]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/delete/tutorial001.py[ln:91-99]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/delete/tutorial001_py310.py ln[89:97] hl[89:97] *}
After deleting it successfully, we just return a response of:
And by default, we will return a maximum of `100` heroes, so `limit` will have a default value of `100`.
-//// tab | Python 3.10+
-
-```Python hl_lines="1 7 9"
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py[ln:52-56]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 9 11"
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py39.py[ln:54-58]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 9 11"
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py[ln:54-58]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/limit_and_offset/tutorial001_py310.py ln[1:2,52:56] hl[1,53,55] *}
We want to allow clients to set different `offset` and `limit` values.
The simplest way to solve it could be to create **multiple models**, each one with all the corresponding fields:
-//// tab | Python 3.10+
-
-```Python hl_lines="5-9 12-15 18-22"
-# This would work, but there's a better option below π¨
-
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py[ln:5-22]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="5-9 12-15 18-22"
-# This would work, but there's a better option below π¨
-
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py[ln:7-24]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5-9 12-15 18-22"
-# This would work, but there's a better option below π¨
-
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py[ln:7-24]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py ln[5:22] hl[5:9,12:15,18:22] *}
Here's the important detail, and probably the most important feature of **SQLModel**: only `Hero` is declared with `table = True`.
Let's first check how is the process to create a hero now:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-4 6"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py[ln:44-51]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-4 6"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py[ln:46-53]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-4 6"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py[ln:46-53]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py ln[44:51] hl[44:45,47] *}
Let's check that in detail.
Now we use the type annotation `HeroCreate` for the request JSON data in the `hero` parameter of the **path operation function**.
-//// tab | Python 3.10+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py[ln:45]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py[ln:47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py[ln:47]!}
-
-# Code below omitted π
-```
-
-////
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py ln[45] hl[45] *}
Then we create a new `Hero` (this is the actual **table** model that saves things to the database) using `Hero.model_validate()`.
We can now create a new `Hero` instance (the one for the database) and put it in the variable `db_hero` from the data in the `hero` variable that is the `HeroCreate` instance we received from the request.
-//// tab | Python 3.10+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py[ln:47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py[ln:49]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py[ln:49]!}
-
-# Code below omitted π
-```
-
-////
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py ln[47] hl[47] *}
Then we just `add` it to the **session**, `commit`, and `refresh` it, and finally, we return the same `db_hero` variable that has the just refreshed `Hero` instance.
And now that we return it, FastAPI will validate the data with the `response_model`, which is a `HeroPublic`:
-//// tab | Python 3.10+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py[ln:44]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001_py39.py[ln:46]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py[ln:46]!}
-
-# Code below omitted π
-```
-
-////
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial001_py310.py ln[44] hl[44] *}
This will validate that all the data that we promised is there and will remove any data we didn't declare.
So let's create a **base** model `HeroBase` that the others can inherit from:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-6"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py[ln:5-8]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-6"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py[ln:7-10]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-6"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py[ln:7-10]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py ln[5:8] hl[5:8] *}
As you can see, this is *not* a **table model**, it doesn't have the `table = True` config.
Let's start with the only **table model**, the `Hero`:
-//// tab | Python 3.10+
-
-```Python hl_lines="9-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py[ln:5-12]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py[ln:7-14]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py[ln:7-14]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py ln[5:12] hl[11:12] *}
Notice that `Hero` now doesn't inherit from `SQLModel`, but from `HeroBase`.
Notice that the parent model `HeroBase` is not a **table model**, but still, we can declare `name` and `age` using `Field(index=True)`.
-//// tab | Python 3.10+
-
-```Python hl_lines="4 6 9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py[ln:5-12]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="4 6 9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py[ln:7-14]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="4 6 9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py[ln:7-14]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py ln[5:12] hl[6,8,11] *}
This won't affect this parent **data model** `HeroBase`.
This is a fun one:
-//// tab | Python 3.10+
-
-```Python hl_lines="13-14"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py[ln:5-16]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="13-14"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py[ln:7-18]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13-14"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py[ln:7-18]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py ln[5:16] hl[15:16] *}
What's happening here?
This one just declares that the `id` field is required when reading a hero from the API, because a hero read from the API will come from the database, and in the database it will always have an ID.
-//// tab | Python 3.10+
-
-```Python hl_lines="17-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py[ln:5-20]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="17-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py[ln:7-22]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="17-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py[ln:7-22]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/multiple_models/tutorial002_py310.py ln[5:20] hl[19:20] *}
## Review the Updated Docs UI
///
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py[ln:59-65]!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py[ln:61-67]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py ln[1:2,59:65] hl[59] *}
For example, to get the hero with ID `2` we would send a `GET` request to:
This will let the client know that they probably made a mistake on their side and requested a hero that doesn't exist in the database.
-//// tab | Python 3.10+
-
-```Python hl_lines="1 9-11"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py[ln:59-65]!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 11-13"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py[ln:61-67]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 11-13"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py ln[1:2,59:65] hl[1,62:64] *}
## Return the Hero
And because we are using the `response_model` with `HeroPublic`, it will be validated, documented, etc.
-//// tab | Python 3.10+
-
-```Python hl_lines="6 12"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py[ln:59-65]!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8 14"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py[ln:61-67]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8 14"
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/read_one/tutorial001_py310.py ln[1:2,59:65] hl[59,65] *}
## Check the Docs UI
And the same way, we declared the `TeamPublic` with only the same base fields of the `TeamBase` plus the `id`. But it doesn't include a field `heroes` for the **relationship attribute**.
-//// tab | Python 3.10+
-
-```Python hl_lines="3-5 9-10 14-19 23-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:5-7]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:20-21]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:29-34]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:43-44]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-5 9-10 14-19 23-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:7-9]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:22-23]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:31-36]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:45-46]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-5 9-10 14-19 23-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:7-9]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:22-23]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:31-36]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:45-46]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/teams/tutorial001_py310.py ln[5:7,20:21,29:34,43:44] hl[5:7,20:21,29:34,43:44] *}
Now, remember that <a href="https://fastapi.tiangolo.com/tutorial/response-model/" class="external-link" target="_blank">FastAPI uses the `response_model` to validate and **filter** the response data</a>?
In this case, we used `response_model=TeamPublic` and `response_model=HeroPublic`, so FastAPI will use them to filter the response data, even if we return a **table model** that includes **relationship attributes**:
-//// tab | Python 3.10+
-
-```Python hl_lines="3 8 12 17"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:102-107]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:156-161]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 8 12 17"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:104-109]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:158-163]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 8 12 17"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:104-109]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:158-163]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/teams/tutorial001_py310.py ln[102:107,156:161] hl[102,107,156,161] *}
## Don't Include All the Data
We'll add them **after** the other models so that we can easily reference the previous models.
-//// tab | Python 3.10+
-
-```Python hl_lines="3-4 7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py[ln:59-64]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-4 7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py39.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-4 7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001.py[ln:61-66]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py ln[59:64] hl[59:60,63:64] *}
These two models are very **simple in code**, but there's a lot happening here. Let's check it out.
In the case of the hero, this tells FastAPI to extract the `team` too. And in the case of the team, to extract the list of `heroes` too.
-//// tab | Python 3.10+
-
-```Python hl_lines="3 8 12 17"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py[ln:111-116]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py[ln:165-170]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 8 12 17"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py39.py[ln:113-118]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py39.py[ln:167-172]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 8 12 17"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001.py[ln:113-118]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/relationships/tutorial001.py[ln:167-172]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/relationships/tutorial001_py310.py ln[111:116,165:170] hl[111,116,165,170] *}
## Check It Out in the Docs UI
For example, we can pass the same `Hero` **SQLModel** class (because it is also a Pydantic model):
-//// tab | Python 3.10+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py310.py[ln:31-37]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py39.py[ln:33-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/response_model/tutorial001.py[ln:33-39]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/response_model/tutorial001_py310.py ln[31:37] hl[31] *}
## List of Heroes in `response_model`
First, we import `List` from `typing` and then we declare the `response_model` with `List[Hero]`:
-//// tab | Python 3.10+
-
-```Python hl_lines="3"
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py310.py[ln:40-44]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3"
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py39.py[ln:42-46]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="1 5"
-{!./docs_src/tutorial/fastapi/response_model/tutorial001.py[ln:1]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/response_model/tutorial001.py[ln:42-46]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/response_model/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/response_model/tutorial001_py310.py ln[40:44] hl[40] *}
## FastAPI and Response Model
Up to now, we have been creating a session in each *path operation*, in a `with` block.
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py310.py[ln:48-55]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py39.py[ln:50-57]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/delete/tutorial001.py[ln:50-57]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/delete/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/delete/tutorial001_py310.py ln[48:55] hl[50] *}
That's perfectly fine, but in many use cases we would want to use <a href="https://fastapi.tiangolo.com/tutorial/dependencies/" class="external-link" target="_blank">FastAPI Dependencies</a>, for example to **verify** that the client is **logged in** and get the **current user** before executing any other code in the *path operation*.
It could use `yield` instead of `return`, and in that case **FastAPI** will make sure it executes all the code **after** the `yield`, once it is done with the request.
-//// tab | Python 3.10+
-
-```Python hl_lines="3-5"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:40-42]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-5"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:42-44]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-5"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:42-44]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py ln[40:42] hl[40:42] *}
## Use the Dependency
We import `Depends()` from `fastapi`. Then we use it in the *path operation function* in a **parameter**, the same way we declared parameters to get JSON bodies, path parameters, etc.
-//// tab | Python 3.10+
-
-```Python hl_lines="1 13"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:40-42]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:53-59]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 15"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:55-61]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 15"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-61]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py ln[1:2,40:42,53:59] hl[1,54] *}
/// tip
This means that in the main code of the *path operation function*, it will work equivalently to the previous version with the explicit `with` block.
-//// tab | Python 3.10+
-
-```Python hl_lines="14-18"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:40-42]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:53-59]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="16-20"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:55-61]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="16-20"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-61]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py ln[1:2,40:42,53:59] hl[55:59] *}
In fact, you could think that all that block of code inside of the `create_hero()` function is still inside a `with` block for the **session**, because this is more or less what's happening behind the scenes.
But now, the `with` block is not explicitly in the function, but in the dependency above:
-//// tab | Python 3.10+
-
-```Python hl_lines="7-8"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:40-42]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:53-59]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9-10"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:55-61]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9-10"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-61]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py ln[1:2,40:42,53:59] hl[41:42] *}
We will see how this is very useful when testing the code later. β
And then we remove the previous `with` block with the old **session**.
-//// tab | Python 3.10+
-
-```Python hl_lines="13 24 33 42 57"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:1-2]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:40-42]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py[ln:53-104]!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="15 26 35 44 59"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py[ln:55-106]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="15 26 35 44 59"
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:1-4]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-106]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/session_with_dependency/tutorial001_py310.py ln[1:2,40:42,53:104] hl[54,65,74,83,98] *}
## Recap
This is almost the same code we have seen up to now in previous examples:
-//// tab | Python 3.10+
-
-```Python hl_lines="18-19"
-
-# One line of FastAPI imports here later π
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:2]!}
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:5-20]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="20-21"
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:1]!}
-
-# One line of FastAPI imports here later π
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:4]!}
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:7-22]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py ln[2,5:20] hl[19:20] *}
There's only one change here from the code we have used before, the `check_same_thread` in the `connect_args`.
And then create an `app` object that is an instance of that `FastAPI` class:
-//// tab | Python 3.10+
-
-```Python hl_lines="1 6"
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:1-2]!}
-
-# SQLModel code here omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:23]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 8"
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:1-4]!}
-
-# SQLModel code here omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py ln[1:2,23] hl[1,23] *}
## Create Database and Tables on `startup`
This should be called only once at startup, not before every request, so we put it in the function to handle the `"startup"` event:
-//// tab | Python 3.10+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:23-28]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25-30]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py ln[23:28] hl[26:28] *}
## Create Heroes *Path Operation*
It will be called when a user sends a request with a `POST` **operation** to the `/heroes/` **path**:
-//// tab | Python 3.10+
-
-```Python hl_lines="11-12"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:23-37]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11-12"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25-39]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py ln[23:37] hl[31:32] *}
/// info
Now let's add another **path operation** to read all the heroes:
-//// tab | Python 3.10+
-
-```Python hl_lines="20-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py[ln:23-44]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="20-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25-46]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/simple_hero_api/tutorial001_py310.py ln[23:44] hl[40:44] *}
This is pretty straightforward.
And we also create a `TeamUpdate` **data model**.
-//// tab | Python 3.10+
-
-```Python hl_lines="5-7 10-13 16-17 20-21 24-26"
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:1-26]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="7-9 12-15 18-19 22-23 26-28"
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:1-28]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7-9 12-15 18-19 22-23 26-28"
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:1-28]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/teams/tutorial001_py310.py ln[1:26] hl[5:7,10:13,16:17,20:21,24:26] *}
We now also have **relationship attributes**. π
## Update Hero Models
-//// tab | Python 3.10+
-
-```Python hl_lines="3-8 11-14 17-18 21-22 25-29"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:29-55]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-8 11-14 17-18 21-22 25-29"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:31-57]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-8 11-14 17-18 21-22 25-29"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:31-57]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/teams/tutorial001_py310.py ln[29:55] hl[29:34,37:40,43:44,47:48,51:55] *}
We now have a `team_id` in the hero models.
Notice that the **relationship attributes**, the ones with `Relationship()`, are **only** in the **table models**, as those are the ones that are handled by **SQLModel** with SQLAlchemy and that can have the automatic fetching of data from the database when we access them.
-//// tab | Python 3.10+
-
-```Python hl_lines="11 38"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:5-55]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 38"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:7-57]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 38"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:7-57]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/teams/tutorial001_py310.py ln[5:55] hl[13,40] *}
## Path Operations for Teams
These are equivalent and very similar to the **path operations** for the **heroes** we had before, so we don't have to go over the details for each one, let's check the code.
-//// tab | Python 3.10+
-
-```Python hl_lines="3-9 12-20 23-28 31-47 50-57"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py[ln:136-190]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-9 12-20 23-28 31-47 50-57"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py[ln:138-192]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-9 12-20 23-28 31-47 50-57"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py[ln:138-192]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/teams/tutorial001_py310.py ln[136:190] hl[136:142,145:153,156:161,164:180,183:190] *}
## Using Relationships Attributes
Now we will see how useful it is to have this session dependency. β¨
-/// details | π Full file preview
-
-```Python
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/main.py!}
-```
-
-///
+{* ./docs_src/tutorial/fastapi/app_testing/tutorial001/main.py ln[0] *}
## File Structure
Let's add some more tests:
-```Python hl_lines="3 22"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:30-58]!}
-
-# Code below omitted π
-```
-
-/// details | π Full file preview
-
-```Python
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
-```
-
-///
+{* ./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py ln[30:58] hl[30,49] *}
/// tip
But for the next test function, we will require **both fixtures**, the **client** and the **session**.
-```Python hl_lines="6 10"
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:1-6]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:61-81]!}
-
-# Code below omitted π
-```
-
-/// details | π Full file preview
-
-```Python
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
-```
-
-///
+{* ./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py ln[1:6,61:81] hl[6,61] *}
In this test function, we want to check that the *path operation* to **read a list of heroes** actually sends us heroes.
Using the same ideas, requiring the fixtures, creating data that we need for the tests, etc., we can now add the rest of the tests. They look quite similar to what we have done up to now.
-```Python hl_lines="3 18 33"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:84-125]!}
-```
-
-/// details | π Full file preview
-
-```Python
-{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
-```
-
-///
+{* ./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py ln[84:125] hl[84,99,114] *}
## Run the Tests
And the data models for `HeroCreate` and `HeroUpdate` will also have a new field `password` that will contain the plain text password sent by clients.
-//// tab | Python 3.10+
-
-```Python hl_lines="11 15 26"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py[ln:5-28]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 15 26"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py[ln:7-30]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 15 26"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002.py[ln:7-30]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial002_py310.py ln[5:28] hl[13,17,28] *}
When a client is creating a new hero, they will send the `password` in the request body.
This contains the `password` field with the plain text password, and we cannot use that one. So we need to generate a hash from it.
-//// tab | Python 3.10+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py[ln:42-44]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py[ln:55-57]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py[ln:44-46]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py[ln:57-59]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002.py[ln:44-46]!}
-
-# Code here omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002.py[ln:57-59]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial002_py310.py ln[42:44,55:57] hl[57] *}
## Create an Object with Extra Data
Similar to how dictionaries have an `update` method, **SQLModel** models have a parameter `update` in `Hero.model_validate()` that takes a dictionary with extra data, or data that should take precedence:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py[ln:55-64]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py[ln:57-66]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002.py[ln:57-66]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial002_py310.py ln[55:64] hl[60] *}
Now, `db_hero` (which is a *table model* `Hero`) will extract its values from `hero` (which is a *data model* `HeroCreate`), and then it will **`update`** its values with the extra data from the dictionary `extra_data`.
The same way as before, to avoid removing existing data, we will use `exclude_unset=True` when calling `hero.model_dump()`, to get a dictionary with only the data sent by the client.
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py[ln:83-89]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py[ln:85-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002.py[ln:85-91]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial002_py310.py ln[83:89] hl[89] *}
Now, this `hero_data` dictionary could contain a `password`. We need to check it, and if it's there, we need to generate the `hashed_password`.
It takes a model object or dictionary with the data to update the object and also an **additional `update` argument** with extra data.
-//// tab | Python 3.10+
-
-```Python hl_lines="15"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py[ln:83-99]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="15"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py[ln:85-101]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="15"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial002.py[ln:85-101]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial002_py310.py ln[83:99] hl[95] *}
/// tip
So, let's create this new `HeroUpdate` model:
-//// tab | Python 3.10+
-
-```Python hl_lines="21-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py[ln:5-26]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="21-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py[ln:7-28]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="21-24"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001.py[ln:7-28]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial001_py310.py ln[5:26] hl[23:26] *}
This is almost the same as `HeroBase`, but all the fields are optional, so we can't simply inherit from `HeroBase`.
We will use a `PATCH` HTTP operation. This is used to **partially update data**, which is what we are doing.
-//// tab | Python 3.10+
-
-```Python hl_lines="3-4"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py[ln:74-89]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-4"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-4"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial001_py310.py ln[74:89] hl[74:75] *}
We also read the `hero_id` from the *path parameter* and the request body, a `HeroUpdate`.
So, we need to read the hero from the database, with the **same logic** we used to **read a single hero**, checking if it exists, possibly raising an error for the client if it doesn't exist, etc.
-//// tab | Python 3.10+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py[ln:74-89]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial001_py310.py ln[74:89] hl[77:79] *}
### Get the New Data
Then we use that to get the data that was actually sent by the client:
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py[ln:74-89]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial001_py310.py ln[74:89] hl[80] *}
/// tip
Before SQLModel 0.0.14, the method was called `hero.dict(exclude_unset=True)`, but it was renamed to `hero.model_dump(exclude_unset=True)` to be consistent with Pydantic v2.
Now that we have a **dictionary with the data sent by the client**, we can use the method `db_hero.sqlmodel_update()` to update the object `db_hero`.
-//// tab | Python 3.10+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py[ln:74-89]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/fastapi/update/tutorial001.py[ln:76-91]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/fastapi/update/tutorial001_py310.py ln[74:89] hl[81] *}
/// tip
Fine, in that case, you can **sneak peek** the final code to create indexes here.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial002_py310.py ln[0] *}
..but if you are not an expert, **continue reading**, this will probably be useful. π€
Here's the `Hero` model we had before:
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-{!./docs_src/tutorial/where/tutorial001_py310.py[ln:1-8]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-{!./docs_src/tutorial/where/tutorial001.py[ln:1-10]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial001_py310.py ln[1:8] hl[6] *}
Let's now update it to tell **SQLModel** to create an index for the `name` field when creating the table:
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-{!./docs_src/tutorial/indexes/tutorial001_py310.py[ln:1-8]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-{!./docs_src/tutorial/indexes/tutorial001.py[ln:1-10]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial001_py310.py ln[1:8] hl[6] *}
We use the same `Field()` again as we did before, and set `index=True`. That's it! π
This is great because it means that indexes are very **simple to use**. But it might also feel counterintuitive at first, as you are **not doing anything** explicitly in the code to make it obvious that the index is useful, it all happens in the database behind the scenes.
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/indexes/tutorial001_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/indexes/tutorial001.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial001_py310.py ln[34:39] hl[36] *}
This is exactly the same code as we had before, but now the database will **use the index** underneath.
We are going to query the `hero` table doing comparisons on the `age` field too, so we should **define an index** for that one as well:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-{!./docs_src/tutorial/indexes/tutorial002_py310.py[ln:1-8]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10"
-{!./docs_src/tutorial/indexes/tutorial002.py[ln:1-10]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial002_py310.py ln[1:8] hl[8] *}
In this case, we want the default value of `age` to continue being `None`, so we set `default=None` when using `Field()`.
We'll create 3 right away, for the 3 heroes:
-//// tab | Python 3.10+
-
-```Python
-# Code above omitted π
-
-{!./docs_src/tutorial/insert/tutorial002_py310.py[ln:21-24]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-# Code above omitted π
-
-{!./docs_src/tutorial/insert/tutorial002.py[ln:23-26]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial002_py310.py ln[21:24] *}
/// tip
The first step is to import the `Session` class:
-//// tab | Python 3.10+
-
-```Python hl_lines="1"
-{!./docs_src/tutorial/insert/tutorial001_py310.py[ln:1]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-{!./docs_src/tutorial/insert/tutorial001.py[ln:1-3]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial001_py310.py ln[1] hl[1] *}
Then we can create a new session:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/insert/tutorial001_py310.py[ln:21-26]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/insert/tutorial001.py[ln:23-28]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial001_py310.py ln[21:26] hl[26] *}
The new `Session` takes an `engine` as a parameter. And it will use the **engine** underneath.
Now that we have some hero model instances (some objects in memory) and a **session**, the next step is to add them to the session:
-//// tab | Python 3.10+
-
-```Python hl_lines="9-11"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial001_py310.py[ln:21-30]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9-11"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial001.py[ln:23-32]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial001_py310.py ln[21:30] hl[28:30] *}
By this point, our heroes are *not* stored in the database yet.
Now that we have the heroes in the **session** and that we are ready to save all that to the database, we can **commit** the changes:
-//// tab | Python 3.10+
-
-```Python hl_lines="13"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial001_py310.py[ln:21-32]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial001.py[ln:23-34]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial001_py310.py ln[21:32] hl[32] *}
Once this line is executed, the **session** will use the **engine** to save all the data in the database by sending the corresponding SQL.
But to keep things a bit more organized, let's instead create a new function `main()` that will contain all the code that should be executed when called as an independent script, and we can put there the previous function `create_db_and_tables()`, and add the new function `create_heroes()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="2 4"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial002_py310.py[ln:34-36]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="2 4"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial002.py[ln:36-38]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial002_py310.py ln[34:36] hl[34,36] *}
And then we can call that single `main()` function from that main block:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial002_py310.py[ln:34-40]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial002.py[ln:36-42]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial002_py310.py ln[34:40] hl[40] *}
By having everything that should happen when called as a script in a single function, we can easily add more code later on.
So once we are done with the session, we should **close** it to make it release those resources and finish its cleanup:
-//// tab | Python 3.10+
-
-```Python hl_lines="16"
-# Code above omitted π
-
-{!./docs_src/tutorial/insert/tutorial001_py310.py[ln:21-34]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="16"
-# Code above omitted π
-
-{!./docs_src/tutorial/insert/tutorial001.py[ln:23-36]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial001_py310.py ln[21:34] hl[34] *}
But what happens if we forget to close the session?
But there's a better way to handle the session, using a `with` block:
-//// tab | Python 3.10+
-
-```Python hl_lines="7-12"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial002_py310.py[ln:21-31]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7-12"
-# Code above omitted π
-{!./docs_src/tutorial/insert/tutorial002.py[ln:23-33]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial002_py310.py ln[21:31] hl[26:31] *}
This is the same as creating the session manually and then manually closing it. But here, using a `with` block, it will be automatically created when **starting** the `with` block and assigned to the variable `session`, and it will be automatically closed after the `with` block is **finished**.
Again, we will create several heroes to have some data to select from:
-//// tab | Python 3.10+
-
-```Python hl_lines="4-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial001_py310.py[ln:21-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="4-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial001.py[ln:23-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/offset_and_limit/tutorial001_py310.py ln[21:39] hl[22:28] *}
## Review Select All
This is the code we had to select all the heroes in the `select()` examples:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial003_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial003.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial003_py310.py ln[34:39] hl[34:39] *}
But this would get us **all** the heroes at the same time, in a database that could have thousands, that could be problematic.
We currently have 7 heroes in the database. But we could as well have thousands, so let's limit the results to get only the first 3:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial001_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial001.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/offset_and_limit/tutorial001_py310.py ln[42:47] hl[44] *}
The special **select** object we get from `select()` also has a method `.limit()` that we can use to limit the results to a certain number.
We can use `.offset()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial002_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial002.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/offset_and_limit/tutorial002_py310.py ln[42:47] hl[44] *}
The way this works is that the special **select** object we get from `select()` has methods like `.where()`, `.offset()` and `.limit()`.
Then to get the next batch of 3 rows we would offset all the ones we already saw, the first 6:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial003_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial003.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/offset_and_limit/tutorial003_py310.py ln[42:47] hl[44] *}
The database right now has **only 7 rows**, so this query can only get 1 row.
Of course, you can also combine `.limit()` and `.offset()` with `.where()` and other methods you will learn about later:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial004_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/offset_and_limit/tutorial004.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/offset_and_limit/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/offset_and_limit/tutorial004_py310.py ln[42:47] hl[44] *}
## Run the Program with Limit, Offset, and Where on the Command Line
We'll continue from where we left off with the previous code.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[0] *}
## Create Heroes
As we have done before, we'll create a function `create_heroes()` and we'll create some teams and heroes in it:
-//// tab | Python 3.10+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:36-54]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:42-60]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:42-60]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[36:54] hl[44] *}
This is very similar to what we have done before.
Now let's do as we have done before, `commit` the **session**, `refresh` the data, and print it:
-//// tab | Python 3.10+
-
-```Python hl_lines="22-25 27-29 31-36"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:36-69]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="22-25 27-29 31-36"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:42-75]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="22-25 27-29 31-36"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:42-75]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[36:69] hl[55:58,60:62,64:69] *}
## Add to Main
As before, add the `create_heroes()` function to the `main()` function to make sure it is called when running this program from the command line:
-//// tab | Python 3.10+
-
-```Python
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:72-74]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:78-80]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:78-80]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[72:74] *}
## Run the Program
We can create it just as any other **SQLModel**:
-//// tab | Python 3.10+
-
-```Python hl_lines="4-6"
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:1-6]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="6-12"
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:1-12]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6-12"
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:1-12]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[1:6] hl[4:6] *}
This is a **SQLModel** class model table like any other.
Let's see the `Team` model, it's almost identical as before, but with a little change:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:9-14]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:15-20]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:15-20]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[9:14] hl[14] *}
The **relationship attribute `heroes`** is still a list of heroes, annotated as `List["Hero"]`. Again, we use `"Hero"` in quotes because we haven't declared that class yet by this point in the code (but as you know, editors and **SQLModel** understand that).
Let's see the other side, here's the `Hero` model:
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:17-23]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:23-29]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:23-29]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[17:23] hl[23] *}
We **removed** the previous `team_id` field (column) because now the relationship is done via the link table. π₯
The same as before, we will have the rest of the code to create the **engine**, and a function to create all the tables `create_db_and_tables()`.
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:26-33]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:32-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:32-39]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
-
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[26:33] hl[32] *}
And as in previous examples, we will add that function to a function `main()`, and we will call that `main()` function in the main block:
-//// tab | Python 3.10+
-
-```Python hl_lines="4"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:72-73]!}
- # We will do more stuff here later π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py[ln:77-78]!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="4"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:78-79]!}
- # We will do more stuff here later π
-
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py[ln:83-84]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="4"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:78-79]!}
- # We will do more stuff here later π
-
-{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:83-84]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
-
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[72:73,77:78] hl[73] *}
## Run the Code
And we will also add two **relationship attributes**, for the linked `team` and `hero`:
-//// tab | Python 3.10+
-
-```Python hl_lines="6 8-9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:4-10]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="10 12-13"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:6-16]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10 12-13"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:6-16]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial003_py310.py ln[4:10] hl[7,9:10] *}
The new **relationship attributes** have their own `back_populates` pointing to new relationship attributes we will create in the `Hero` and `Team` models:
We no longer have the `heroes` relationship attribute, and instead we have the new `hero_links` attribute:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:13-18]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:19-24]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:19-24]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial003_py310.py ln[13:18] hl[18] *}
## Update Hero Model
We change the `teams` relationship attribute for `team_links`:
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:21-27]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:27-33]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:27-33]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial003_py310.py ln[21:27] hl[27] *}
## Create Relationships
But now we create the **explicit link models** manually, pointing to their hero and team instances, and specifying the additional link data (`is_training`):
-//// tab | Python 3.10+
-
-```Python hl_lines="21-30 32-35"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:40-79]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="21-30 32-35"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:46-85]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="21-30 32-35"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:46-85]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial003_py310.py ln[40:79] hl[58:67,69:72] *}
We are just adding the link model instances to the session, because the link model instances are connected to the heroes and teams, they will be also automatically included in the session when we commit.
Here we do that in the `update_heroes()` function:
-//// tab | Python 3.10+
-
-```Python hl_lines="10-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:82-97]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="10-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:88-103]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:88-103]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial003_py310.py ln[82:97] hl[89:94] *}
## Run the Program with the New Relationship
We can do that by iterating on the links:
-//// tab | Python 3.10+
-
-```Python hl_lines="8-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:82-83]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py[ln:99-107]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:88-89]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py[ln:105-113]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8-10"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:88-89]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial003.py[ln:105-113]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial003_py310.py ln[82:83,99:107] hl[99:101] *}
## Run the Program with the Updated Relationships
We'll continue from where we left off with the previous code.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial001_py310.py ln[0] *}
## Get Data to Update
And because we are now using `select()`, we also have to import it.
-//// tab | Python 3.10+
-
-```Python hl_lines="1 5-10"
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py[ln:1]!}
-
-# Some code here omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py[ln:72-77]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 7-12"
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py[ln:1-3]!}
-
-# Some code here omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py[ln:78-83]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 7-12"
-{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:1-3]!}
-
-# Some code here omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:78-83]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial002_py310.py ln[1,72:77] hl[1,72:77] *}
And of course, we have to add `update_heroes()` to our `main()` function:
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py[ln:94-101]!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py[ln:100-107]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:100-107]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial002_py310.py ln[94:101] hl[97] *}
## Add Many-to-Many Relationships
We can use the same **relationship attributes** to include `hero_spider_boy` in the `team_z_force.heroes`.
-//// tab | Python 3.10+
-
-```Python hl_lines="10-12 14-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py[ln:72-84]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="10-12 14-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py[ln:78-90]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10-12 14-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:78-90]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial002_py310.py ln[72:84] hl[79:81,83:84] *}
/// tip
In this case, we use the method `.remove()`, that takes an item and removes it from the list.
-//// tab | Python 3.10+
-
-```Python hl_lines="17-19 21-22"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py[ln:72-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="17-19 21-22"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py[ln:78-97]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="17-19 21-22"
-# Code above omitted π
-
-{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:78-97]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/many_to_many/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/many_to_many/tutorial002_py310.py ln[72:91] hl[86:88,90:91] *}
And this time, just to show again that by using `back_populates` **SQLModel** (actually SQLAlchemy) takes care of connecting the models by their relationships, even though we performed the operation from the `hero_spider_boy` object (modifying `hero_spider_boy.teams`), we are adding `team_z_force` to the **session**. And we commit that, without even add `hero_spider_boy`.
We'll continue with the same examples we have been using in the previous chapters to create and select data and we'll keep updating them.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial002_py310.py ln[0] *}
If you already executed the previous examples and have a database with data, **remove the database file** before running each example, that way you won't have duplicate data and you will be able to get the same results.
We have been iterating over the rows in a `result` object like:
-//// tab | Python 3.10+
-
-```Python hl_lines="7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/indexes/tutorial002_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/indexes/tutorial002.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial002_py310.py ln[42:47] hl[46:47] *}
But let's say that we are not interested in all the rows, just the **first** one.
We can call the `.first()` method on the `results` object to get the first row:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial001_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial001.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial001_py310.py ln[42:47] hl[46] *}
This will return the first object in the `results` (if there was any).
In that case, `.first()` will return `None`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial002_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial002.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial002_py310.py ln[42:47] hl[44,46] *}
In this case, as there's no hero with an age less than 25, `.first()` will return `None`.
In that case, instead of `.first()` we can use `.one()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial003_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial003.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial003_py310.py ln[42:47] hl[46] *}
Here we know that there's only one `"Deadpond"`, and there shouldn't be any more than one.
Of course, even if we don't duplicate the data, we could get the same error if we send a query that finds more than one row and expect exactly one with `.one()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial004_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial004.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial004_py310.py ln[42:47] hl[44,46] *}
That would find 2 rows, and would end up with the same error.
And also, if we get no rows at all with `.one()`, it will also raise an error:
-//// tab | Python 3.10+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial005_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial005.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial005_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial005.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial005_py310.py ln[42:47] hl[44,46] *}
In this case, as there are no heroes with an age less than 25, `.one()` will raise an error.
Of course, with `.first()` and `.one()` you would also probably write all that in a more compact form most of the time, all in a single line (or at least a single Python statement):
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial006_py310.py[ln:42-45]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial006.py[ln:44-47]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial006_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial006.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial006_py310.py ln[42:45] hl[44] *}
That would result in the same as some examples above.
You could do it the same way we have been doing with a `.where()` and then getting the first item with `.first()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial007_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5 7"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial007.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial007_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial007.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial007_py310.py ln[42:47] hl[44,46] *}
That would work correctly, as expected. But there's a shorter version. π
As selecting a single row by its Id column with the **primary key** is a common operation, there's a shortcut for it:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial008_py310.py[ln:42-45]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial008.py[ln:44-47]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial008_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial008.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial008_py310.py ln[42:45] hl[44] *}
`session.get(Hero, 1)` is an equivalent to creating a `select()`, then filtering by Id using `.where()`, and then getting the first item with `.first()`.
`.get()` behaves similar to `.first()`, if there's no data it will simply return `None` (instead of raising an error):
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial009_py310.py[ln:42-45]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/one/tutorial009.py[ln:44-47]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/one/tutorial009_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/one/tutorial009.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/one/tutorial009_py310.py ln[42:45] hl[44] *}
Running that will output:
Let's see how that works by writing an **incomplete** version first, without `back_populates`:
-//// tab | Python 3.10+
-
-```Python hl_lines="9 19"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:1-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py ln[1:19] hl[9,19] *}
## Read Data Objects
As you already know how this works, I won't separate that in a select `statement`, `results`, etc. Let's use the shorter form in a single call:
-//// tab | Python 3.10+
-
-```Python hl_lines="5-7 9-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:103-111]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="5-7 9-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:105-113]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5-7 9-11"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:105-113]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py ln[103:111] hl[105:107,109:111] *}
/// tip
Now, let's print the current **Spider-Boy**, the current **Preventers** team, and particularly, the current **Preventers** list of heroes:
-//// tab | Python 3.10+
-
-```Python hl_lines="13-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:103-115]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="13-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:105-117]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13-15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:105-117]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py ln[103:115] hl[113:115] *}
Up to this point, it's all good. π
Now let's update **Spider-Boy**, removing him from the team by setting `hero_spider_boy.team = None` and then let's print this object again:
-//// tab | Python 3.10+
-
-```Python hl_lines="8 12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:103-104]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:117-121]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8 12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:105-106]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:119-123]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8 12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:105-106]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:119-123]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py ln[103:104,117:121] hl[117,121] *}
The first important thing is, we *haven't committed* the hero yet, so accessing the list of heroes would not trigger an automatic refresh.
Now, if we commit it and print again:
-//// tab | Python 3.10+
-
-```Python hl_lines="8-9 15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:103-104]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py[ln:123-130]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8-9 15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:105-106]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py[ln:125-132]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8-9 15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:105-106]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py[ln:125-132]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial001_py310.py ln[103:104,123:130] hl[123:124,130] *}
When we access `preventers_team.heroes` after the `commit`, that triggers a refresh, so we get the latest list, without **Spider-Boy**, so that's fine again:
Let's add it back:
-//// tab | Python 3.10+
-
-```Python hl_lines="9 19"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py[ln:1-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py ln[1:19] hl[9,19] *}
And we can keep the rest of the code the same:
-//// tab | Python 3.10+
-
-```Python hl_lines="8 12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py[ln:103-104]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py[ln:117-121]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8 12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py[ln:105-106]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py[ln:119-123]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8 12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py[ln:105-106]!}
-
- # Code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py[ln:119-123]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py ln[103:104,117:121] hl[117,121] *}
/// tip
It's quite simple code, it's just a string, but it might be confusing to think exactly *what* string should go there:
-//// tab | Python 3.10+
-
-```Python hl_lines="9 19"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py[ln:1-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py ln[1:19] hl[9,19] *}
The string in `back_populates` is the name of the attribute *in the other* model, that will reference *the current* model.
So, in the class `Team`, we have an attribute `heroes` and we declare it with `Relationship(back_populates="team")`.
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py[ln:4-9]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py[ln:6-11]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py[ln:6-11]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py ln[4:9] hl[9] *}
The string in `back_populates="team"` refers to the attribute `team` in the class `Hero` (the other class).
So, the string `"heroes"` refers to the attribute `heroes` in the class `Team`.
-//// tab | Python 3.10+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py[ln:12-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py[ln:14-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py[ln:14-21]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial002_py310.py ln[12:19] hl[19] *}
/// tip
<img src="/img/tutorial/relationships/attributes/back-populates2.svg">
-//// tab | Python 3.10+
-
-```Python hl_lines="3 10 13 15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003_py310.py[ln:27-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3 10 13 15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003_py39.py[ln:29-41]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3 10 13 15"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py[ln:29-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/back_populates/tutorial003_py310.py ln[27:39] hl[27,34,37,39] *}
This configures SQLModel to **automatically delete** the related records (heroes) **when the initial one is deleted** (a team).
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py[ln:1-9]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py[ln:1-11]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py[ln:1-11]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py ln[1:9] hl[9] *}
With this configuration, when we delete a team, SQLModel (actually SQLAlchemy) will:
If we want to configure the database to **automatically delete** the related records when the parent is deleted, we can set `ondelete="CASCADE"`.
-//// tab | Python 3.10+
-
-```Python hl_lines="18"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py[ln:1-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py ln[1:19] hl[18] *}
Now, when we **create the tables** in the database, the `team_id` column in the `Hero` table will have an `ON DELETE CASCADE` in its definition at the database level.
Now, when we **delete a team**, we don't need to do anything else, it's **automatically** going to **delete its heroes**.
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py[ln:76-82]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py[ln:80-86]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py[ln:80-86]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py ln[76:82] hl[80] *}
## Confirm Heroes are Deleted
If we try to select them from the database, we will **no longer find them**.
-//// tab | Python 3.10+
-
-```Python hl_lines="5 8 10 13"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py[ln:85-95]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="5 8 10 13"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py[ln:89-99]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5 8 10 13"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py[ln:89-99]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial001_py310.py ln[85:95] hl[87,90,92,95] *}
## Run the Program with `cascade_delete=True` and `ondelete="CASCADE"`
In this case, the side with `Relationship()` won't have `cascade_delete`, but the side with `Field()` and a `foreign_key` will have `ondelete="SET NULL"`.
-//// tab | Python 3.10+
-
-```Python hl_lines="19"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py310.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py39.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py310.py ln[1:21] hl[19] *}
The configuration above is setting the `team_id` column from the `Hero` table to have an `ON DELETE SET NULL`.
Removing a team has the **same code** as before, the only thing that changes is the configuration underneath in the database.
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py310.py[ln:78-84]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py39.py[ln:80-86]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002.py[ln:80-86]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial002_py310.py ln[78:84] hl[82] *}
The result would be these tables.
To be able to test this out with SQLite, we first need to enable foreign key support.
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py310.py[ln:30-33]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py39.py[ln:32-35]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003.py[ln:32-35]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py310.py ln[30:33] hl[33] *}
/// info
We will also use `ondelete="SET NULL"` in the `Hero` model table, in the foreign key `Field()` for the `team_id` to make the database set those fields to `NULL` automatically.
-//// tab | Python 3.10+
-
-```Python hl_lines="9 19"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py310.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py39.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial003_py310.py ln[1:21] hl[9,19] *}
### Run the Program with `passive_deletes`
As `ondelete="RESTRICT"` is mainly a database-level constraint, let's enable foreign key support in SQLite first to be able to test it.
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py310.py[ln:30-33]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py39.py[ln:32-35]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004.py[ln:32-35]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py310.py ln[30:33] hl[33] *}
### Use `ondelete="RESTRICT"`
///
-//// tab | Python 3.10+
-
-```Python hl_lines="9 19"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py310.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py39.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004.py[ln:1-23]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial004_py310.py ln[1:21] hl[9,19] *}
### Run the Program with `RESTRICT`, See the Error
///
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005_py310.py[ln:80-88]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005_py39.py[ln:82-90]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005.py[ln:82-90]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/cascade_delete_relationships/tutorial005_py310.py ln[80:88] hl[84] *}
### Run the Program Deleting Heroes First
Let's check the old code we used to create some heroes and teams:
-//// tab | Python 3.10+
-
-```Python hl_lines="9 12 18 24"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:29-58]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9 12 18 24"
-# Code above omitted π
-
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:31-60]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[29:58] hl[35,38,44,50] *}
There are several things to **notice** here.
Now let's do all that, but this time using the new, shiny `Relationship` attributes:
-//// tab | Python 3.10+
-
-```Python hl_lines="9 12 18"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py[ln:32-55]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9 12 18"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py[ln:34-57]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9 12 18"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py[ln:34-57]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py ln[32:55] hl[38,41,47] *}
Now we can create the `Team` instances and pass them directly to the new `team` argument when creating the `Hero` instances, as `team=team_preventers` instead of `team_id=team_preventers.id`.
The same way we could assign an integer with a `team.id` to a `hero.team_id`, we can also assign the `Team` instance to the `hero.team`:
-//// tab | Python 3.10+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py[ln:32-33]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py[ln:57-61]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py[ln:34-35]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py[ln:59-63]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="8"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py[ln:34-35]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py[ln:59-63]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py ln[32:33,57:61] hl[57] *}
## Create a Team with Heroes
We could also create the `Hero` instances first, and then pass them in the `heroes=` argument that takes a list, when creating a `Team` instance:
-//// tab | Python 3.10+
-
-```Python hl_lines="13 15-16"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py[ln:32-33]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py[ln:63-73]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="13 15-16"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py[ln:34-35]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py[ln:65-75]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13 15-16"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py[ln:34-35]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py[ln:65-75]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py ln[32:33,63:73] hl[68,70:71] *}
Here we create two heroes first, **Black Lion** and **Princess Sure-E**, and then we pass them in the `heroes` argument.
Let's create some more heroes and add them to the `team_preventers.heroes` list attribute:
-//// tab | Python 3.10+
-
-```Python hl_lines="14-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py[ln:32-33]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py[ln:75-91]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="14-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py[ln:34-35]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py[ln:77-93]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="14-18"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py[ln:34-35]!}
-
- # Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py[ln:77-93]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001_py310.py ln[32:33,75:91] hl[81:85] *}
The attribute `team_preventers.heroes` behaves like a list. But it's a special type of list, because when we modify it adding heroes to it, **SQLModel** (actually SQLAlchemy) **keeps track of the necessary changes** to be done in the database.
Up to now, we have only used the `team_id` column to connect the tables when querying with `select()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="16"
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py[ln:1-16]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="18"
-{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:1-18]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/connect/insert/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/connect/insert/tutorial001_py310.py ln[1:16] hl[16] *}
This is a **plain field** like all the others, all representing a **column in the table**.
First, import `Relationship` from `sqlmodel`:
-//// tab | Python 3.10+
-
-```Python hl_lines="1"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py[ln:1]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py[ln:1-3]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py[ln:1-3]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py ln[1] hl[1] *}
Next, use that `Relationship` to declare a new attribute in the model classes:
-//// tab | Python 3.10+
-
-```Python hl_lines="9 19"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py[ln:1-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11 21"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py ln[1:19] hl[9,19] *}
## What Are These Relationship Attributes
First, add a function `select_heroes()` where we get a hero to start working with, and add that function to the `main()` function:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-7 14"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py[ln:94-98]!}
-
-# Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py[ln:108-111]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="3-7 14"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py[ln:96-100]!}
-
-# Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py[ln:110-113]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-7 14"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py[ln:96-100]!}
-
-# Previous code here omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py[ln:110-113]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py ln[94:98,108:111] hl[94:98,111] *}
## Select the Related Team - Old Way
With what we have learned **up to now**, we could use a `select()` statement, then execute it with `session.exec()`, and then get the `.first()` result, for example:
-//// tab | Python 3.10+
-
-```Python hl_lines="9-12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py[ln:94-103]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9-12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py[ln:96-105]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9-12"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py[ln:96-105]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py ln[94:103] hl[100:103] *}
## Get Relationship Team - New Way
So, the highlighted block above, has the same results as the block below:
-//// tab | Python 3.10+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py[ln:94-98]!}
-
- # Code from the previous example omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py[ln:105]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py[ln:96-100]!}
-
- # Code from the previous example omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py[ln:107]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py[ln:96-100]!}
-
- # Code from the previous example omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py[ln:107]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001_py310.py ln[94:98,105] hl[105] *}
/// tip
And the same way, when we are working on the **many** side of the **one-to-many** relationship, we can get a list of of the related objects just by accessing the relationship attribute:
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py[ln:94-100]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py39.py[ln:96-102]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py[ln:96-102]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py ln[94:100] hl[100] *}
That would print a list with all the heroes in the Preventers team:
We can remove the relationship by setting it to `None`, the same as with the `team_id`, it also works with the new relationship attribute `.team`:
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py[ln:103-114]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py39.py[ln:105-116]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py[ln:105-116]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py ln[103:114] hl[109] *}
And of course, we should remember to add this `update_heroes()` function to `main()` so that it runs when we call this program from the command line:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py[ln:117-121]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py39.py[ln:119-123]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py[ln:119-123]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002_py310.py ln[117:121] hl[121] *}
## Recap
In the first Relationship attribute, we declare it with `List["Hero"]`, putting the `Hero` in quotes instead of just normally there:
-//// tab | Python 3.10+
-
-```Python hl_lines="9"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py[ln:1-19]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python hl_lines="11"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py[ln:1-21]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.9+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py39.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001_py310.py ln[1:19] hl[9] *}
What's that about? Can't we just write it normally as `List[Hero]`?
Let's continue from the last code we used to create some data.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/insert/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/insert/tutorial002_py310.py ln[0] *}
We are creating a **SQLModel** `Hero` class model and creating some records.
We will start with that in a new function `select_heroes()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="3-4"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:34-35]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3-4"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001.py[ln:36-37]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[34:35] hl[34:35] *}
## Create a `select` Statement
First we have to import `select` from `sqlmodel` at the top of the file:
-//// tab | Python 3.10+
-
-```Python hl_lines="1"
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:1]!}
-
-# More code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-{!./docs_src/tutorial/select/tutorial001.py[ln:1-3]!}
-
-# More code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[1] hl[1] *}
And then we will use it to create a `SELECT` statement in Python code:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:1]!}
-
-# More code here omitted π
-
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:34-36]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="9"
-{!./docs_src/tutorial/select/tutorial001.py[ln:1-3]!}
-
-# More code here omitted π
-
-{!./docs_src/tutorial/select/tutorial001.py[ln:36-38]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[1,34:36] hl[36] *}
It's a very simple line of code that conveys a lot of information:
Now that we have the `select` statement, we can execute it with the **session**:
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:34-37]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001.py[ln:36-39]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[34:37] hl[37] *}
This will tell the **session** to go ahead and use the **engine** to execute that `SELECT` statement in the database and bring the results back.
Now we can put it in a `for` loop and print each one of the heroes:
-//// tab | Python 3.10+
-
-```Python hl_lines="7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[34:39] hl[38:39] *}
This will print the output:
Now include a call to `select_heroes()` in the `main()` function so that it is executed when we run the program from the command line:
-//// tab | Python 3.10+
-
-```Python hl_lines="14"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:34-45]!}
-
-# More code here later π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="14"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001.py[ln:36-47]!}
-
-# More code here later π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[34:45] hl[45] *}
## Review The Code
The special `results` object also has a method `results.all()` that returns a list with all the objects:
-//// tab | Python 3.10+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial003_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="7"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial003.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial003_py310.py ln[34:39] hl[38] *}
With this now we have all the heroes in a list in the `heroes` variable.
But knowing what is each object and what it is all doing, we can simplify it a bit and put it in a more compact form:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial004_py310.py[ln:34-37]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial004.py[ln:36-39]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial004_py310.py ln[34:37] hl[36] *}
Here we are putting it all on a single line, you will probably put the select statements in a single line like this more often.
As before, we'll continue from where we left off with the previous code.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/indexes/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/indexes/tutorial002_py310.py ln[0] *}
Remember to remove the `database.db` file before running the examples to get the same results.
We'll start by selecting the hero `"Spider-Boy"`, this is the one we will update:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[42:47] hl[44] *}
Let's not forget to add that `update_heroes()` function to the `main()` function so that we call it when executing the program from the command line:
-//// tab | Python 3.10+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:56-63]!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:58-65]!}
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[56:63] hl[59] *}
Up to that point, running that in the command line will output:
In this case, we will set the `age` to `16`:
-//// tab | Python 3.10+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:42-49]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="10"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:44-51]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[42:49] hl[49] *}
## Add the Hero to the Session
This is the same we did when creating new hero instances:
-//// tab | Python 3.10+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:42-50]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="11"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:44-52]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[42:50] hl[50] *}
## Commit the Session
This will save the updated hero in the database:
-//// tab | Python 3.10+
-
-```Python hl_lines="12"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:42-51]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="12"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:44-53]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[42:51] hl[51] *}
It will also save anything else that was added to the session.
But in this example we are not accessing any attribute, we will only print the object. And we also want to be explicit, so we will `.refresh()` the object directly:
-//// tab | Python 3.10+
-
-```Python hl_lines="13"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:42-52]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="13"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:44-54]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[42:52] hl[52] *}
This refresh will trigger the same SQL query that would be automatically triggered by accessing an attribute. So it will generate this output:
Now we can just print the hero:
-//// tab | Python 3.10+
-
-```Python hl_lines="14"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001_py310.py[ln:42-53]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="14"
-# Code above omitted π
-
-{!./docs_src/tutorial/update/tutorial001.py[ln:44-55]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/update/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/update/tutorial001_py310.py ln[42:53] hl[53] *}
Because we refreshed it right after updating it, it has fresh data, including the new `age` we just updated.
And now we will update `select_heroes()` to filter the data.
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python hl_lines="36-41"
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="36-41"
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[0] *}
If you already executed the previous examples and have a database with data, **remove the database file** before running each example, that way you won't have duplicate data and you will be able to get the same results.
We care specially about the **select** statement:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/select/tutorial001.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/select/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/select/tutorial001_py310.py ln[34:39] hl[36] *}
## Filter Rows Using `WHERE` with **SQLModel**
Now, the same way that we add `WHERE` to a SQL statement to filter rows, we can add a `.where()` to a **SQLModel** `select()` statement to filter rows, which will filter the objects returned:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial001_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial001.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial001_py310.py ln[34:39] hl[36] *}
It's a very small change, but it's packed of details. Let's explore them.
It's actually the same as in previous chapters for selecting data:
-//// tab | Python 3.10+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial001_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="6-8"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial001.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial001_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial001.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial001_py310.py ln[34:39] hl[37:39] *}
We take that statement, that now includes a `WHERE`, and we `exec()` it to get the results.
We could get the rows where a column is **not** equal to a value using `!=`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial002_py310.py[ln:34-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial002.py[ln:36-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial002_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial002.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial002_py310.py ln[34:39] hl[36] *}
That would output:
Let's update the function `create_heroes()` and add some more rows to make the next comparison examples clearer:
-//// tab | Python 3.10+
-
-```Python hl_lines="4-10 13-19"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial003_py310.py[ln:21-39]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="4-10 13-19"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial003.py[ln:23-41]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial003_py310.py ln[21:39] hl[22:28,31:37] *}
Now that we have several heroes with different ages, it's gonna be more obvious what the next comparisons do.
Now let's use `>` to get the rows where a column is **more than** a value:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial003_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial003.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial003_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial003.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial003_py310.py ln[42:47] hl[44] *}
That would output:
Let's do that again, but with `>=` to get the rows where a column is **more than or equal** to a value:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial004_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial004.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial004_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial004.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial004_py310.py ln[42:47] hl[44] *}
Because we are using `>=`, the age `35` will be included in the output:
Similarly, we can use `<` to get the rows where a column is **less than** a value:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial005_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial005.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial005_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial005.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial005_py310.py ln[42:47] hl[44] *}
And we get the younger one with an age in the database:
Finally, we can use `<=` to get the rows where a column is **less than or equal** to a value:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial006_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial006.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial006_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial006.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial006_py310.py ln[42:47] hl[44] *}
And we get the younger ones, `35` and below:
Because `.where()` returns the same special select object back, we can add more `.where()` calls to it:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial007_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial007.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial007_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial007.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial007_py310.py ln[42:47] hl[44] *}
This will select the rows `WHERE` the `age` is **greater than or equal** to `35`, `AND` also the `age` is **less than** `40`.
As an alternative to using multiple `.where()` we can also pass several expressions to a single `.where()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial008_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial008.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial008_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial008.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial008_py310.py ln[42:47] hl[44] *}
This is the same as the above, and will result in the same output with the two heroes:
To do it, you can import `or_`:
-//// tab | Python 3.10+
-
-```Python hl_lines="1"
-{!./docs_src/tutorial/where/tutorial009_py310.py[ln:1]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-{!./docs_src/tutorial/where/tutorial009.py[ln:1-3]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial009_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial009.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial009_py310.py ln[1] hl[1] *}
And then pass both expressions to `or_()` and put it inside `.where()`.
For example, here we select the heroes that are the youngest OR the oldest:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial009_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial009.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial009_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial009.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial009_py310.py ln[42:47] hl[44] *}
When we run it, this generates the output:
To do that, we can import `col()` (as short for "column"):
-//// tab | Python 3.10+
-
-```Python hl_lines="1"
-{!./docs_src/tutorial/where/tutorial011_py310.py[ln:1]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="3"
-{!./docs_src/tutorial/where/tutorial011.py[ln:1-3]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial011_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial011.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial011_py310.py ln[1] hl[1] *}
And then put the **class attribute** inside `col()` when using it in a `.where()`:
-//// tab | Python 3.10+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial011_py310.py[ln:42-47]!}
-
-# Code below omitted π
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python hl_lines="5"
-# Code above omitted π
-
-{!./docs_src/tutorial/where/tutorial011.py[ln:44-49]!}
-
-# Code below omitted π
-```
-
-////
-
-/// details | π Full file preview
-
-//// tab | Python 3.10+
-
-```Python
-{!./docs_src/tutorial/where/tutorial011_py310.py!}
-```
-
-////
-
-//// tab | Python 3.7+
-
-```Python
-{!./docs_src/tutorial/where/tutorial011.py!}
-```
-
-////
-
-///
+{* ./docs_src/tutorial/where/tutorial011_py310.py ln[42:47] hl[44] *}
So, now the comparison is not:
# For griffe, it formats with black
typer == 0.12.3
mkdocs-macros-plugin==1.0.5
-markdown-include-variants==0.0.3
+markdown-include-variants==0.0.4