Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
8218979242
⬆ Bump pillow from 10.3.0 to 11.0.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.3.0 to 11.0.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.3.0...11.0.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-15 22:50:40 +00:00
7 changed files with 542 additions and 32 deletions

View File

@ -80,7 +80,45 @@ We don't call `uuid.uuid4()` ourselves in the code (we don't put the parenthesis
This means that the UUID will be generated in the Python code, **before sending the data to the database**.
{* ./docs_src/advanced/uuid/tutorial001_py310.py ln[1:10] hl[1,7] *}
//// tab | Python 3.10+
```Python hl_lines="1 7"
{!./docs_src/advanced/uuid/tutorial001_py310.py[ln:1-10]!}
# Code below omitted 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="1 8"
{!./docs_src/advanced/uuid/tutorial001.py[ln:1-11]!}
# Code below omitted 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/advanced/uuid/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/advanced/uuid/tutorial001.py!}
```
////
///
Pydantic has support for <a href="https://docs.pydantic.dev/latest/api/standard_library_types/#uuid" class="external-link" target="_blank">`UUID` types</a>.
@ -94,7 +132,49 @@ As `uuid.uuid4` will be called when creating the model instance, even before sen
And that **same ID (a UUID)** will be saved in the database.
{* ./docs_src/advanced/uuid/tutorial001_py310.py ln[23:34] hl[25,27,29,34] *}
//// tab | Python 3.10+
```Python hl_lines="5 7 9 14"
# Code above omitted 👆
{!./docs_src/advanced/uuid/tutorial001_py310.py[ln:23-34]!}
# Code below omitted 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="5 7 9 14"
# Code above omitted 👆
{!./docs_src/advanced/uuid/tutorial001.py[ln:24-35]!}
# Code below omitted 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/advanced/uuid/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/advanced/uuid/tutorial001.py!}
```
////
///
### Select a Hero
@ -102,7 +182,49 @@ We can do the same operations we could do with other fields.
For example we can **select a hero by ID**:
{* ./docs_src/advanced/uuid/tutorial001_py310.py ln[37:54] hl[49] *}
//// tab | Python 3.10+
```Python hl_lines="15"
# Code above omitted 👆
{!./docs_src/advanced/uuid/tutorial001_py310.py[ln:37-54]!}
# Code below omitted 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="15"
# Code above omitted 👆
{!./docs_src/advanced/uuid/tutorial001.py[ln:38-55]!}
# Code below omitted 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/advanced/uuid/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/advanced/uuid/tutorial001.py!}
```
////
///
/// tip
@ -116,7 +238,49 @@ SQLModel (actually SQLAlchemy) will take care of making it work. ✨
We could also select by ID with `session.get()`:
{* ./docs_src/advanced/uuid/tutorial002_py310.py ln[37:53] hl[49] *}
//// tab | Python 3.10+
```Python hl_lines="15"
# Code above omitted 👆
{!./docs_src/advanced/uuid/tutorial002_py310.py[ln:37-54]!}
# Code below omitted 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="15"
# Code above omitted 👆
{!./docs_src/advanced/uuid/tutorial002.py[ln:38-55]!}
# Code below omitted 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/advanced/uuid/tutorial002_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/advanced/uuid/tutorial002.py!}
```
////
///
The same way as with other fields, we could update, delete, etc. 🚀

View File

@ -68,7 +68,7 @@ There are many databases of many types.
A database could be a single file called `heroes.db`, managed with code in a very efficient way. An example would be SQLite, more about that on a bit.
![database as a single file](img/databases/single-file.svg)
![database as a single file](/img/databases/single-file.svg)
### A server database
@ -80,11 +80,11 @@ In this case, your code would talk to this server application instead of reading
The database could be located in a different server/machine:
![database in an external server](img/databases/external-server.svg)
![database in an external server](/img/databases/external-server.svg)
Or the database could be located in the same server/machine:
![database in the same server](img/databases/same-server.svg)
![database in the same server](/img/databases/same-server.svg)
The most important aspect of these types of databases is that **your code doesn't read or modify** the files containing the data directly.
@ -98,7 +98,7 @@ In some cases, the database could even be a group of server applications running
In this case, your code would talk to one or more of these server applications running on different machines.
![distributed database in multiple servers](img/databases/multiple-servers.svg)
![distributed database in multiple servers](/img/databases/multiple-servers.svg)
Most of the databases that work as server applications also support multiple servers in one way or another.
@ -257,7 +257,7 @@ For example, the table for the teams has the ID `1` for the team `Preventers` an
As these **primary key** IDs can uniquely identify each row on the table for teams, we can now go to the table for heroes and refer to those IDs in the table for teams.
![table relationships](img/databases/relationships.svg)
<img alt="table relationships" src="/img/databases/relationships.svg">
So, in the table for heroes, we use the `team_id` column to define a relationship to the *foreign* table for teams. Each value in the `team_id` column on the table with heroes will be the same value as the `id` column of one row in the table with teams.

View File

@ -236,7 +236,8 @@ database.execute(
).all()
```
![](img/db-to-code/autocompletion01.png){class="shadow"}
<img class="shadow" src="/img/db-to-code/autocompletion01.png">
## ORMs and SQL
@ -279,7 +280,7 @@ For example this **Relation** or table:
* **Mapper**: this comes from Math, when there's something that can convert from some set of things to another, that's called a "**mapping function**". That's where the **Mapper** comes from.
![Squares to Triangles Mapper](img/db-to-code/mapper.svg)
![Squares to Triangles Mapper](/img/db-to-code/mapper.svg)
We could also write a **mapping function** in Python that converts from the *set of lowercase letters* to the *set of uppercase letters*, like this:

View File

@ -16,11 +16,11 @@ As **SQLModel** is built on top of <a href="https://www.sqlalchemy.org/" class="
## Install DB Browser for SQLite
Remember that [SQLite is a simple database in a single file](databases.md#a-single-file-database){.internal-link target=_blank}?
Remember that [SQLite is a simple database in a single file](../databases.md#a-single-file-database){.internal-link target=_blank}?
For most of the tutorial I'll use SQLite for the examples.
Python has integrated support for SQLite, it is a single file read and processed from Python. And it doesn't need an [External Database Server](databases.md#a-server-database){.internal-link target=_blank}, so it will be perfect for learning.
Python has integrated support for SQLite, it is a single file read and processed from Python. And it doesn't need an [External Database Server](../databases.md#a-server-database){.internal-link target=_blank}, so it will be perfect for learning.
In fact, SQLite is perfectly capable of handling quite big applications. At some point you might want to migrate to a server-based database like <a href="https://www.postgresql.org/" class="external-link" target="_blank">PostgreSQL</a> (which is also free). But for now we'll stick to SQLite.

View File

@ -8,16 +8,11 @@
### Docs
* ✏️ Fix typo in the release notes of v0.0.22. PR [#1195](https://github.com/fastapi/sqlmodel/pull/1195) by [@PipeKnight](https://github.com/PipeKnight).
* 📝 Update includes for `docs/advanced/uuid.md`. PR [#1151](https://github.com/fastapi/sqlmodel/pull/1151) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update includes for `docs/tutorial/create-db-and-table.md`. PR [#1149](https://github.com/fastapi/sqlmodel/pull/1149) by [@tiangolo](https://github.com/tiangolo).
* 📝 Fix internal links in docs. PR [#1148](https://github.com/fastapi/sqlmodel/pull/1148) by [@tiangolo](https://github.com/tiangolo).
* ✏️ Fix typo in documentation. PR [#1106](https://github.com/fastapi/sqlmodel/pull/1106) by [@Solipsistmonkey](https://github.com/Solipsistmonkey).
* 📝 Remove highlights in `indexes.md` . PR [#1100](https://github.com/fastapi/sqlmodel/pull/1100) by [@alejsdev](https://github.com/alejsdev).
### Internal
* ⬆️ Upgrade markdown-include-variants to version 0.0.3. PR [#1152](https://github.com/fastapi/sqlmodel/pull/1152) by [@tiangolo](https://github.com/tiangolo).
* 👷 Update issue manager workflow. PR [#1137](https://github.com/fastapi/sqlmodel/pull/1137) by [@alejsdev](https://github.com/alejsdev).
* 👷 Fix smokeshow, checkout files on CI. PR [#1136](https://github.com/fastapi/sqlmodel/pull/1136) by [@tiangolo](https://github.com/tiangolo).
* 👷 Use uv in CI. PR [#1135](https://github.com/fastapi/sqlmodel/pull/1135) by [@tiangolo](https://github.com/tiangolo).
@ -37,7 +32,7 @@
### Fixes
* 🐛 Fix support for types with `Optional[Annotated[x, f()]]`, e.g. `id: Optional[pydantic.UUID4]`. PR [#1093](https://github.com/fastapi/sqlmodel/pull/1093) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix support for types with `Optional[Annoated[x, f()]]`, e.g. `id: Optional[pydantic.UUID4]`. PR [#1093](https://github.com/fastapi/sqlmodel/pull/1093) by [@tiangolo](https://github.com/tiangolo).
### Docs

View File

@ -41,7 +41,45 @@ That's why this package is called `SQLModel`. Because it's mainly used to create
For that, we will import `SQLModel` (plus other things we will also use) and create a class `Hero` that inherits from `SQLModel` and represents the **table model** for our heroes:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:8] hl[1,4] *}
//// tab | Python 3.10+
```Python hl_lines="1 4"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-8]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="3 6"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-10]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
This class `Hero` **represents the table** for our heroes. And each instance we create later will **represent a row** in the table.
@ -63,7 +101,45 @@ The name of each of these variables will be the name of the column in the table.
And the type of each of them will also be the type of table column:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:8] hl[1,5:8] *}
//// tab | Python 3.10+
```Python hl_lines="1 5-8"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-8]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="1 3 7-10"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-10]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
Let's now see with more detail these field/column declarations.
@ -77,7 +153,45 @@ That is the standard way to declare that something "could be an `int` or `None`"
And we also set the default value of `age` to `None`.
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:8] hl[8] *}
//// tab | Python 3.10+
```Python hl_lines="8"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-8]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="1 10"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-10]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
/// tip
@ -107,7 +221,45 @@ So, we need to mark `id` as the **primary key**.
To do that, we use the special `Field` function from `sqlmodel` and set the argument `primary_key=True`:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:8] hl[1,5] *}
//// tab | Python 3.10+
```Python hl_lines="1 5"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-8]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="3 7"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-10]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
That way, we tell **SQLModel** that this `id` field/column is the primary key of the table.
@ -150,7 +302,45 @@ If you have a server database (for example PostgreSQL or MySQL), the **engine**
Creating the **engine** is very simple, just call `create_engine()` with a URL for the database to use:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:16] hl[1,14] *}
//// tab | Python 3.10+
```Python hl_lines="1 14"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-16]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="3 16"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-18]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
You should normally have a single **engine** object for your whole application and re-use it everywhere.
@ -174,7 +364,45 @@ SQLite supports a special database that lives all *in memory*. Hence, it's very
* `sqlite://`
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:16] hl[11:12,14] *}
//// tab | Python 3.10+
```Python hl_lines="11-12 14"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-16]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="13-14 16"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-18]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
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>.
@ -186,7 +414,45 @@ It will make the engine print all the SQL statements it executes, which can help
It is particularly useful for **learning** and **debugging**:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:16] hl[14] *}
//// tab | Python 3.10+
```Python hl_lines="14"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py[ln:1-16]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="16"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py[ln:1-18]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
But in production, you would probably want to remove `echo=True`:
@ -212,7 +478,21 @@ And SQLModel's version of `create_engine()` is type annotated internally, so you
Now everything is in place to finally create the database and table:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py hl[16] *}
//// tab | Python 3.10+
```Python hl_lines="16"
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python hl_lines="18"
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
/// tip
@ -323,7 +603,25 @@ Let's run the program to see it all working.
Put the code it in a file `app.py` if you haven't already.
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py *}
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial001.py!}
```
////
///
/// tip
@ -428,7 +726,45 @@ In this example it's just the `SQLModel.metadata.create_all(engine)`.
Let's put it in a function `create_db_and_tables()`:
{* ./docs_src/tutorial/create_db_and_table/tutorial002_py310.py ln[1:18] hl[17:18] *}
//// tab | Python 3.10+
```Python hl_lines="17-18"
{!./docs_src/tutorial/create_db_and_table/tutorial002_py310.py[ln:1-18]!}
# More code here later 👇
```
////
//// tab | Python 3.7+
```Python hl_lines="19-20"
{!./docs_src/tutorial/create_db_and_table/tutorial002.py[ln:1-20]!}
# More code here later 👇
```
////
/// details | 👀 Full file preview
//// tab | Python 3.10+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial002_py310.py!}
```
////
//// tab | Python 3.7+
```Python
{!./docs_src/tutorial/create_db_and_table/tutorial002.py!}
```
////
///
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.
@ -458,7 +794,21 @@ The word **script** often implies that the code could be run independently and e
For that we can use the special variable `__name__` in an `if` block:
{* ./docs_src/tutorial/create_db_and_table/tutorial002_py310.py hl[21:22] *}
//// tab | Python 3.10+
```Python hl_lines="21-22"
{!./docs_src/tutorial/create_db_and_table/tutorial002_py310.py!}
```
////
//// tab | Python 3.7+
```Python hl_lines="23-24"
{!./docs_src/tutorial/create_db_and_table/tutorial002.py!}
```
////
### About `__name__ == "__main__"`

View File

@ -7,7 +7,7 @@ pyyaml >=5.3.1,<7.0.0
# For Material for MkDocs, Chinese search
# jieba==0.42.1
# For image processing by Material for MkDocs
pillow==10.3.0
pillow==11.0.0
# For image processing by Material for MkDocs
cairosvg==2.7.1
# mkdocstrings[python]==0.25.1
@ -16,4 +16,4 @@ cairosvg==2.7.1
# For griffe, it formats with black
typer == 0.12.3
mkdocs-macros-plugin==1.0.5
markdown-include-variants==0.0.3
markdown-include-variants==0.0.1