📝 Update details syntax with new pymdown extensions format (#713)
This commit is contained in:
parent
be464fba69
commit
799d0aa7a6
@ -47,14 +47,13 @@ Let's say that each hero in the database will have an amount of money. We could
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/advanced/decimal/tutorial001.py!}
|
{!./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).
|
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).
|
||||||
|
|
||||||
@ -96,14 +95,13 @@ When creating new models you can actually pass normal (`float`) numbers, Pydanti
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/advanced/decimal/tutorial001.py!}
|
{!./docs_src/advanced/decimal/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Select Decimal data
|
## Select Decimal data
|
||||||
|
|
||||||
@ -117,14 +115,13 @@ Then, when working with Decimal types, you can confirm that they indeed avoid th
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/advanced/decimal/tutorial001.py!}
|
{!./docs_src/advanced/decimal/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Review the results
|
## Review the results
|
||||||
|
|
||||||
|
@ -14,14 +14,13 @@ But the same `id` field actually **can be `None`** in the Python code, so we dec
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./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.
|
Next, I'll show you a bit more about the synchronization of data between the database and the Python code.
|
||||||
|
|
||||||
@ -39,14 +38,13 @@ When we create a new `Hero` instance, we don't set the `id`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
### How `Optional` Helps
|
### How `Optional` Helps
|
||||||
|
|
||||||
@ -82,14 +80,13 @@ We can confirm that by printing our heroes before adding them to the database:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That will output:
|
That will output:
|
||||||
|
|
||||||
@ -128,14 +125,13 @@ We can verify by creating a session using a `with` block and adding the objects.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This will, again, output the `id`s of the objects as `None`:
|
This will, again, output the `id`s of the objects as `None`:
|
||||||
|
|
||||||
@ -168,14 +164,13 @@ Then we can `commit` the changes in the session, and print again:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./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:
|
And now, something unexpected happens, look at the output, it seems as if the `Hero` instance objects had no data at all:
|
||||||
|
|
||||||
@ -241,14 +236,13 @@ To confirm and understand how this **automatic expiration and refresh** of data
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./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`:
|
Now we are actually accessing the attributes, because instead of printing the whole object `hero_1`:
|
||||||
|
|
||||||
@ -338,14 +332,13 @@ You can do that too with `session.refresh(object)`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
When Python executes this code:
|
When Python executes this code:
|
||||||
|
|
||||||
@ -411,14 +404,13 @@ There are no surprises here, it still works:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
{!./docs_src/tutorial/automatic_id_none_refresh/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And the output shows again the same data:
|
And the output shows again the same data:
|
||||||
|
|
||||||
|
@ -45,14 +45,13 @@ We will later update **Spider-Boy** to add him to the **Preventers** team too, b
|
|||||||
|
|
||||||
We will continue with the code in the previous example and we will add more things to it.
|
We will continue with the code in the previous example and we will add more things to it.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
{!./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.
|
Make sure you remove the `database.db` file before running the examples to get the same results.
|
||||||
|
|
||||||
@ -72,14 +71,13 @@ Let's start by creating two teams:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This would hopefully look already familiar.
|
This would hopefully look already familiar.
|
||||||
|
|
||||||
@ -103,14 +101,13 @@ Let's not forget to add this function `create_heroes()` to the `main()` function
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run it
|
## Run it
|
||||||
|
|
||||||
@ -151,14 +148,13 @@ As the `Hero` class model now has a field (column, attribute) `team_id`, we can
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./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.
|
We haven't committed this hero to the database yet, but there are already a couple of things to pay **attention** to.
|
||||||
|
|
||||||
@ -190,14 +186,13 @@ Let's now create two more heroes:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./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:
|
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:
|
||||||
|
|
||||||
@ -236,14 +231,13 @@ Now let's refresh and print those new heroes to see their new ID pointing to the
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
|
|
||||||
If we execute that in the command line, it will output:
|
If we execute that in the command line, it will output:
|
||||||
|
@ -63,14 +63,13 @@ Import the things we need from `sqlmodel` and create a new `Team` model:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This is very similar to what we have been doing with the `Hero` model.
|
This is very similar to what we have been doing with the `Hero` model.
|
||||||
|
|
||||||
@ -95,14 +94,13 @@ This is the same model we have been using up to now, we are just adding the new
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Most of that should look familiar:
|
Most of that should look familiar:
|
||||||
|
|
||||||
@ -142,14 +140,13 @@ Now we can add the same code as before to create the engine and the function to
|
|||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:21-28]!}
|
{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:21-28]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
{!./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:
|
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:
|
||||||
|
|
||||||
@ -159,14 +156,13 @@ And as before, we'll call this function from another function `main()`, and we'l
|
|||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:31-36]!}
|
{!./docs_src/tutorial/connect/create_tables/tutorial001.py[ln:31-36]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
{!./docs_src/tutorial/connect/create_tables/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run the Code
|
## Run the Code
|
||||||
|
|
||||||
|
@ -35,14 +35,13 @@ And the `hero` table has this data:
|
|||||||
|
|
||||||
We will continue with the code in the previous example and we will add more things to it.
|
We will continue with the code in the previous example and we will add more things to it.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## `SELECT` Connected Data with SQL
|
## `SELECT` Connected Data with SQL
|
||||||
|
|
||||||
@ -132,14 +131,13 @@ So, we can pass the `Hero` and `Team` model classes. And we can also use both th
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial001.py!}
|
{!./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`.
|
Notice that in the comparison with `==` we are using the class attributes for both `Hero.team_id` and `Team.id`.
|
||||||
|
|
||||||
@ -157,14 +155,13 @@ And as we used `select` with two models, we will receive tuples of instances of
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial001.py!}
|
{!./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`.
|
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`.
|
||||||
|
|
||||||
@ -190,14 +187,13 @@ As always, we must remember to add this new `select_heroes()` function to the `m
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial001.py!}
|
{!./docs_src/tutorial/connect/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
|
|
||||||
## Run the Program
|
## Run the Program
|
||||||
@ -312,14 +308,13 @@ And in SQLModel (actually SQLAlchemy), when using the `.join()`, because we alre
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial002.py!}
|
{!./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.
|
Also notice that we are still including `Team` in the `select(Hero, Team)`, because we still want to access that data.
|
||||||
|
|
||||||
@ -454,14 +449,13 @@ Now let's replicate the same query in **SQLModel**.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial003.py!}
|
{!./docs_src/tutorial/connect/select/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And if we run it, it will output:
|
And if we run it, it will output:
|
||||||
|
|
||||||
@ -516,14 +510,13 @@ We could even add some additional `.where()` after `.join()` to filter the data
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial004.py!}
|
{!./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.
|
Here we are **filtering** with `.where()` to get only the heroes that belong to the **Preventers** team.
|
||||||
|
|
||||||
@ -562,14 +555,13 @@ By putting the `Team` in `select()` we tell **SQLModel** and the database that w
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/select/tutorial005.py!}
|
{!./docs_src/tutorial/connect/select/tutorial005.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And if we run that, it will output:
|
And if we run that, it will output:
|
||||||
|
|
||||||
|
@ -35,14 +35,13 @@ Let's see how to **remove** connections between rows in tables.
|
|||||||
|
|
||||||
We will continue with the code from the previous chapter.
|
We will continue with the code from the previous chapter.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/update/tutorial001.py!}
|
{!./docs_src/tutorial/connect/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Break a Connection
|
## Break a Connection
|
||||||
|
|
||||||
@ -64,14 +63,13 @@ We can simply set the `team_id` to `None`, and now it doesn't have a connection
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/delete/tutorial001.py!}
|
{!./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()`.
|
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()`.
|
||||||
|
|
||||||
|
@ -37,14 +37,13 @@ Now we'll see how to **update** those connections between rows tables.
|
|||||||
|
|
||||||
We will continue with the code we used to create some heroes, and we'll update them.
|
We will continue with the code we used to create some heroes, and we'll update them.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Assign a Team to a Hero
|
## Assign a Team to a Hero
|
||||||
|
|
||||||
@ -64,14 +63,13 @@ Doing it is just like updating any other field:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/update/tutorial001.py!}
|
{!./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()`.
|
We can simply **assign** a value to that field attribute `team_id`, then `add()` the hero to the session, and then `commit()`.
|
||||||
|
|
||||||
|
@ -47,14 +47,13 @@ For that, we will import `SQLModel` (plus other things we will also use) and cre
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./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.
|
This class `Hero` **represents the table** for our heroes. And each instance we create later will **represent a row** in the table.
|
||||||
|
|
||||||
@ -82,14 +81,13 @@ And the type of each of them will also be the type of table column:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Let's now see with more detail these field/column declarations.
|
Let's now see with more detail these field/column declarations.
|
||||||
|
|
||||||
@ -109,14 +107,13 @@ And we also set the default value of `age` to `None`.
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -152,14 +149,13 @@ To do that, we use the special `Field` function from `sqlmodel` and set the argu
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./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.
|
That way, we tell **SQLModel** that this `id` field/column is the primary key of the table.
|
||||||
|
|
||||||
@ -208,14 +204,13 @@ Creating the **engine** is very simple, just call `create_engine()` with a URL f
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./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.
|
You should normally have a single **engine** object for your whole application and re-use it everywhere.
|
||||||
|
|
||||||
@ -245,14 +240,13 @@ SQLite supports a special database that lives all *in memory*. Hence, it's very
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./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>.
|
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>.
|
||||||
|
|
||||||
@ -270,14 +264,13 @@ It is particularly useful for **learning** and **debugging**:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
But in production, you would probably want to remove `echo=True`:
|
But in production, you would probably want to remove `echo=True`:
|
||||||
|
|
||||||
@ -416,14 +409,13 @@ Let's run the program to see it all working.
|
|||||||
|
|
||||||
Put the code it in a file `app.py` if you haven't already.
|
Put the code it in a file `app.py` if you haven't already.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -534,14 +526,13 @@ Let's put it in a function `create_db_and_tables()`:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/create_db_and_table/tutorial002.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
|
@ -6,14 +6,13 @@ Now let's delete some data using **SQLModel**.
|
|||||||
|
|
||||||
As before, we'll continue from where we left off with the previous code.
|
As before, we'll continue from where we left off with the previous code.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial003.py!}
|
{!./docs_src/tutorial/update/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Remember to remove the `database.db` file before running the examples to get the same results.
|
Remember to remove the `database.db` file before running the examples to get the same results.
|
||||||
|
|
||||||
@ -71,14 +70,13 @@ We'll start by selecting the hero `"Spider-Youngster"` that we updated in the pr
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./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:
|
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:
|
||||||
|
|
||||||
@ -88,14 +86,13 @@ As this is a new function `delete_heroes()`, we'll also add it to the `main()` f
|
|||||||
{!./docs_src/tutorial/delete/tutorial001.py[ln:92-100]!}
|
{!./docs_src/tutorial/delete/tutorial001.py[ln:92-100]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./docs_src/tutorial/delete/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That will print the same existing hero **Spider-Youngster**:
|
That will print the same existing hero **Spider-Youngster**:
|
||||||
|
|
||||||
@ -131,14 +128,13 @@ Now, very similar to how we used `session.add()` to add or update new heroes, we
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./docs_src/tutorial/delete/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Commit the Session
|
## Commit the Session
|
||||||
|
|
||||||
@ -154,14 +150,13 @@ This will save all the changes stored in the **session**, like the deleted hero:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./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.
|
The same as we have seen before, `.commit()` will also save anything else that was added to the session. Including updates, or created heroes.
|
||||||
|
|
||||||
@ -204,14 +199,13 @@ Because of that, the object still contains its attributes with the data in it, s
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./docs_src/tutorial/delete/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This will output:
|
This will output:
|
||||||
|
|
||||||
@ -242,14 +236,13 @@ To confirm if it was deleted, now let's query the database again, with the same
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -294,14 +287,13 @@ We'll do it by checking that the "first" item in the `results` is `None`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/delete/tutorial001.py!}
|
{!./docs_src/tutorial/delete/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This will output:
|
This will output:
|
||||||
|
|
||||||
|
@ -20,14 +20,13 @@ And if we actually find a hero, we just delete it with the **session**.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
After deleting it successfully, we just return a response of:
|
After deleting it successfully, we just return a response of:
|
||||||
|
|
||||||
|
@ -32,14 +32,13 @@ And by default, we will return a maximum of `100` heroes, so `limit` will have a
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We want to allow clients to set different `offset` and `limit` values.
|
We want to allow clients to set different `offset` and `limit` values.
|
||||||
|
|
||||||
|
@ -119,14 +119,13 @@ The simplest way to solve it could be to create **multiple models**, each one wi
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
|
{!./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`.
|
Here's the important detail, and probably the most important feature of **SQLModel**: only `Hero` is declared with `table = True`.
|
||||||
|
|
||||||
@ -156,14 +155,13 @@ Let's first check how is the process to create a hero now:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/multiple_models/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Let's check that in detail.
|
Let's check that in detail.
|
||||||
|
|
||||||
@ -267,14 +265,13 @@ So let's create a **base** model `HeroBase` that the others can inherit from:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
{!./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.
|
As you can see, this is *not* a **table model**, it doesn't have the `table = True` config.
|
||||||
|
|
||||||
@ -292,14 +289,13 @@ Let's start with the only **table model**, the `Hero`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Notice that `Hero` now doesn't inherit from `SQLModel`, but from `HeroBase`.
|
Notice that `Hero` now doesn't inherit from `SQLModel`, but from `HeroBase`.
|
||||||
|
|
||||||
@ -323,14 +319,13 @@ Notice that the parent model `HeroBase` is not a **table model**, but still, we
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This won't affect this parent **data model** `HeroBase`.
|
This won't affect this parent **data model** `HeroBase`.
|
||||||
|
|
||||||
@ -350,14 +345,13 @@ This is a fun one:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
What's happening here?
|
What's happening here?
|
||||||
|
|
||||||
@ -385,14 +379,13 @@ This one just declares that the `id` field is required when reading a hero from
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
{!./docs_src/tutorial/fastapi/multiple_models/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Review the Updated Docs UI
|
## Review the Updated Docs UI
|
||||||
|
|
||||||
|
@ -22,14 +22,13 @@ If you need to refresh how *path parameters* work, including their data validati
|
|||||||
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
|
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
|
{!./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:
|
For example, to get the hero with ID `2` we would send a `GET` request to:
|
||||||
|
|
||||||
@ -57,14 +56,13 @@ This will let the client know that they probably made a mistake on their side an
|
|||||||
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
|
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Return the Hero
|
## Return the Hero
|
||||||
|
|
||||||
@ -80,14 +78,13 @@ And because we are using the `response_model` with `HeroRead`, it will be valida
|
|||||||
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
|
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py[ln:61-67]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/read_one/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Check the Docs UI
|
## Check the Docs UI
|
||||||
|
|
||||||
|
@ -64,14 +64,13 @@ And the same way, we declared the `TeamRead` with only the same base fields of t
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
{!./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>?
|
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>?
|
||||||
|
|
||||||
@ -89,14 +88,13 @@ In this case, we used `response_model=TeamRead` and `response_model=HeroRead`, s
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Don't Include All the Data
|
## Don't Include All the Data
|
||||||
|
|
||||||
@ -186,14 +184,13 @@ We'll add them **after** the other models so that we can easily reference the pr
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
|
{!./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.
|
These two models are very **simple in code**, but there's a lot happening here. Let's check it out.
|
||||||
|
|
||||||
@ -239,14 +236,13 @@ In the case of the hero, this tells FastAPI to extract the `team` too. And in th
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/relationships/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Check It Out in the Docs UI
|
## Check It Out in the Docs UI
|
||||||
|
|
||||||
|
@ -40,14 +40,13 @@ For example, we can pass the same `Hero` **SQLModel** class (because it is also
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## List of Heroes in `response_model`
|
## List of Heroes in `response_model`
|
||||||
|
|
||||||
@ -65,14 +64,13 @@ First, we import `List` from `typing` and then we declare the `response_model` w
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/response_model/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## FastAPI and Response Model
|
## FastAPI and Response Model
|
||||||
|
|
||||||
|
@ -14,14 +14,13 @@ Up to now, we have been creating a session in each *path operation*, in a `with`
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/delete/tutorial001.py!}
|
{!./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*.
|
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*.
|
||||||
|
|
||||||
@ -43,14 +42,13 @@ It could use `yield` instead of `return`, and in that case **FastAPI** will make
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Use the Dependency
|
## Use the Dependency
|
||||||
|
|
||||||
@ -72,14 +70,13 @@ We import `Depends()` from `fastapi`. Then we use it in the *path operation func
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -121,14 +118,13 @@ This means that in the main code of the *path operation function*, it will work
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -148,14 +144,13 @@ But now, the `with` block is not explicitly in the function, but in the dependen
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We will see how this is very useful when testing the code later. ✅
|
We will see how this is very useful when testing the code later. ✅
|
||||||
|
|
||||||
@ -183,14 +178,13 @@ And then we remove the previous `with` block with the old **session**.
|
|||||||
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-106]!}
|
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py[ln:55-106]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/session_with_dependency/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Recap
|
## Recap
|
||||||
|
|
||||||
|
@ -43,14 +43,13 @@ This is almost the same code we have seen up to now in previous examples:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
{!./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`.
|
There's only one change here from the code we have used before, the `check_same_thread` in the `connect_args`.
|
||||||
|
|
||||||
@ -88,14 +87,13 @@ And then create an `app` object that is an instance of that `FastAPI` class:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Create Database and Tables on `startup`
|
## Create Database and Tables on `startup`
|
||||||
|
|
||||||
@ -111,14 +109,13 @@ This should be called only once at startup, not before every request, so we put
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Create Heroes *Path Operation*
|
## Create Heroes *Path Operation*
|
||||||
|
|
||||||
@ -140,14 +137,13 @@ It will be called when a user sends a request with a `POST` **operation** to the
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// info
|
/// info
|
||||||
|
|
||||||
@ -187,14 +183,13 @@ Now let's add another **path operation** to read all the heroes:
|
|||||||
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25-46]!}
|
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py[ln:25-46]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/simple_hero_api/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This is pretty straightforward.
|
This is pretty straightforward.
|
||||||
|
|
||||||
|
@ -24,14 +24,13 @@ And we also create a `TeamUpdate` **data model**.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We now also have **relationship attributes**. 🎉
|
We now also have **relationship attributes**. 🎉
|
||||||
|
|
||||||
@ -47,14 +46,13 @@ Let's now update the `Hero` models too.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We now have a `team_id` in the hero models.
|
We now have a `team_id` in the hero models.
|
||||||
|
|
||||||
@ -74,14 +72,13 @@ Notice that the **relationship attributes**, the ones with `Relationship()`, are
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Path Operations for Teams
|
## Path Operations for Teams
|
||||||
|
|
||||||
@ -97,14 +94,13 @@ These are equivalent and very similar to the **path operations** for the **heroe
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/teams/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Using Relationships Attributes
|
## Using Relationships Attributes
|
||||||
|
|
||||||
|
@ -14,14 +14,13 @@ We will use the application with the hero models, but without team models, and w
|
|||||||
|
|
||||||
Now we will see how useful it is to have this session dependency. ✨
|
Now we will see how useful it is to have this session dependency. ✨
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/main.py!}
|
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/main.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## File Structure
|
## File Structure
|
||||||
|
|
||||||
@ -171,10 +170,8 @@ But **it works great for testing**, because it can be quickly created before eac
|
|||||||
|
|
||||||
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. 🏎
|
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>
|
/// details | Other alternatives and ideas 👀
|
||||||
<summary>
|
|
||||||
Other alternatives and ideas 👀
|
|
||||||
</summary>
|
|
||||||
Before arriving at the idea of using an **in-memory database** we could have explored 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. 🔥
|
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. 🔥
|
||||||
@ -187,7 +184,7 @@ So, if we tried to run the tests at the same time **in parallel** to try to spee
|
|||||||
|
|
||||||
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**. ✨
|
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
|
## Configure the In-Memory Database
|
||||||
|
|
||||||
@ -315,14 +312,13 @@ Let's add some more tests:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
|
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -352,14 +348,13 @@ But for the next test function, we will require **both fixtures**, the **client*
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
|
{!./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.
|
In this test function, we want to check that the *path operation* to **read a list of heroes** actually sends us heroes.
|
||||||
|
|
||||||
@ -391,14 +386,13 @@ Using the same ideas, requiring the fixtures, creating data that we need for the
|
|||||||
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:84-125]!}
|
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py[ln:84-125]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
|
{!./docs_src/tutorial/fastapi/app_testing/tutorial001/test_main.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run the Tests
|
## Run the Tests
|
||||||
|
|
||||||
|
@ -30,14 +30,13 @@ So, let's create this new `HeroUpdate` model:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
{!./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`.
|
This is almost the same as `HeroBase`, but all the fields are optional, so we can't simply inherit from `HeroBase`.
|
||||||
|
|
||||||
@ -55,14 +54,13 @@ We will use a `PATCH` HTTP operation. This is used to **partially update data**,
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We also read the `hero_id` from the *path parameter* and the request body, a `HeroUpdate`.
|
We also read the `hero_id` from the *path parameter* and the request body, a `HeroUpdate`.
|
||||||
|
|
||||||
@ -80,14 +78,13 @@ So, we need to read the hero from the database, with the **same logic** we used
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
### Get the New Data
|
### Get the New Data
|
||||||
|
|
||||||
@ -147,14 +144,13 @@ Then we use that to get the data that was actually sent by the client:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Update the Hero in the Database
|
## Update the Hero in the Database
|
||||||
|
|
||||||
@ -168,14 +164,13 @@ Now that we have a **dictionary with the data sent by the client**, we can itera
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/fastapi/update/tutorial001.py!}
|
{!./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**.
|
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**.
|
||||||
|
|
||||||
|
@ -20,14 +20,13 @@ Are you already a **SQL expert** and don't have time for all my explanations?
|
|||||||
|
|
||||||
Fine, in that case, you can **sneak peek** the final code to create indexes here.
|
Fine, in that case, you can **sneak peek** the final code to create indexes here.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python hl_lines="8 10"
|
```Python hl_lines="8 10"
|
||||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
..but if you are not an expert, **continue reading**, this will probably be useful. 🤓
|
..but if you are not an expert, **continue reading**, this will probably be useful. 🤓
|
||||||
|
|
||||||
@ -270,14 +269,13 @@ Here's the `Hero` model we had before:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial001.py!}
|
{!./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:
|
Let's now update it to tell **SQLModel** to create an index for the `name` field when creating the table:
|
||||||
|
|
||||||
@ -287,14 +285,13 @@ Let's now update it to tell **SQLModel** to create an index for the `name` field
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/indexes/tutorial001.py!}
|
{!./docs_src/tutorial/indexes/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We use the same `Field()` again as we did before, and set `index=True`. That's it! 🚀
|
We use the same `Field()` again as we did before, and set `index=True`. That's it! 🚀
|
||||||
|
|
||||||
@ -324,14 +321,13 @@ This is great because it means that indexes are very **simple to use**. But it m
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/indexes/tutorial001.py!}
|
{!./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.
|
This is exactly the same code as we had before, but now the database will **use the index** underneath.
|
||||||
|
|
||||||
@ -380,14 +376,13 @@ We are going to query the `hero` table doing comparisons on the `age` field too,
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
{!./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()`.
|
In this case, we want the default value of `age` to continue being `None`, so we set `default=None` when using `Field()`.
|
||||||
|
|
||||||
|
@ -135,14 +135,13 @@ We'll create 3 right away, for the 3 heroes:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial002.py!}
|
{!./docs_src/tutorial/insert/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -180,14 +179,13 @@ The first step is to import the `Session` class:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial001.py!}
|
{!./docs_src/tutorial/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Then we can create a new session:
|
Then we can create a new session:
|
||||||
|
|
||||||
@ -199,14 +197,13 @@ Then we can create a new session:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial001.py!}
|
{!./docs_src/tutorial/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
The new `Session` takes an `engine` as a parameter. And it will use the **engine** underneath.
|
The new `Session` takes an `engine` as a parameter. And it will use the **engine** underneath.
|
||||||
|
|
||||||
@ -227,14 +224,13 @@ Now that we have some hero model instances (some objects in memory) and a **sess
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial001.py!}
|
{!./docs_src/tutorial/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
By this point, our heroes are *not* stored in the database yet.
|
By this point, our heroes are *not* stored in the database yet.
|
||||||
|
|
||||||
@ -265,14 +261,13 @@ Now that we have the heroes in the **session** and that we are ready to save all
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial001.py!}
|
{!./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.
|
Once this line is executed, the **session** will use the **engine** to save all the data in the database by sending the corresponding SQL.
|
||||||
|
|
||||||
@ -306,14 +301,13 @@ But to keep things a bit more organized, let's instead create a new function `ma
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial002.py!}
|
{!./docs_src/tutorial/insert/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And then we can call that single `main()` function from that main block:
|
And then we can call that single `main()` function from that main block:
|
||||||
|
|
||||||
@ -322,14 +316,13 @@ And then we can call that single `main()` function from that main block:
|
|||||||
{!./docs_src/tutorial/insert/tutorial002.py[ln:36-42]!}
|
{!./docs_src/tutorial/insert/tutorial002.py[ln:36-42]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial002.py!}
|
{!./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.
|
By having everything that should happen when called as a script in a single function, we can easily add more code later on.
|
||||||
|
|
||||||
@ -392,14 +385,13 @@ So once we are done with the session, we should **close** it to make it release
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial001.py!}
|
{!./docs_src/tutorial/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
But what happens if we forget to close the session?
|
But what happens if we forget to close the session?
|
||||||
|
|
||||||
@ -418,14 +410,13 @@ But there's a better way to handle the session, using a `with` block:
|
|||||||
{!./docs_src/tutorial/insert/tutorial002.py[ln:23-33]!}
|
{!./docs_src/tutorial/insert/tutorial002.py[ln:23-33]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial002.py!}
|
{!./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**.
|
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**.
|
||||||
|
|
||||||
|
@ -22,14 +22,13 @@ Again, we will create several heroes to have some data to select from:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
|
{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Review Select All
|
## Review Select All
|
||||||
|
|
||||||
@ -43,14 +42,13 @@ This is the code we had to select all the heroes in the `select()` examples:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial003.py!}
|
{!./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.
|
But this would get us **all** the heroes at the same time, in a database that could have thousands, that could be problematic.
|
||||||
|
|
||||||
@ -66,14 +64,13 @@ We currently have 7 heroes in the database. But we could as well have thousands,
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/offset_and_limit/tutorial001.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -144,14 +141,13 @@ We can use `.offset()`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/offset_and_limit/tutorial002.py!}
|
{!./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()`.
|
The way this works is that the special **select** object we get from `select()` has methods like `.where()`, `.offset()` and `.limit()`.
|
||||||
|
|
||||||
@ -198,14 +194,13 @@ Then to get the next batch of 3 rows we would offset all the ones we already saw
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/offset_and_limit/tutorial003.py!}
|
{!./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.
|
The database right now has **only 7 rows**, so this query can only get 1 row.
|
||||||
|
|
||||||
@ -268,14 +263,13 @@ Of course, you can also combine `.limit()` and `.offset()` with `.where()` and o
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/offset_and_limit/tutorial004.py!}
|
{!./docs_src/tutorial/offset_and_limit/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run the Program with Limit, Offset, and Where on the Command Line
|
## Run the Program with Limit, Offset, and Where on the Command Line
|
||||||
|
|
||||||
|
@ -8,14 +8,13 @@ We'll create data for this same **many-to-many** relationship with a link table:
|
|||||||
|
|
||||||
We'll continue from where we left off with the previous code.
|
We'll continue from where we left off with the previous code.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Create Heroes
|
## Create Heroes
|
||||||
|
|
||||||
@ -29,14 +28,13 @@ As we have done before, we'll create a function `create_heroes()` and we'll crea
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This is very similar to what we have done before.
|
This is very similar to what we have done before.
|
||||||
|
|
||||||
@ -58,14 +56,13 @@ Now let's do as we have done before, `commit` the **session**, `refresh` the dat
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Add to Main
|
## Add to Main
|
||||||
|
|
||||||
@ -79,14 +76,13 @@ As before, add the `create_heroes()` function to the `main()` function to make s
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run the Program
|
## Run the Program
|
||||||
|
|
||||||
|
@ -18,14 +18,13 @@ We can create it just as any other **SQLModel**:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This is a **SQLModel** class model table like any other.
|
This is a **SQLModel** class model table like any other.
|
||||||
|
|
||||||
@ -47,14 +46,13 @@ Let's see the `Team` model, it's almost identical as before, but with a little c
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./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).
|
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).
|
||||||
|
|
||||||
@ -76,14 +74,13 @@ Let's see the other side, here's the `Hero` model:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./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. 🔥
|
We **removed** the previous `team_id` field (column) because now the relationship is done via the link table. 🔥
|
||||||
|
|
||||||
@ -109,14 +106,13 @@ The same as before, we will have the rest of the code to create the **engine**,
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./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:
|
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:
|
||||||
@ -130,14 +126,13 @@ And as in previous examples, we will add that function to a function `main()`, a
|
|||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:83-84]!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py[ln:83-84]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
|
|
||||||
## Run the Code
|
## Run the Code
|
||||||
|
@ -40,14 +40,13 @@ And we will also add two **relationship attributes**, for the linked `team` and
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
{!./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:
|
The new **relationship attributes** have their own `back_populates` pointing to new relationship attributes we will create in the `Hero` and `Team` models:
|
||||||
|
|
||||||
@ -76,14 +75,13 @@ We no longer have the `heroes` relationship attribute, and instead we have the n
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Update Hero Model
|
## Update Hero Model
|
||||||
|
|
||||||
@ -99,14 +97,13 @@ We change the `teams` relationship attribute for `team_links`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Create Relationships
|
## Create Relationships
|
||||||
|
|
||||||
@ -122,14 +119,13 @@ But now we create the **explicit link models** manually, pointing to their hero
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -235,14 +231,13 @@ Here we do that in the `update_heroes()` function:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run the Program with the New Relationship
|
## Run the Program with the New Relationship
|
||||||
|
|
||||||
@ -335,14 +330,13 @@ We can do that by iterating on the links:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Run the Program with the Updated Relationships
|
## Run the Program with the Updated Relationships
|
||||||
|
|
||||||
|
@ -4,14 +4,13 @@ Now we'll see how to update and remove these **many-to-many** relationships.
|
|||||||
|
|
||||||
We'll continue from where we left off with the previous code.
|
We'll continue from where we left off with the previous code.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Get Data to Update
|
## Get Data to Update
|
||||||
|
|
||||||
@ -33,14 +32,13 @@ And because we are now using `select()`, we also have to import it.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And of course, we have to add `update_heroes()` to our `main()` function:
|
And of course, we have to add `update_heroes()` to our `main()` function:
|
||||||
|
|
||||||
@ -50,14 +48,13 @@ And of course, we have to add `update_heroes()` to our `main()` function:
|
|||||||
{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:100-107]!}
|
{!./docs_src/tutorial/many_to_many/tutorial002.py[ln:100-107]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Add Many-to-Many Relationships
|
## Add Many-to-Many Relationships
|
||||||
|
|
||||||
@ -73,14 +70,13 @@ We can use the same **relationship attributes** to include `hero_spider_boy` in
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -173,14 +169,13 @@ In this case, we use the method `.remove()`, that takes an item and removes it f
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/many_to_many/tutorial002.py!}
|
{!./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`.
|
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`.
|
||||||
|
|
||||||
|
@ -14,14 +14,13 @@ Let's see the utilities to read a single row.
|
|||||||
|
|
||||||
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.
|
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>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -37,14 +36,13 @@ We have been iterating over the rows in a `result` object like:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
But let's say that we are not interested in all the rows, just the **first** one.
|
But let's say that we are not interested in all the rows, just the **first** one.
|
||||||
|
|
||||||
@ -58,14 +56,13 @@ We can call the `.first()` method on the `results` object to get the first row:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial001.py!}
|
{!./docs_src/tutorial/one/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This will return the first object in the `results` (if there was any).
|
This will return the first object in the `results` (if there was any).
|
||||||
|
|
||||||
@ -114,14 +111,13 @@ In that case, `.first()` will return `None`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial002.py!}
|
{!./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`.
|
In this case, as there's no hero with an age less than 25, `.first()` will return `None`.
|
||||||
|
|
||||||
@ -162,14 +158,13 @@ In that case, instead of `.first()` we can use `.one()`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial003.py!}
|
{!./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.
|
Here we know that there's only one `"Deadpond"`, and there shouldn't be any more than one.
|
||||||
|
|
||||||
@ -233,14 +228,13 @@ Of course, even if we don't duplicate the data, we could get the same error if w
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial004.py!}
|
{!./docs_src/tutorial/one/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That would find 2 rows, and would end up with the same error.
|
That would find 2 rows, and would end up with the same error.
|
||||||
|
|
||||||
@ -256,14 +250,13 @@ And also, if we get no rows at all with `.one()`, it will also raise an error:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial005.py!}
|
{!./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.
|
In this case, as there are no heroes with an age less than 25, `.one()` will raise an error.
|
||||||
|
|
||||||
@ -304,14 +297,13 @@ Of course, with `.first()` and `.one()` you would also probably write all that i
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial006.py!}
|
{!./docs_src/tutorial/one/tutorial006.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That would result in the same as some examples above.
|
That would result in the same as some examples above.
|
||||||
|
|
||||||
@ -329,14 +321,13 @@ You could do it the same way we have been doing with a `.where()` and then getti
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial007.py!}
|
{!./docs_src/tutorial/one/tutorial007.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That would work correctly, as expected. But there's a shorter version. 👇
|
That would work correctly, as expected. But there's a shorter version. 👇
|
||||||
|
|
||||||
@ -352,14 +343,13 @@ As selecting a single row by its Id column with the **primary key** is a common
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial008.py!}
|
{!./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()`.
|
`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()`.
|
||||||
|
|
||||||
@ -396,14 +386,13 @@ Hero: secret_name='Dive Wilson' age=None id=1 name='Deadpond'
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/one/tutorial009.py!}
|
{!./docs_src/tutorial/one/tutorial009.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Running that will output:
|
Running that will output:
|
||||||
|
|
||||||
|
@ -26,14 +26,13 @@ Let's see how that works by writing an **incomplete** version first, without `ba
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Read Data Objects
|
## Read Data Objects
|
||||||
|
|
||||||
@ -49,14 +48,13 @@ As you already know how this works, I won't separate that in a select `statement
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -76,14 +74,13 @@ Now, let's print the current **Spider-Boy**, the current **Preventers** team, an
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Up to this point, it's all good. 😊
|
Up to this point, it's all good. 😊
|
||||||
|
|
||||||
@ -117,14 +114,13 @@ Now let's update **Spider-Boy**, removing him from the team by setting `hero_spi
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
{!./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.
|
The first important thing is, we *haven't committed* the hero yet, so accessing the list of heroes would not trigger an automatic refresh.
|
||||||
|
|
||||||
@ -176,14 +172,13 @@ Now, if we commit it and print again:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial001.py!}
|
{!./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:
|
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:
|
||||||
|
|
||||||
@ -221,14 +216,13 @@ Let's add it back:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And we can keep the rest of the code the same:
|
And we can keep the rest of the code the same:
|
||||||
|
|
||||||
@ -244,14 +238,13 @@ And we can keep the rest of the code the same:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -290,14 +283,13 @@ It's quite simple code, it's just a string, but it might be confusing to think e
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
{!./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.
|
The string in `back_populates` is the name of the attribute *in the other* model, that will reference *the current* model.
|
||||||
|
|
||||||
@ -313,14 +305,13 @@ So, in the class `Team`, we have an attribute `heroes` and we declare it with `R
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
{!./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).
|
The string in `back_populates="team"` refers to the attribute `team` in the class `Hero` (the other class).
|
||||||
|
|
||||||
@ -336,14 +327,13 @@ So, the string `"heroes"` refers to the attribute `heroes` in the class `Team`.
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -376,11 +366,10 @@ So, `back_populates` would most probably be something like `"hero"` or `"heroes"
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py!}
|
{!./docs_src/tutorial/relationship_attributes/back_populates/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
@ -14,14 +14,13 @@ Let's check the old code we used to create some heroes and teams:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
There are several things to **notice** here.
|
There are several things to **notice** here.
|
||||||
|
|
||||||
@ -49,14 +48,13 @@ Now let's do all that, but this time using the new, shiny `Relationship` attribu
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
|
{!./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`.
|
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`.
|
||||||
|
|
||||||
@ -84,14 +82,13 @@ The same way we could assign an integer with a `team.id` to a `hero.team_id`, we
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Create a Team with Heroes
|
## Create a Team with Heroes
|
||||||
|
|
||||||
@ -111,14 +108,13 @@ We could also create the `Hero` instances first, and then pass them in the `hero
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
|
{!./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.
|
Here we create two heroes first, **Black Lion** and **Princess Sure-E**, and then we pass them in the `heroes` argument.
|
||||||
|
|
||||||
@ -146,14 +142,13 @@ Let's create some more heroes and add them to the `team_preventers.heroes` list
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/create_and_update_relationships/tutorial001.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
|
@ -47,14 +47,13 @@ Up to now, we have only used the `team_id` column to connect the tables when que
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
{!./docs_src/tutorial/connect/insert/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This is a **plain field** like all the others, all representing a **column in the table**.
|
This is a **plain field** like all the others, all representing a **column in the table**.
|
||||||
|
|
||||||
@ -68,14 +67,13 @@ First, import `Relationship` from `sqlmodel`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Next, use that `Relationship` to declare a new attribute in the model classes:
|
Next, use that `Relationship` to declare a new attribute in the model classes:
|
||||||
|
|
||||||
@ -85,14 +83,13 @@ Next, use that `Relationship` to declare a new attribute in the model classes:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## What Are These Relationship Attributes
|
## What Are These Relationship Attributes
|
||||||
|
|
||||||
|
@ -18,14 +18,13 @@ First, add a function `select_heroes()` where we get a hero to start working wit
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Select the Related Team - Old Way
|
## Select the Related Team - Old Way
|
||||||
|
|
||||||
@ -41,14 +40,13 @@ With what we have learned **up to now**, we could use a `select()` statement, th
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Get Relationship Team - New Way
|
## Get Relationship Team - New Way
|
||||||
|
|
||||||
@ -68,14 +66,13 @@ So, the highlighted block above, has the same results as the block below:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
|
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
@ -97,14 +94,13 @@ And the same way, when we are working on the **many** side of the **one-to-many*
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
|
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That would print a list with all the heroes in the Preventers team:
|
That would print a list with all the heroes in the Preventers team:
|
||||||
|
|
||||||
|
@ -16,14 +16,13 @@ We can remove the relationship by setting it to `None`, the same as with the `te
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
|
{!./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:
|
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:
|
||||||
|
|
||||||
@ -35,14 +34,13 @@ And of course, we should remember to add this `update_heroes()` function to `mai
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
|
{!./docs_src/tutorial/relationship_attributes/read_relationships/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Recap
|
## Recap
|
||||||
|
|
||||||
|
@ -8,14 +8,13 @@ In the first Relationship attribute, we declare it with `List["Hero"]`, putting
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}
|
{!./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]`?
|
What's that about? Can't we just write it normally as `List[Hero]`?
|
||||||
|
|
||||||
|
@ -23,14 +23,13 @@ Things are getting more exciting! Let's now see how to read data from the databa
|
|||||||
|
|
||||||
Let's continue from the last code we used to create some data.
|
Let's continue from the last code we used to create some data.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/insert/tutorial002.py!}
|
{!./docs_src/tutorial/insert/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We are creating a **SQLModel** `Hero` class model and creating some records.
|
We are creating a **SQLModel** `Hero` class model and creating some records.
|
||||||
|
|
||||||
@ -175,14 +174,13 @@ We will start with that in a new function `select_heroes()`:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./docs_src/tutorial/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Create a `select` Statement
|
## Create a `select` Statement
|
||||||
|
|
||||||
@ -196,14 +194,13 @@ First we have to import `select` from `sqlmodel` at the top of the file:
|
|||||||
# More code below omitted 👇
|
# More code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./docs_src/tutorial/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And then we will use it to create a `SELECT` statement in Python code:
|
And then we will use it to create a `SELECT` statement in Python code:
|
||||||
|
|
||||||
@ -217,14 +214,13 @@ And then we will use it to create a `SELECT` statement in Python code:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./docs_src/tutorial/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
It's a very simple line of code that conveys a lot of information:
|
It's a very simple line of code that conveys a lot of information:
|
||||||
|
|
||||||
@ -263,14 +259,13 @@ Now that we have the `select` statement, we can execute it with the **session**:
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -316,14 +311,13 @@ Now we can put it in a `for` loop and print each one of the heroes:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./docs_src/tutorial/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
This will print the output:
|
This will print the output:
|
||||||
|
|
||||||
@ -345,14 +339,13 @@ Now include a call to `select_heroes()` in the `main()` function so that it is e
|
|||||||
# More code here later 👇
|
# More code here later 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./docs_src/tutorial/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Review The Code
|
## Review The Code
|
||||||
|
|
||||||
@ -406,14 +399,13 @@ The special `results` object also has a method `results.all()` that returns a li
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial003.py!}
|
{!./docs_src/tutorial/select/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
With this now we have all the heroes in a list in the `heroes` variable.
|
With this now we have all the heroes in a list in the `heroes` variable.
|
||||||
|
|
||||||
@ -447,14 +439,13 @@ But knowing what is each object and what it is all doing, we can simplify it a b
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial004.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
|
@ -6,14 +6,13 @@ Now let's see how to update data using **SQLModel**.
|
|||||||
|
|
||||||
As before, we'll continue from where we left off with the previous code.
|
As before, we'll continue from where we left off with the previous code.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
{!./docs_src/tutorial/indexes/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Remember to remove the `database.db` file before running the examples to get the same results.
|
Remember to remove the `database.db` file before running the examples to get the same results.
|
||||||
|
|
||||||
@ -102,14 +101,13 @@ We'll start by selecting the hero `"Spider-Boy"`, this is the one we will update
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./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:
|
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:
|
||||||
|
|
||||||
@ -119,14 +117,13 @@ Let's not forget to add that `update_heroes()` function to the `main()` function
|
|||||||
{!./docs_src/tutorial/update/tutorial001.py[ln:58-65]!}
|
{!./docs_src/tutorial/update/tutorial001.py[ln:58-65]!}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./docs_src/tutorial/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Up to that point, running that in the command line will output:
|
Up to that point, running that in the command line will output:
|
||||||
|
|
||||||
@ -169,14 +166,13 @@ In this case, we will set the `age` to `16`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./docs_src/tutorial/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Add the Hero to the Session
|
## Add the Hero to the Session
|
||||||
|
|
||||||
@ -192,14 +188,13 @@ This is the same we did when creating new hero instances:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./docs_src/tutorial/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Commit the Session
|
## Commit the Session
|
||||||
|
|
||||||
@ -215,14 +210,13 @@ This will save the updated hero in the database:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./docs_src/tutorial/update/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
It will also save anything else that was added to the session.
|
It will also save anything else that was added to the session.
|
||||||
|
|
||||||
@ -263,14 +257,13 @@ But in this example we are not accessing any attribute, we will only print the o
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./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:
|
This refresh will trigger the same SQL query that would be automatically triggered by accessing an attribute. So it will generate this output:
|
||||||
|
|
||||||
@ -304,14 +297,13 @@ Now we can just print the hero:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial001.py!}
|
{!./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.
|
Because we refreshed it right after updating it, it has fresh data, including the new `age` we just updated.
|
||||||
|
|
||||||
@ -364,14 +356,13 @@ This also means that you can update several fields (attributes, columns) at once
|
|||||||
|
|
||||||
{!./docs_src/tutorial/update/annotations/en/tutorial004.md!}
|
{!./docs_src/tutorial/update/annotations/en/tutorial004.md!}
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/update/tutorial004.py!}
|
{!./docs_src/tutorial/update/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
/// tip
|
/// tip
|
||||||
|
|
||||||
|
@ -31,14 +31,13 @@ We'll continue with the same examples we have been using in the previous chapter
|
|||||||
|
|
||||||
And now we will update `select_heroes()` to filter the data.
|
And now we will update `select_heroes()` to filter the data.
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python hl_lines="36-41"
|
```Python hl_lines="36-41"
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./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.
|
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.
|
||||||
|
|
||||||
@ -198,14 +197,13 @@ We care specially about the **select** statement:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/select/tutorial001.py!}
|
{!./docs_src/tutorial/select/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
## Filter Rows Using `WHERE` with **SQLModel**
|
## Filter Rows Using `WHERE` with **SQLModel**
|
||||||
|
|
||||||
@ -219,14 +217,13 @@ Now, the same way that we add `WHERE` to a SQL statement to filter rows, we can
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial001.py!}
|
{!./docs_src/tutorial/where/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
It's a very small change, but it's packed of details. Let's explore them.
|
It's a very small change, but it's packed of details. Let's explore them.
|
||||||
|
|
||||||
@ -480,14 +477,13 @@ It's actually the same as in previous chapters for selecting data:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial001.py!}
|
{!./docs_src/tutorial/where/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
We take that statement, that now includes a `WHERE`, and we `exec()` it to get the results.
|
We take that statement, that now includes a `WHERE`, and we `exec()` it to get the results.
|
||||||
|
|
||||||
@ -544,14 +540,13 @@ We could get the rows where a column is **not** equal to a value using `!=`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial002.py!}
|
{!./docs_src/tutorial/where/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That would output:
|
That would output:
|
||||||
|
|
||||||
@ -572,14 +567,13 @@ Let's update the function `create_heroes()` and add some more rows to make the n
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial003.py!}
|
{!./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.
|
Now that we have several heroes with different ages, it's gonna be more obvious what the next comparisons do.
|
||||||
|
|
||||||
@ -595,14 +589,13 @@ Now let's use `>` to get the rows where a column is **more than** a value:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial003.py!}
|
{!./docs_src/tutorial/where/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
That would output:
|
That would output:
|
||||||
|
|
||||||
@ -630,14 +623,13 @@ Let's do that again, but with `>=` to get the rows where a column is **more than
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial004.py!}
|
{!./docs_src/tutorial/where/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
Because we are using `>=`, the age `35` will be included in the output:
|
Because we are using `>=`, the age `35` will be included in the output:
|
||||||
|
|
||||||
@ -666,14 +658,13 @@ Similarly, we can use `<` to get the rows where a column is **less than** a valu
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial005.py!}
|
{!./docs_src/tutorial/where/tutorial005.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And we get the younger one with an age in the database:
|
And we get the younger one with an age in the database:
|
||||||
|
|
||||||
@ -699,14 +690,13 @@ Finally, we can use `<=` to get the rows where a column is **less than or equal*
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial006.py!}
|
{!./docs_src/tutorial/where/tutorial006.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And we get the younger ones, `35` and below:
|
And we get the younger ones, `35` and below:
|
||||||
|
|
||||||
@ -739,14 +729,13 @@ Because `.where()` returns the same special select object back, we can add more
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial007.py!}
|
{!./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`.
|
This will select the rows `WHERE` the `age` is **greater than or equal** to `35`, `AND` also the `age` is **less than** `40`.
|
||||||
|
|
||||||
@ -795,14 +784,13 @@ As an alternative to using multiple `.where()` we can also pass several expressi
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial008.py!}
|
{!./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:
|
This is the same as the above, and will result in the same output with the two heroes:
|
||||||
|
|
||||||
@ -825,14 +813,13 @@ To do it, you can import `or_`:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial009.py!}
|
{!./docs_src/tutorial/where/tutorial009.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And then pass both expressions to `or_()` and put it inside `.where()`.
|
And then pass both expressions to `or_()` and put it inside `.where()`.
|
||||||
|
|
||||||
@ -846,14 +833,13 @@ For example, here we select the heroes that are the youngest OR the oldest:
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial009.py!}
|
{!./docs_src/tutorial/where/tutorial009.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
When we run it, this generates the output:
|
When we run it, this generates the output:
|
||||||
|
|
||||||
@ -910,14 +896,13 @@ To do that, we can import `col()` (as short for "column"):
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial011.py!}
|
{!./docs_src/tutorial/where/tutorial011.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
And then put the **class attribute** inside `col()` when using it in a `.where()`:
|
And then put the **class attribute** inside `col()` when using it in a `.where()`:
|
||||||
|
|
||||||
@ -929,14 +914,13 @@ And then put the **class attribute** inside `col()` when using it in a `.where()
|
|||||||
# Code below omitted 👇
|
# Code below omitted 👇
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
/// details | 👀 Full file preview
|
||||||
<summary>👀 Full file preview</summary>
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
{!./docs_src/tutorial/where/tutorial011.py!}
|
{!./docs_src/tutorial/where/tutorial011.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
///
|
||||||
|
|
||||||
So, now the comparison is not:
|
So, now the comparison is not:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user