Skip to content

Commit 1eb40b1

Browse files
estebanx64tiangolo
andauthored
📝 Update ModelRead to ModelPublic documentation and examples (fastapi#885)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
1 parent fa79856 commit 1eb40b1

File tree

68 files changed

+427
-427
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+427
-427
lines changed
Loading

docs/tutorial/fastapi/multiple-models.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ But we also want to have a `HeroCreate` for the data we want to receive when **c
9898
* `secret_name`, required
9999
* `age`, optional
100100

101-
And we want to have a `HeroRead` with the `id` field, but this time annotated with `id: int`, instead of `id: Optional[int]`, to make it clear that it is required in responses **read** from the clients:
101+
And we want to have a `HeroPublic` with the `id` field, but this time annotated with `id: int`, instead of `id: Optional[int]`, to make it clear that it is required in responses **read** from the clients:
102102

103103
* `id`, required
104104
* `name`, required
@@ -183,9 +183,9 @@ Here's the important detail, and probably the most important feature of **SQLMod
183183

184184
This means that the class `Hero` represents a **table** in the database. It is both a **Pydantic** model and a **SQLAlchemy** model.
185185

186-
But `HeroCreate` and `HeroRead` don't have `table = True`. They are only **data models**, they are only **Pydantic** models. They won't be used with the database, but only to declare data schemas for the API (or for other uses).
186+
But `HeroCreate` and `HeroPublic` don't have `table = True`. They are only **data models**, they are only **Pydantic** models. They won't be used with the database, but only to declare data schemas for the API (or for other uses).
187187

188-
This also means that `SQLModel.metadata.create_all()` won't create tables in the database for `HeroCreate` and `HeroRead`, because they don't have `table = True`, which is exactly what we want. 🚀
188+
This also means that `SQLModel.metadata.create_all()` won't create tables in the database for `HeroCreate` and `HeroPublic`, because they don't have `table = True`, which is exactly what we want. 🚀
189189

190190
/// tip
191191

@@ -355,7 +355,7 @@ Then we just `add` it to the **session**, `commit`, and `refresh` it, and finall
355355

356356
Because it is just refreshed, it has the `id` field set with a new ID taken from the database.
357357

358-
And now that we return it, FastAPI will validate the data with the `response_model`, which is a `HeroRead`:
358+
And now that we return it, FastAPI will validate the data with the `response_model`, which is a `HeroPublic`:
359359

360360
//// tab | Python 3.10+
361361

@@ -743,9 +743,9 @@ As an alternative, we could use `HeroBase` directly in the API code instead of `
743743

744744
On top of that, we could easily decide in the future that we want to receive **more data** when creating a new hero apart from the data in `HeroBase` (for example, a password), and now we already have the class to put those extra fields.
745745

746-
### The `HeroRead` **Data Model**
746+
### The `HeroPublic` **Data Model**
747747

748-
Now let's check the `HeroRead` model.
748+
Now let's check the `HeroPublic` model.
749749

750750
This one just declares that the `id` field is required when reading a hero from the API, because a hero read from the API will come from the database, and in the database it will always have an ID.
751751

@@ -815,7 +815,7 @@ This one just declares that the `id` field is required when reading a hero from
815815

816816
## Review the Updated Docs UI
817817

818-
The FastAPI code is still the same as above, we still use `Hero`, `HeroCreate`, and `HeroRead`. But now, we define them in a smarter way with inheritance.
818+
The FastAPI code is still the same as above, we still use `Hero`, `HeroCreate`, and `HeroPublic`. But now, we define them in a smarter way with inheritance.
819819

820820
So, we can jump to the docs UI right away and see how they look with the updated data.
821821

docs/tutorial/fastapi/read-one.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ This will let the client know that they probably made a mistake on their side an
164164

165165
Then, if the hero exists, we return it.
166166

167-
And because we are using the `response_model` with `HeroRead`, it will be validated, documented, etc.
167+
And because we are using the `response_model` with `HeroPublic`, it will be validated, documented, etc.
168168

169169
//// tab | Python 3.10+
170170

docs/tutorial/fastapi/relationships.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ Let's update that. 🤓
4040

4141
First, why is it that we are not getting the related data for each hero and for each team?
4242

43-
It's because we declared the `HeroRead` with only the same base fields of the `HeroBase` plus the `id`. But it doesn't include a field `team` for the **relationship attribute**.
43+
It's because we declared the `HeroPublic` with only the same base fields of the `HeroBase` plus the `id`. But it doesn't include a field `team` for the **relationship attribute**.
4444

45-
And the same way, we declared the `TeamRead` with only the same base fields of the `TeamBase` plus the `id`. But it doesn't include a field `heroes` for the **relationship attribute**.
45+
And the same way, we declared the `TeamPublic` with only the same base fields of the `TeamBase` plus the `id`. But it doesn't include a field `heroes` for the **relationship attribute**.
4646

4747
//// tab | Python 3.10+
4848

@@ -146,7 +146,7 @@ And the same way, we declared the `TeamRead` with only the same base fields of t
146146

147147
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>?
148148

149-
In this case, we used `response_model=TeamRead` and `response_model=HeroRead`, so FastAPI will use them to filter the response data, even if we return a **table model** that includes **relationship attributes**:
149+
In this case, we used `response_model=TeamPublic` and `response_model=HeroPublic`, so FastAPI will use them to filter the response data, even if we return a **table model** that includes **relationship attributes**:
150150

151151
//// tab | Python 3.10+
152152

@@ -300,7 +300,7 @@ Let's add a couple more **data models** that declare that data so we can use the
300300

301301
## Models with Relationships
302302

303-
Let's add the models `HeroReadWithTeam` and `TeamReadWithHeroes`.
303+
Let's add the models `HeroPublicWithTeam` and `TeamPublicWithHeroes`.
304304

305305
We'll add them **after** the other models so that we can easily reference the previous models.
306306

@@ -372,11 +372,11 @@ These two models are very **simple in code**, but there's a lot happening here.
372372

373373
### Inheritance and Type Annotations
374374

375-
The `HeroReadWithTeam` **inherits** from `HeroRead`, which means that it will have the **normal fields for reading**, including the required `id` that was declared in `HeroRead`.
375+
The `HeroPublicWithTeam` **inherits** from `HeroPublic`, which means that it will have the **normal fields for reading**, including the required `id` that was declared in `HeroPublic`.
376376

377-
And then it adds the **new field** `team`, which could be `None`, and is declared with the type `TeamRead` with the base fields for reading a team.
377+
And then it adds the **new field** `team`, which could be `None`, and is declared with the type `TeamPublic` with the base fields for reading a team.
378378

379-
Then we do the same for the `TeamReadWithHeroes`, it **inherits** from `TeamRead`, and declares the **new field** `heroes`, which is a list of `HeroRead`.
379+
Then we do the same for the `TeamPublicWithHeroes`, it **inherits** from `TeamPublic`, and declares the **new field** `heroes`, which is a list of `HeroPublic`.
380380

381381
### Data Models Without Relationship Attributes
382382

@@ -386,11 +386,11 @@ Instead, here these are only **data models** that will tell FastAPI **which attr
386386

387387
### Reference to Other Models
388388

389-
Also, notice that the field `team` is not declared with this new `TeamReadWithHeroes`, because that would again create that infinite recursion of data. Instead, we declare it with the normal `TeamRead` model.
389+
Also, notice that the field `team` is not declared with this new `TeamPublicWithHeroes`, because that would again create that infinite recursion of data. Instead, we declare it with the normal `TeamPublic` model.
390390

391-
And the same for `TeamReadWithHeroes`, the model used for the new field `heroes` uses `HeroRead` to get only each hero's data.
391+
And the same for `TeamPublicWithHeroes`, the model used for the new field `heroes` uses `HeroPublic` to get only each hero's data.
392392

393-
This also means that, even though we have these two new models, **we still need the previous ones**, `HeroRead` and `TeamRead`, because we need to reference them here (and we are also using them in the rest of the *path operations*).
393+
This also means that, even though we have these two new models, **we still need the previous ones**, `HeroPublic` and `TeamPublic`, because we need to reference them here (and we are also using them in the rest of the *path operations*).
394394

395395
## Update the Path Operations
396396

docs/tutorial/fastapi/teams.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ It's the same process we did for heroes, with a base model, a **table model**, a
1414

1515
We have a `TeamBase` **data model**, and from it, we inherit with a `Team` **table model**.
1616

17-
Then we also inherit from the `TeamBase` for the `TeamCreate` and `TeamRead` **data models**.
17+
Then we also inherit from the `TeamBase` for the `TeamCreate` and `TeamPublic` **data models**.
1818

1919
And we also create a `TeamUpdate` **data model**.
2020

docs_src/tutorial/fastapi/app_testing/tutorial001/main.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase):
1818
pass
1919

2020

21-
class HeroRead(HeroBase):
21+
class HeroPublic(HeroBase):
2222
id: int
2323

2424

@@ -52,7 +52,7 @@ def on_startup():
5252
create_db_and_tables()
5353

5454

55-
@app.post("/heroes/", response_model=HeroRead)
55+
@app.post("/heroes/", response_model=HeroPublic)
5656
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
5757
db_hero = Hero.model_validate(hero)
5858
session.add(db_hero)
@@ -61,7 +61,7 @@ def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
6161
return db_hero
6262

6363

64-
@app.get("/heroes/", response_model=List[HeroRead])
64+
@app.get("/heroes/", response_model=List[HeroPublic])
6565
def read_heroes(
6666
*,
6767
session: Session = Depends(get_session),
@@ -72,15 +72,15 @@ def read_heroes(
7272
return heroes
7373

7474

75-
@app.get("/heroes/{hero_id}", response_model=HeroRead)
75+
@app.get("/heroes/{hero_id}", response_model=HeroPublic)
7676
def read_hero(*, session: Session = Depends(get_session), hero_id: int):
7777
hero = session.get(Hero, hero_id)
7878
if not hero:
7979
raise HTTPException(status_code=404, detail="Hero not found")
8080
return hero
8181

8282

83-
@app.patch("/heroes/{hero_id}", response_model=HeroRead)
83+
@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
8484
def update_hero(
8585
*, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate
8686
):

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class HeroCreate(HeroBase):
1616
pass
1717

1818

19-
class HeroRead(HeroBase):
19+
class HeroPublic(HeroBase):
2020
id: int
2121

2222

@@ -50,7 +50,7 @@ def on_startup():
5050
create_db_and_tables()
5151

5252

53-
@app.post("/heroes/", response_model=HeroRead)
53+
@app.post("/heroes/", response_model=HeroPublic)
5454
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
5555
db_hero = Hero.model_validate(hero)
5656
session.add(db_hero)
@@ -59,7 +59,7 @@ def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
5959
return db_hero
6060

6161

62-
@app.get("/heroes/", response_model=list[HeroRead])
62+
@app.get("/heroes/", response_model=list[HeroPublic])
6363
def read_heroes(
6464
*,
6565
session: Session = Depends(get_session),
@@ -70,15 +70,15 @@ def read_heroes(
7070
return heroes
7171

7272

73-
@app.get("/heroes/{hero_id}", response_model=HeroRead)
73+
@app.get("/heroes/{hero_id}", response_model=HeroPublic)
7474
def read_hero(*, session: Session = Depends(get_session), hero_id: int):
7575
hero = session.get(Hero, hero_id)
7676
if not hero:
7777
raise HTTPException(status_code=404, detail="Hero not found")
7878
return hero
7979

8080

81-
@app.patch("/heroes/{hero_id}", response_model=HeroRead)
81+
@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
8282
def update_hero(
8383
*, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate
8484
):

docs_src/tutorial/fastapi/app_testing/tutorial001_py39/main.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase):
1818
pass
1919

2020

21-
class HeroRead(HeroBase):
21+
class HeroPublic(HeroBase):
2222
id: int
2323

2424

@@ -52,7 +52,7 @@ def on_startup():
5252
create_db_and_tables()
5353

5454

55-
@app.post("/heroes/", response_model=HeroRead)
55+
@app.post("/heroes/", response_model=HeroPublic)
5656
def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
5757
db_hero = Hero.model_validate(hero)
5858
session.add(db_hero)
@@ -61,7 +61,7 @@ def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate):
6161
return db_hero
6262

6363

64-
@app.get("/heroes/", response_model=list[HeroRead])
64+
@app.get("/heroes/", response_model=list[HeroPublic])
6565
def read_heroes(
6666
*,
6767
session: Session = Depends(get_session),
@@ -72,15 +72,15 @@ def read_heroes(
7272
return heroes
7373

7474

75-
@app.get("/heroes/{hero_id}", response_model=HeroRead)
75+
@app.get("/heroes/{hero_id}", response_model=HeroPublic)
7676
def read_hero(*, session: Session = Depends(get_session), hero_id: int):
7777
hero = session.get(Hero, hero_id)
7878
if not hero:
7979
raise HTTPException(status_code=404, detail="Hero not found")
8080
return hero
8181

8282

83-
@app.patch("/heroes/{hero_id}", response_model=HeroRead)
83+
@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
8484
def update_hero(
8585
*, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate
8686
):

docs_src/tutorial/fastapi/delete/tutorial001.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase):
1818
pass
1919

2020

21-
class HeroRead(HeroBase):
21+
class HeroPublic(HeroBase):
2222
id: int
2323

2424

@@ -47,7 +47,7 @@ def on_startup():
4747
create_db_and_tables()
4848

4949

50-
@app.post("/heroes/", response_model=HeroRead)
50+
@app.post("/heroes/", response_model=HeroPublic)
5151
def create_hero(hero: HeroCreate):
5252
with Session(engine) as session:
5353
db_hero = Hero.model_validate(hero)
@@ -57,14 +57,14 @@ def create_hero(hero: HeroCreate):
5757
return db_hero
5858

5959

60-
@app.get("/heroes/", response_model=List[HeroRead])
60+
@app.get("/heroes/", response_model=List[HeroPublic])
6161
def read_heroes(offset: int = 0, limit: int = Query(default=100, le=100)):
6262
with Session(engine) as session:
6363
heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
6464
return heroes
6565

6666

67-
@app.get("/heroes/{hero_id}", response_model=HeroRead)
67+
@app.get("/heroes/{hero_id}", response_model=HeroPublic)
6868
def read_hero(hero_id: int):
6969
with Session(engine) as session:
7070
hero = session.get(Hero, hero_id)
@@ -73,7 +73,7 @@ def read_hero(hero_id: int):
7373
return hero
7474

7575

76-
@app.patch("/heroes/{hero_id}", response_model=HeroRead)
76+
@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
7777
def update_hero(hero_id: int, hero: HeroUpdate):
7878
with Session(engine) as session:
7979
db_hero = session.get(Hero, hero_id)

docs_src/tutorial/fastapi/delete/tutorial001_py310.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class HeroCreate(HeroBase):
1616
pass
1717

1818

19-
class HeroRead(HeroBase):
19+
class HeroPublic(HeroBase):
2020
id: int
2121

2222

@@ -45,7 +45,7 @@ def on_startup():
4545
create_db_and_tables()
4646

4747

48-
@app.post("/heroes/", response_model=HeroRead)
48+
@app.post("/heroes/", response_model=HeroPublic)
4949
def create_hero(hero: HeroCreate):
5050
with Session(engine) as session:
5151
db_hero = Hero.model_validate(hero)
@@ -55,14 +55,14 @@ def create_hero(hero: HeroCreate):
5555
return db_hero
5656

5757

58-
@app.get("/heroes/", response_model=list[HeroRead])
58+
@app.get("/heroes/", response_model=list[HeroPublic])
5959
def read_heroes(offset: int = 0, limit: int = Query(default=100, le=100)):
6060
with Session(engine) as session:
6161
heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
6262
return heroes
6363

6464

65-
@app.get("/heroes/{hero_id}", response_model=HeroRead)
65+
@app.get("/heroes/{hero_id}", response_model=HeroPublic)
6666
def read_hero(hero_id: int):
6767
with Session(engine) as session:
6868
hero = session.get(Hero, hero_id)
@@ -71,7 +71,7 @@ def read_hero(hero_id: int):
7171
return hero
7272

7373

74-
@app.patch("/heroes/{hero_id}", response_model=HeroRead)
74+
@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
7575
def update_hero(hero_id: int, hero: HeroUpdate):
7676
with Session(engine) as session:
7777
db_hero = session.get(Hero, hero_id)

docs_src/tutorial/fastapi/delete/tutorial001_py39.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase):
1818
pass
1919

2020

21-
class HeroRead(HeroBase):
21+
class HeroPublic(HeroBase):
2222
id: int
2323

2424

@@ -47,7 +47,7 @@ def on_startup():
4747
create_db_and_tables()
4848

4949

50-
@app.post("/heroes/", response_model=HeroRead)
50+
@app.post("/heroes/", response_model=HeroPublic)
5151
def create_hero(hero: HeroCreate):
5252
with Session(engine) as session:
5353
db_hero = Hero.model_validate(hero)
@@ -57,14 +57,14 @@ def create_hero(hero: HeroCreate):
5757
return db_hero
5858

5959

60-
@app.get("/heroes/", response_model=list[HeroRead])
60+
@app.get("/heroes/", response_model=list[HeroPublic])
6161
def read_heroes(offset: int = 0, limit: int = Query(default=100, le=100)):
6262
with Session(engine) as session:
6363
heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()
6464
return heroes
6565

6666

67-
@app.get("/heroes/{hero_id}", response_model=HeroRead)
67+
@app.get("/heroes/{hero_id}", response_model=HeroPublic)
6868
def read_hero(hero_id: int):
6969
with Session(engine) as session:
7070
hero = session.get(Hero, hero_id)
@@ -73,7 +73,7 @@ def read_hero(hero_id: int):
7373
return hero
7474

7575

76-
@app.patch("/heroes/{hero_id}", response_model=HeroRead)
76+
@app.patch("/heroes/{hero_id}", response_model=HeroPublic)
7777
def update_hero(hero_id: int, hero: HeroUpdate):
7878
with Session(engine) as session:
7979
db_hero = session.get(Hero, hero_id)

0 commit comments

Comments
 (0)