# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/advanced/decimal/tutorial001.py!}
```
-</details>
+///
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).
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/advanced/decimal/tutorial001.py!}
```
-</details>
+///
## Select Decimal data
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/advanced/decimal/tutorial001.py!}
```
-</details>
+///
## Review the results
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
Next, I'll show you a bit more about the synchronization of data between the database and the Python code.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
### How `Optional` Helps
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
That will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
This will, again, output the `id`s of the objects as `None`:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
And now, something unexpected happens, look at the output, it seems as if the `Hero` instance objects had no data at all:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
Now we are actually accessing the attributes, because instead of printing the whole object `hero_1`:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
When Python executes this code:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
```
-</details>
+///
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>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
```
-</details>
+///
Make sure you remove the `database.db` file before running the examples to get the same results.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
This would hopefully look already familiar.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
## Run it
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
We haven't committed this hero to the database yet, but there are already a couple of things to pay **attention** to.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
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:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
If we execute that in the command line, it will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
```
-</details>
+///
This is very similar to what we have been doing with the `Hero` model.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
```
-</details>
+///
Most of that should look familiar:
{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:21-28]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
```
-</details>
+///
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:
{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:31-36]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
```
-</details>
+///
## Run the Code
We will continue with the code in the previous example and we will add more things to it.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
## `SELECT` Connected Data with SQL
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial001.py!}
```
-</details>
+///
Notice that in the comparison with `==` we are using the class attributes for both `Hero.team_id` and `Team.id`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial001.py!}
```
-</details>
+///
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`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial001.py!}
```
-</details>
+///
## Run the Program
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial002.py!}
```
-</details>
+///
Also notice that we are still including `Team` in the `select(Hero, Team)`, because we still want to access that data.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial003.py!}
```
-</details>
+///
And if we run it, it will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial004.py!}
```
-</details>
+///
Here we are **filtering** with `.where()` to get only the heroes that belong to the **Preventers** team.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/select/tutorial005.py!}
```
-</details>
+///
And if we run that, it will output:
We will continue with the code from the previous chapter.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/update/tutorial001.py!}
```
-</details>
+///
## Break a Connection
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/delete/tutorial001.py!}
```
-</details>
+///
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>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
## Assign a Team to a Hero
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/update/tutorial001.py!}
```
-</details>
+///
We can simply **assign** a value to that field attribute `team_id`, then `add()` the hero to the session, and then `commit()`.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
This class `Hero` **represents the table** for our heroes. And each instance we create later will **represent a row** in the table.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
Let's now see with more detail these field/column declarations.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
/// tip
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
That way, we tell **SQLModel** that this `id` field/column is the primary key of the table.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
You should normally have a single **engine** object for your whole application and re-use it everywhere.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
You can read a lot more about all the databases supported by **SQLAlchemy** (and that way supported by **SQLModel**) in the <a href="https://docs.sqlalchemy.org/en/14/core/engines.html" class="external-link" target="_blank">SQLAlchemy documentation</a>.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
But in production, you would probably want to remove `echo=True`:
Put the code it in a file `app.py` if you haven't already.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
-</details>
+///
/// tip
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial002.py!}
```
-</details>
+///
If `SQLModel.metadata.create_all(engine)` was not in a function and we tried to import something from this module (from this file) in another, it would try to create the database and table **every time** we executed that other file that imported this module.
As before, we'll continue from where we left off with the previous code.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial003.py!}
```
-</details>
+///
Remember to remove the `database.db` file before running the examples to get the same results.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
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:
{!./docs_src/tutorial/delete/tutorial001.py[ln:92-100]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
That will print the same existing hero **Spider-Youngster**:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
## Commit the Session
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
The same as we have seen before, `.commit()` will also save anything else that was added to the session. Including updates, or created heroes.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
This will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/delete/tutorial001.py!}
```
-</details>
+///
This will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
```
-</details>
+///
After deleting it successfully, we just return a response of:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py!}
```
-</details>
+///
We want to allow clients to set different `offset` and `limit` values.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
```
-</details>
+///
Here's the important detail, and probably the most important feature of **SQLModel**: only `Hero` is declared with `table = True`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
```
-</details>
+///
Let's check that in detail.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
```
-</details>
+///
As you can see, this is *not* a **table model**, it doesn't have the `table = True` config.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
```
-</details>
+///
Notice that `Hero` now doesn't inherit from `SQLModel`, but from `HeroBase`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
```
-</details>
+///
This won't affect this parent **data model** `HeroBase`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
```
-</details>
+///
What's happening here?
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
```
-</details>
+///
## Review the Updated Docs UI
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
```
-</details>
+///
For example, to get the hero with ID `2` we would send a `GET` request to:
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
```
-</details>
+///
## Return the Hero
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
```
-</details>
+///
## Check the Docs UI
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
```
-</details>
+///
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>?
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
```
-</details>
+///
## Don't Include All the Data
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
```
-</details>
+///
These two models are very **simple in code**, but there's a lot happening here. Let's check it out.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
```
-</details>
+///
## Check It Out in the Docs UI
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
```
-</details>
+///
## List of Heroes in `response_model`
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
```
-</details>
+///
## FastAPI and Response Model
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
```
-</details>
+///
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*.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
```
-</details>
+///
## Use the Dependency
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
```
-</details>
+///
We will see how this is very useful when testing the code later. β
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-106]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
```
-</details>
+///
## Recap
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
```
-</details>
+///
There's only one change here from the code we have used before, the `check_same_thread` in the `connect_args`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
```
-</details>
+///
## Create Database and Tables on `startup`
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
```
-</details>
+///
## Create Heroes *Path Operation*
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
```
-</details>
+///
/// info
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25-46]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
```
-</details>
+///
This is pretty straightforward.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
```
-</details>
+///
We now also have **relationship attributes**. π
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
```
-</details>
+///
We now have a `team_id` in the hero models.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
```
-</details>
+///
## Path Operations for Teams
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
```
-</details>
+///
## Using Relationships Attributes
Now we will see how useful it is to have this session dependency. β¨
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/main.py!}
```
-</details>
+///
## File Structure
And also, because it never has to write anything to a file and it's all just in memory, it will be even faster than normally. π
-<details>
-<summary>
-Other alternatives and ideas π
-</summary>
+/// details | Other alternatives and ideas π
+
Before arriving at the idea of using an **in-memory database** we could have explored other alternatives and ideas.
The first is that we are not deleting the file after we finish the test, so the next test could have **leftover data**. So, the right thing would be to delete the file right after finishing the test. π₯
Of course, we could also fix that, using some **random name** for each testing database file... but in the case of SQLite, we have an even better alternative by just using an **in-memory database**. β¨
-</details>
+///
## Configure the In-Memory Database
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
```
-</details>
+///
In this test function, we want to check that the *path operation* to **read a list of heroes** actually sends us heroes.
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:84-125]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
```
-</details>
+///
## Run the Tests
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
```
-</details>
+///
This is almost the same as `HeroBase`, but all the fields are optional, so we can't simply inherit from `HeroBase`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
```
-</details>
+///
We also read the `hero_id` from the *path parameter* and the request body, a `HeroUpdate`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
```
-</details>
+///
### Get the New Data
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
```
-</details>
+///
## Update the Hero in the Database
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
```
-</details>
+///
If you are not familiar with that `setattr()`, it takes an object, like the `db_hero`, then an attribute name (`key`), that in our case could be `"name"`, and a value (`value`). And then it **sets the attribute with that name to the value**.
Fine, in that case, you can **sneak peek** the final code to create indexes here.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python hl_lines="8 10"
{!./docs_src/tutorial/indexes/tutorial002.py!}
```
-</details>
+///
..but if you are not an expert, **continue reading**, this will probably be useful. π€
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial001.py!}
```
-</details>
+///
Let's now update it to tell **SQLModel** to create an index for the `name` field when creating the table:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/indexes/tutorial001.py!}
```
-</details>
+///
We use the same `Field()` again as we did before, and set `index=True`. That's it! π
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/indexes/tutorial001.py!}
```
-</details>
+///
This is exactly the same code as we had before, but now the database will **use the index** underneath.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/indexes/tutorial002.py!}
```
-</details>
+///
In this case, we want the default value of `age` to continue being `None`, so we set `default=None` when using `Field()`.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial002.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial001.py!}
```
-</details>
+///
Then we can create a new session:
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial001.py!}
```
-</details>
+///
The new `Session` takes an `engine` as a parameter. And it will use the **engine** underneath.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial001.py!}
```
-</details>
+///
By this point, our heroes are *not* stored in the database yet.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial001.py!}
```
-</details>
+///
Once this line is executed, the **session** will use the **engine** to save all the data in the database by sending the corresponding SQL.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial002.py!}
```
-</details>
+///
And then we can call that single `main()` function from that main block:
{!./docs_src/tutorial/insert/tutorial002.py[ln:36-42]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial002.py!}
```
-</details>
+///
By having everything that should happen when called as a script in a single function, we can easily add more code later on.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial001.py!}
```
-</details>
+///
But what happens if we forget to close the session?
{!./docs_src/tutorial/insert/tutorial002.py[ln:23-33]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial002.py!}
```
-</details>
+///
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**.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
```
-</details>
+///
## Review Select All
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial003.py!}
```
-</details>
+///
But this would get us **all** the heroes at the same time, in a database that could have thousands, that could be problematic.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/offset_and_limit/tutorial002.py!}
```
-</details>
+///
The way this works is that the special **select** object we get from `select()` has methods like `.where()`, `.offset()` and `.limit()`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/offset_and_limit/tutorial003.py!}
```
-</details>
+///
The database right now has **only 7 rows**, so this query can only get 1 row.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/offset_and_limit/tutorial004.py!}
```
-</details>
+///
## 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>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
## Create Heroes
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
This is very similar to what we have done before.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
## Add to Main
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
## Run the Program
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
This is a **SQLModel** class model table like any other.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
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).
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
We **removed** the previous `team_id` field (column) because now the relationship is done via the link table. π₯
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
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:
{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:83-84]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
## Run the Code
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
```
-</details>
+///
The new **relationship attributes** have their own `back_populates` pointing to new relationship attributes we will create in the `Hero` and `Team` models:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
```
-</details>
+///
## Update Hero Model
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
```
-</details>
+///
## Create Relationships
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
```
-</details>
+///
## Run the Program with the New Relationship
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
```
-</details>
+///
## Run the Program with the Updated Relationships
We'll continue from where we left off with the previous code.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
```
-</details>
+///
## Get Data to Update
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
```
-</details>
+///
And of course, we have to add `update_heroes()` to our `main()` function:
{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:100-107]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
```
-</details>
+///
## Add Many-to-Many Relationships
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
```
-</details>
+///
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>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/indexes/tutorial002.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/indexes/tutorial002.py!}
```
-</details>
+///
But let's say that we are not interested in all the rows, just the **first** one.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial001.py!}
```
-</details>
+///
This will return the first object in the `results` (if there was any).
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial002.py!}
```
-</details>
+///
In this case, as there's no hero with an age less than 25, `.first()` will return `None`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial003.py!}
```
-</details>
+///
Here we know that there's only one `"Deadpond"`, and there shouldn't be any more than one.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial004.py!}
```
-</details>
+///
That would find 2 rows, and would end up with the same error.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial005.py!}
```
-</details>
+///
In this case, as there are no heroes with an age less than 25, `.one()` will raise an error.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial006.py!}
```
-</details>
+///
That would result in the same as some examples above.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial007.py!}
```
-</details>
+///
That would work correctly, as expected. But there's a shorter version. π
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial008.py!}
```
-</details>
+///
`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()`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/one/tutorial009.py!}
```
-</details>
+///
Running that will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
```
-</details>
+///
## Read Data Objects
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
```
-</details>
+///
Up to this point, it's all good. π
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
```
-</details>
+///
The first important thing is, we *haven't committed* the hero yet, so accessing the list of heroes would not trigger an automatic refresh.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
```
-</details>
+///
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:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
```
-</details>
+///
And we can keep the rest of the code the same:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
```
-</details>
+///
The string in `back_populates` is the name of the attribute *in the other* model, that will reference *the current* model.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
```
-</details>
+///
The string in `back_populates="team"` refers to the attribute `team` in the class `Hero` (the other class).
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py!}
```
-</details>
+///
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
There are several things to **notice** here.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
```
-</details>
+///
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`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
```
-</details>
+///
## Create a Team with Heroes
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
```
-</details>
+///
Here we create two heroes first, **Black Lion** and **Princess Sure-E**, and then we pass them in the `heroes` argument.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
```
-</details>
+///
This is a **plain field** like all the others, all representing a **column in the table**.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
```
-</details>
+///
Next, use that `Relationship` to declare a new attribute in the model classes:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
```
-</details>
+///
## What Are These Relationship Attributes
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
```
-</details>
+///
## Select the Related Team - Old Way
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
```
-</details>
+///
## Get Relationship Team - New Way
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
```
-</details>
+///
/// tip
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
```
-</details>
+///
That would print a list with all the heroes in the Preventers team:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
```
-</details>
+///
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:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
```
-</details>
+///
## Recap
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
```
-</details>
+///
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>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/insert/tutorial002.py!}
```
-</details>
+///
We are creating a **SQLModel** `Hero` class model and creating some records.
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
## Create a `select` Statement
# More code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
And then we will use it to create a `SELECT` statement in Python code:
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
It's a very simple line of code that conveys a lot of information:
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
This will print the output:
# More code here later π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
## Review The Code
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial003.py!}
```
-</details>
+///
With this now we have all the heroes in a list in the `heroes` variable.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial004.py!}
```
-</details>
+///
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>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/indexes/tutorial002.py!}
```
-</details>
+///
Remember to remove the `database.db` file before running the examples to get the same results.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
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:
{!./docs_src/tutorial/update/tutorial001.py[ln:58-65]!}
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
Up to that point, running that in the command line will output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
## Add the Hero to the Session
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
## Commit the Session
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
It will also save anything else that was added to the session.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
This refresh will trigger the same SQL query that would be automatically triggered by accessing an attribute. So it will generate this output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial001.py!}
```
-</details>
+///
Because we refreshed it right after updating it, it has fresh data, including the new `age` we just updated.
{!./docs_src/tutorial/update/annotations/en/tutorial004.md!}
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/update/tutorial004.py!}
```
-</details>
+///
/// tip
And now we will update `select_heroes()` to filter the data.
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python hl_lines="36-41"
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
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.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/select/tutorial001.py!}
```
-</details>
+///
## Filter Rows Using `WHERE` with **SQLModel**
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial001.py!}
```
-</details>
+///
It's a very small change, but it's packed of details. Let's explore them.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial001.py!}
```
-</details>
+///
We take that statement, that now includes a `WHERE`, and we `exec()` it to get the results.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial002.py!}
```
-</details>
+///
That would output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial003.py!}
```
-</details>
+///
Now that we have several heroes with different ages, it's gonna be more obvious what the next comparisons do.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial003.py!}
```
-</details>
+///
That would output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial004.py!}
```
-</details>
+///
Because we are using `>=`, the age `35` will be included in the output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial005.py!}
```
-</details>
+///
And we get the younger one with an age in the database:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial006.py!}
```
-</details>
+///
And we get the younger ones, `35` and below:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial007.py!}
```
-</details>
+///
This will select the rows `WHERE` the `age` is **greater than or equal** to `35`, `AND` also the `age` is **less than** `40`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial008.py!}
```
-</details>
+///
This is the same as the above, and will result in the same output with the two heroes:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial009.py!}
```
-</details>
+///
And then pass both expressions to `or_()` and put it inside `.where()`.
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial009.py!}
```
-</details>
+///
When we run it, this generates the output:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial011.py!}
```
-</details>
+///
And then put the **class attribute** inside `col()` when using it in a `.where()`:
# Code below omitted π
```
-<details>
-<summary>π Full file preview</summary>
+/// details | π Full file preview
```Python
{!./docs_src/tutorial/where/tutorial011.py!}
```
-</details>
+///
So, now the comparison is not: