Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add support for Pydantic v2 (while keeping support for v1 if v2 is not available), including initial work by AntonDeMeester #722

Merged
merged 109 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
d0ae3e8
migration to sqlalchemy 2.0
farahats9 Mar 7, 2023
8a27655
fix some linting errors
farahats9 Mar 24, 2023
a2b3c14
reflecting python 3.6 deprecation in docs and tests
farahats9 Mar 31, 2023
4760dbd
Update sqlmodel/sql/expression.py
farahats9 Mar 31, 2023
ad76a88
resolving @sbor23 comments
farahats9 Mar 31, 2023
96e44e5
add the new Subquery class
farahats9 Apr 30, 2023
9e72750
fix jinja2 template
farahats9 Apr 30, 2023
b19a709
`Result` expects a type `Tuple[_T]`
peterlandry Jul 26, 2023
ae369ed
Remove unused type ignore
peterlandry Jul 26, 2023
2ff42db
Result seems well enough typed in SqlAlchemy now we can simply shim over
peterlandry Jul 26, 2023
b6bd94f
_Select expects a `Tuple[Any, ...]`
peterlandry Jul 26, 2023
1dbce4d
Use Dict type instead of Mapping for SqlAlchemy compat
peterlandry Jul 26, 2023
c2d310e
Execution options are not Optional in SA
peterlandry Jul 26, 2023
05a1352
Another instance of non-optional execution_options
peterlandry Jul 26, 2023
bd00a2b
Fix Tuple in jinja template as well
peterlandry Jul 26, 2023
c65f018
Use ForUpdateArg from sqlalchemy
peterlandry Jul 26, 2023
4e29e00
Fix signature for `Session.get`
peterlandry Jul 26, 2023
fd85d02
formatting and remove unused type
farahats9 Jul 27, 2023
d556059
Upgrade to Pydantic 2
AntonDeMeester Jul 31, 2023
e92a52e
Formatting
AntonDeMeester Jul 31, 2023
61d5d8d
Linting
AntonDeMeester Jul 31, 2023
cb494b7
Make all tests but fastapi work
AntonDeMeester Aug 1, 2023
f590548
Get all tests except for openapi working
AntonDeMeester Aug 1, 2023
7ecbc38
Write for pydantic v1 and v2 compat
AntonDeMeester Nov 13, 2023
c21ff69
Make pydantic v1 work again
AntonDeMeester Nov 14, 2023
254fb13
Liniting
AntonDeMeester Nov 14, 2023
ab07514
Linter
AntonDeMeester Nov 14, 2023
4a4161a
Move lint to after tests to see tests
AntonDeMeester Nov 14, 2023
e2d4d1f
Make most tests succeed
AntonDeMeester Nov 16, 2023
725c6ac
🔀 Merge branch 'main' into pv2-b
tiangolo Nov 23, 2023
4c358b2
💡 Add TODO comments
tiangolo Nov 23, 2023
0029193
👷 Update CI from main
tiangolo Nov 23, 2023
8a13945
📝 Update index.md with Python versions
tiangolo Nov 23, 2023
bebd5d8
⏪️ Revert changing model order in examples to account for previous la…
tiangolo Nov 23, 2023
d229a87
⏪️ Revert example changing the order of models to account for the lac…
tiangolo Nov 23, 2023
29e372b
🔥 Remove import removed in __init__ from main
tiangolo Nov 23, 2023
665902c
⏪️ Revert renaming Undefined to PydanticUndefined, limit the changes …
tiangolo Nov 24, 2023
b5460f9
♻️ Refactor compat, rename PydanticUndefined to Undefined as before
tiangolo Nov 24, 2023
d9bafa3
🐛 Fix type of model.__fields__ in Pydantic v1 and add compatibility c…
tiangolo Nov 24, 2023
6e29b22
🐛 Use compat ModelField for type annotation in model.__fields__ for P…
tiangolo Nov 24, 2023
835cbc8
🐛 Fix removed Pydantic v1 field post init
tiangolo Nov 24, 2023
dbaef53
🚚 Move get_sqlalchemy_type and get_column_from_field back to main
tiangolo Nov 25, 2023
dcbc084
♻️ Refactor parameters for set_config_value
tiangolo Nov 25, 2023
c836ec1
♻️ Update calls for get_relationship_to with keyword args, remove don…
tiangolo Nov 25, 2023
3c6b7a9
♻️ Revert import renaming of BaseConfig, to reduce the diff
tiangolo Nov 25, 2023
c7390e1
✏️ Fix typos in warning texts
tiangolo Nov 25, 2023
3e45276
🔥 Remove unused imports
tiangolo Nov 25, 2023
eadf5bc
🔥 Remove unused utils
tiangolo Nov 25, 2023
d35989a
🚚 Move NoArgAnyCallable type to main
tiangolo Nov 25, 2023
ef8bbc6
♻️ Refactor signature of get_config_value, require all keyword arguments
tiangolo Nov 25, 2023
9ba2e59
🔥 Remove unused import
tiangolo Nov 25, 2023
63a55a8
🔥 Remove unused type
tiangolo Nov 25, 2023
f754390
⏪️ Revert removing class_dict_is_table until it's clear if it's neede…
tiangolo Nov 25, 2023
4a3fea8
💡 Add comments for next tasks
tiangolo Nov 25, 2023
b763668
♻️ Refactor imports in main
tiangolo Nov 25, 2023
fb11285
♻️ Tweak names and imports
tiangolo Nov 25, 2023
aeabcf2
♻️ Refactor get_relationship_to to support more than one level of typ…
tiangolo Nov 25, 2023
d6de622
🐛 Fix recursion for forward refs
tiangolo Nov 25, 2023
1ee0482
🔀 Merge branch 'main' into pv2-c
tiangolo Nov 29, 2023
cb02fb2
🐛 Fix detection of unions, detected by new Python 3.10 tests
tiangolo Nov 29, 2023
0460f05
🔥 Remove unnecessary checks and overrides for class defaults
tiangolo Nov 29, 2023
0187c36
♻️ Refactor compat to run all conditionals at import time and not at …
tiangolo Nov 29, 2023
9249021
🚚 Rename compat.py to _compat.py
tiangolo Nov 29, 2023
d400fd7
🐛 Fix handling of Nonable unions
tiangolo Nov 30, 2023
9bb29aa
✅ Simplify test that shoudln't require Pydantic v1 or v2
tiangolo Nov 30, 2023
edb051e
⬆️ Set minimum Pydantic version to 1.10.13
tiangolo Nov 30, 2023
65d6b3e
🚚 Rename compat to _compat
tiangolo Dec 3, 2023
f879c77
🚚 Rename test
tiangolo Dec 3, 2023
baf8f47
✅ Refactor and update test
tiangolo Dec 3, 2023
8c603f1
✅ Update tests, revert broken JSON Schema as a workaround for new mod…
tiangolo Dec 3, 2023
9f388f1
➕ Add dirty_equals to testing dependencies
tiangolo Dec 3, 2023
8d763da
✅ Update tests with compatibility for Pydantic v2 JSON Schema changes
tiangolo Dec 3, 2023
553a3c5
✅ Update additional tests for compatibility with Pydantic v2
tiangolo Dec 3, 2023
f0d088c
♻️ Refactor main and compat, restructure, simplify, and fix implement…
tiangolo Dec 3, 2023
2806b38
♻️ Re-export Representation from _compat
tiangolo Dec 3, 2023
08bd1ef
♻️ Refactor imports
tiangolo Dec 3, 2023
e07ada1
🚚 Update and rename symbols
tiangolo Dec 3, 2023
349a374
📝 Update docs, use Model.model_validate everywhere
tiangolo Dec 3, 2023
577ebb9
♻️ Refactor and simplify main.py
tiangolo Dec 3, 2023
f39bd8f
♻️ Reimplement _calculate_keys in _compat.py
tiangolo Dec 3, 2023
4c38fb0
🗑️ Add deprecation markers for methods
tiangolo Dec 3, 2023
5eb99a3
📝 Update reference to from_orm() in docs
tiangolo Dec 3, 2023
b7f27aa
♻️ Refactor source examples to use model_validate instead of from_orm
tiangolo Dec 3, 2023
224e4ef
🔀 Merge branch 'main' into pv2-c
tiangolo Dec 3, 2023
3070a1e
📝 Add note about from_orm to the docs
tiangolo Dec 3, 2023
8ac7804
✅ Tweak unreachable code coverage
tiangolo Dec 3, 2023
ad5eb08
♻️ Simplify logic for is_table_model_class
tiangolo Dec 3, 2023
0e74c50
✅ Add tests for deprecations
tiangolo Dec 3, 2023
cac622a
🐛 Fix implementation of sqlmodel_validate for Pydantic v1 with deprec…
tiangolo Dec 3, 2023
9d883f5
✅ Tweak coverage for unreachable tests
tiangolo Dec 3, 2023
f28109f
🔀 Merge branch 'main' into pv2-c
tiangolo Dec 4, 2023
cac349c
♻️ Update references to version 0.0.13 as latest
tiangolo Dec 4, 2023
8d5e62b
🎨 Fix type annotations
tiangolo Dec 4, 2023
d03c233
✨ Add method model_dump for compatibility with Pydantic v1 while keep…
tiangolo Dec 4, 2023
be49ad5
✨ Add override for .dict() only to deprecate it and help people migra…
tiangolo Dec 4, 2023
10e4356
📝 Update docs to use new method obj.model_dump() instead of obj.dict()
tiangolo Dec 4, 2023
30dbd40
✅ Update tests
tiangolo Dec 4, 2023
47d473d
✅ Add tests for deprecated obj.dict()
tiangolo Dec 4, 2023
fca1101
🐛 Fix recursion in Pydantic v1
tiangolo Dec 4, 2023
f1ab6a6
👷 Run lints only on Pydantic v2
tiangolo Dec 4, 2023
f68e93e
🎨 Fix type annotations for Python 3.7
tiangolo Dec 4, 2023
3b2f955
⬇️ Downgrade dirty-equals for compatibility with Python 3.7
tiangolo Dec 4, 2023
5f4d502
✅ Update tests to check for deprecation
tiangolo Dec 4, 2023
b995766
🎨 Fix type annotation for Python 3.7
tiangolo Dec 4, 2023
b3fcaf0
🎨 Fix type annotations in _compat
tiangolo Dec 4, 2023
7ab2fdc
🎨 Fix type annotations for Python 3.7 in _compat
tiangolo Dec 4, 2023
43fba36
📌 Fix pin for Pydantic v1
tiangolo Dec 4, 2023
115d439
🎨 Fix type ignores after fixing type annotations
tiangolo Dec 4, 2023
f121b00
🎨 Fix more type annotations
tiangolo Dec 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
- "3.10"
- "3.11"
- "3.12"
pydantic-version:
- pydantic-v1
- pydantic-v2
fail-fast: false

steps:
Expand Down Expand Up @@ -57,9 +60,15 @@ jobs:
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: python -m poetry install
- name: Install Pydantic v1
if: matrix.pydantic-version == 'pydantic-v1'
run: pip install "pydantic>=1.10.0,<2.0.0"
- name: Install Pydantic v2
if: matrix.pydantic-version == 'pydantic-v2'
run: pip install "pydantic>=2.0.2,<3.0.0"
- name: Lint
# Do not run on Python 3.7 as mypy behaves differently
if: matrix.python-version != '3.7'
if: matrix.python-version != '3.7' && matrix.pydantic-version == 'pydantic-v2'
run: python -m poetry run bash scripts/lint.sh
- run: mkdir coverage
- name: Test
Expand Down
12 changes: 7 additions & 5 deletions docs/tutorial/fastapi/multiple-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,17 @@ Now we use the type annotation `HeroCreate` for the request JSON data in the `he
# Code below omitted 👇
```

Then we create a new `Hero` (this is the actual **table** model that saves things to the database) using `Hero.from_orm()`.
Then we create a new `Hero` (this is the actual **table** model that saves things to the database) using `Hero.model_validate()`.

The method `.from_orm()` reads data from another object with attributes and creates a new instance of this class, in this case `Hero`.
The method `.model_validate()` reads data from another object with attributes (or a dict) and creates a new instance of this class, in this case `Hero`.

The alternative is `Hero.parse_obj()` that reads data from a dictionary.
In this case, we have a `HeroCreate` instance in the `hero` variable. This is an object with attributes, so we use `.model_validate()` to read those attributes.

But as in this case, we have a `HeroCreate` instance in the `hero` variable. This is an object with attributes, so we use `.from_orm()` to read those attributes.
/// tip
In versions of **SQLModel** before `0.0.14` you would use the method `.from_orm()`, but it is now deprecated and you should use `.model_validate()` instead.
///

With this, we create a new `Hero` instance (the one for the database) and put it in the variable `db_hero` from the data in the `hero` variable that is the `HeroCreate` instance we received from the request.
We can now create a new `Hero` instance (the one for the database) and put it in the variable `db_hero` from the data in the `hero` variable that is the `HeroCreate` instance we received from the request.

```Python hl_lines="3"
# Code above omitted 👆
Expand Down
15 changes: 9 additions & 6 deletions docs/tutorial/fastapi/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ So, we need to read the hero from the database, with the **same logic** we used

The `HeroUpdate` model has all the fields with **default values**, because they all have defaults, they are all optional, which is what we want.

But that also means that if we just call `hero.dict()` we will get a dictionary that could potentially have several or all of those values with their defaults, for example:
But that also means that if we just call `hero.model_dump()` we will get a dictionary that could potentially have several or all of those values with their defaults, for example:

```Python
{
Expand All @@ -102,7 +102,7 @@ But that also means that if we just call `hero.dict()` we will get a dictionary

And then, if we update the hero in the database with this data, we would be removing any existing values, and that's probably **not what the client intended**.

But fortunately Pydantic models (and so SQLModel models) have a parameter we can pass to the `.dict()` method for that: `exclude_unset=True`.
But fortunately Pydantic models (and so SQLModel models) have a parameter we can pass to the `.model_dump()` method for that: `exclude_unset=True`.

This tells Pydantic to **not include** the values that were **not sent** by the client. Saying it another way, it would **only** include the values that were **sent by the client**.

Expand All @@ -112,7 +112,7 @@ So, if the client sent a JSON with no values:
{}
```

Then the dictionary we would get in Python using `hero.dict(exclude_unset=True)` would be:
Then the dictionary we would get in Python using `hero.model_dump(exclude_unset=True)` would be:

```Python
{}
Expand All @@ -126,7 +126,7 @@ But if the client sent a JSON with:
}
```

Then the dictionary we would get in Python using `hero.dict(exclude_unset=True)` would be:
Then the dictionary we would get in Python using `hero.model_dump(exclude_unset=True)` would be:

```Python
{
Expand All @@ -152,6 +152,9 @@ Then we use that to get the data that was actually sent by the client:

///

/// tip
Before SQLModel 0.0.14, the method was called `hero.dict(exclude_unset=True)`, but it was renamed to `hero.model_dump(exclude_unset=True)` to be consistent with Pydantic v2.

## Update the Hero in the Database

Now that we have a **dictionary with the data sent by the client**, we can iterate for each one of the keys and the values, and then we set them in the database hero model `db_hero` using `setattr()`.
Expand Down Expand Up @@ -208,7 +211,7 @@ So, if the client wanted to intentionally remove the `age` of a hero, they could
}
```

And when getting the data with `hero.dict(exclude_unset=True)`, we would get:
And when getting the data with `hero.model_dump(exclude_unset=True)`, we would get:

```Python
{
Expand All @@ -226,4 +229,4 @@ These are some of the advantages of Pydantic, that we can use with SQLModel.

## Recap

Using `.dict(exclude_unset=True)` in SQLModel models (and Pydantic models) we can easily update data **correctly**, even in the **edge cases**. 😎
Using `.model_dump(exclude_unset=True)` in SQLModel models (and Pydantic models) we can easily update data **correctly**, even in the **edge cases**. 😎
2 changes: 1 addition & 1 deletion docs/tutorial/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ There's a chance that you have multiple Python versions installed.

You might want to try with the specific versions, for example with:

* `python3.11`
* `python3.12`
* `python3.11`
* `python3.10`
* `python3.9`

Expand Down
4 changes: 2 additions & 2 deletions docs_src/tutorial/fastapi/app_testing/tutorial001/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def on_startup():

@app.post("/heroes/", response_model=HeroRead)
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -87,7 +87,7 @@ def update_hero(
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def on_startup():

@app.post("/heroes/", response_model=HeroRead)
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -85,7 +85,7 @@ def update_hero(
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def on_startup():

@app.post("/heroes/", response_model=HeroRead)
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -87,7 +87,7 @@ def update_hero(
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand Down
4 changes: 2 additions & 2 deletions docs_src/tutorial/fastapi/delete/tutorial001.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -79,7 +79,7 @@ def update_hero(hero_id: int, hero: HeroUpdate):
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand Down
4 changes: 2 additions & 2 deletions docs_src/tutorial/fastapi/delete/tutorial001_py310.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -77,7 +77,7 @@ def update_hero(hero_id: int, hero: HeroUpdate):
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand Down
4 changes: 2 additions & 2 deletions docs_src/tutorial/fastapi/delete/tutorial001_py39.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -79,7 +79,7 @@ def update_hero(hero_id: int, hero: HeroUpdate):
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand Down
2 changes: 1 addition & 1 deletion docs_src/tutorial/fastapi/limit_and_offset/tutorial001.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
2 changes: 1 addition & 1 deletion docs_src/tutorial/fastapi/multiple_models/tutorial001.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
2 changes: 1 addition & 1 deletion docs_src/tutorial/fastapi/multiple_models/tutorial002.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
2 changes: 1 addition & 1 deletion docs_src/tutorial/fastapi/read_one/tutorial001.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
2 changes: 1 addition & 1 deletion docs_src/tutorial/fastapi/read_one/tutorial001_py310.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
2 changes: 1 addition & 1 deletion docs_src/tutorial/fastapi/read_one/tutorial001_py39.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def on_startup():
@app.post("/heroes/", response_model=HeroRead)
def create_hero(hero: HeroCreate):
with Session(engine) as session:
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down
8 changes: 4 additions & 4 deletions docs_src/tutorial/fastapi/relationships/tutorial001.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def on_startup():

@app.post("/heroes/", response_model=HeroRead)
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
db_hero = Hero.from_orm(hero)
db_hero = Hero.model_validate(hero)
session.add(db_hero)
session.commit()
session.refresh(db_hero)
Expand Down Expand Up @@ -125,7 +125,7 @@ def update_hero(
db_hero = session.get(Hero, hero_id)
if not db_hero:
raise HTTPException(status_code=404, detail="Hero not found")
hero_data = hero.dict(exclude_unset=True)
hero_data = hero.model_dump(exclude_unset=True)
for key, value in hero_data.items():
setattr(db_hero, key, value)
session.add(db_hero)
Expand All @@ -146,7 +146,7 @@ def delete_hero(*, session: Session = Depends(get_session), hero_id: int):

@app.post("/teams/", response_model=TeamRead)
def create_team(*, session: Session = Depends(get_session), team: TeamCreate):
db_team = Team.from_orm(team)
db_team = Team.model_validate(team)
session.add(db_team)
session.commit()
session.refresh(db_team)
Expand Down Expand Up @@ -182,7 +182,7 @@ def update_team(
db_team = session.get(Team, team_id)
if not db_team:
raise HTTPException(status_code=404, detail="Team not found")
team_data = team.dict(exclude_unset=True)
team_data = team.model_dump(exclude_unset=True)
for key, value in team_data.items():
setattr(db_team, key, value)
session.add(db_team)
Expand Down
Loading