| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent fa79856 commit 1eb40b1
68 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -98,7 +98,7 @@ But we also want to have a `HeroCreate` for the data we want to receive when **c | |||
| 98 | 98 | * `secret_name`, required | |
| 99 | 99 | * `age`, optional | |
| 100 | 100 | ||
| 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: | ||
| 102 | 102 | ||
| 103 | 103 | * `id`, required | |
| 104 | 104 | * `name`, required | |
@@ -183,9 +183,9 @@ Here's the important detail, and probably the most important feature of **SQLMod | |||
| 183 | 183 | ||
| 184 | 184 | This means that the class `Hero` represents a **table** in the database. It is both a **Pydantic** model and a **SQLAlchemy** model. | |
| 185 | 185 | ||
| 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). | ||
| 187 | 187 | ||
| 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. 🚀 | ||
| 189 | 189 | ||
| 190 | 190 | /// tip | |
| 191 | 191 | ||
@@ -355,7 +355,7 @@ Then we just `add` it to the **session**, `commit`, and `refresh` it, and finall | |||
| 355 | 355 | ||
| 356 | 356 | Because it is just refreshed, it has the `id` field set with a new ID taken from the database. | |
| 357 | 357 | ||
| 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`: | ||
| 359 | 359 | ||
| 360 | 360 | //// tab | Python 3.10+ | |
| 361 | 361 | ||
@@ -743,9 +743,9 @@ As an alternative, we could use `HeroBase` directly in the API code instead of ` | |||
| 743 | 743 | ||
| 744 | 744 | 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. | |
| 745 | 745 | ||
| 746 | - ### The `HeroRead` **Data Model** | ||
| 746 | + ### The `HeroPublic` **Data Model** | ||
| 747 | 747 | ||
| 748 | - Now let's check the `HeroRead` model. | ||
| 748 | + Now let's check the `HeroPublic` model. | ||
| 749 | 749 | ||
| 750 | 750 | 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. | |
| 751 | 751 | ||
@@ -815,7 +815,7 @@ This one just declares that the `id` field is required when reading a hero from | |||
| 815 | 815 | ||
| 816 | 816 | ## Review the Updated Docs UI | |
| 817 | 817 | ||
| 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. | ||
| 819 | 819 | ||
| 820 | 820 | So, we can jump to the docs UI right away and see how they look with the updated data. | |
| 821 | 821 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -164,7 +164,7 @@ This will let the client know that they probably made a mistake on their side an | |||
| 164 | 164 | ||
| 165 | 165 | Then, if the hero exists, we return it. | |
| 166 | 166 | ||
| 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. | ||
| 168 | 168 | ||
| 169 | 169 | //// tab | Python 3.10+ | |
| 170 | 170 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,9 +40,9 @@ Let's update that. 🤓 | |||
| 40 | 40 | ||
| 41 | 41 | First, why is it that we are not getting the related data for each hero and for each team? | |
| 42 | 42 | ||
| 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**. | ||
| 44 | 44 | ||
| 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**. | ||
| 46 | 46 | ||
| 47 | 47 | //// tab | Python 3.10+ | |
| 48 | 48 | ||
@@ -146,7 +146,7 @@ And the same way, we declared the `TeamRead` with only the same base fields of t | |||
| 146 | 146 | ||
| 147 | 147 | 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>? | |
| 148 | 148 | ||
| 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**: | ||
| 150 | 150 | ||
| 151 | 151 | //// tab | Python 3.10+ | |
| 152 | 152 | ||
@@ -300,7 +300,7 @@ Let's add a couple more **data models** that declare that data so we can use the | |||
| 300 | 300 | ||
| 301 | 301 | ## Models with Relationships | |
| 302 | 302 | ||
| 303 | - Let's add the models `HeroReadWithTeam` and `TeamReadWithHeroes`. | ||
| 303 | + Let's add the models `HeroPublicWithTeam` and `TeamPublicWithHeroes`. | ||
| 304 | 304 | ||
| 305 | 305 | We'll add them **after** the other models so that we can easily reference the previous models. | |
| 306 | 306 | ||
@@ -372,11 +372,11 @@ These two models are very **simple in code**, but there's a lot happening here. | |||
| 372 | 372 | ||
| 373 | 373 | ### Inheritance and Type Annotations | |
| 374 | 374 | ||
| 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`. | ||
| 376 | 376 | ||
| 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. | ||
| 378 | 378 | ||
| 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`. | ||
| 380 | 380 | ||
| 381 | 381 | ### Data Models Without Relationship Attributes | |
| 382 | 382 | ||
@@ -386,11 +386,11 @@ Instead, here these are only **data models** that will tell FastAPI **which attr | |||
| 386 | 386 | ||
| 387 | 387 | ### Reference to Other Models | |
| 388 | 388 | ||
| 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. | ||
| 390 | 390 | ||
| 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. | ||
| 392 | 392 | ||
| 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*). | ||
| 394 | 394 | ||
| 395 | 395 | ## Update the Path Operations | |
| 396 | 396 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,7 +14,7 @@ It's the same process we did for heroes, with a base model, a **table model**, a | |||
| 14 | 14 | ||
| 15 | 15 | We have a `TeamBase` **data model**, and from it, we inherit with a `Team` **table model**. | |
| 16 | 16 | ||
| 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**. | ||
| 18 | 18 | ||
| 19 | 19 | And we also create a `TeamUpdate` **data model**. | |
| 20 | 20 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase): | |||
| 18 | 18 | pass | |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - class HeroRead(HeroBase): | ||
| 21 | + class HeroPublic(HeroBase): | ||
| 22 | 22 | id: int | |
| 23 | 23 | ||
| 24 | 24 | ||
@@ -52,7 +52,7 @@ def on_startup(): | |||
| 52 | 52 | create_db_and_tables() | |
| 53 | 53 | ||
| 54 | 54 | ||
| 55 | - @app.post("/heroes/", response_model=HeroRead) | ||
| 55 | + @app.post("/heroes/", response_model=HeroPublic) | ||
| 56 | 56 | def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): | |
| 57 | 57 | db_hero = Hero.model_validate(hero) | |
| 58 | 58 | session.add(db_hero) | |
@@ -61,7 +61,7 @@ def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): | |||
| 61 | 61 | return db_hero | |
| 62 | 62 | ||
| 63 | 63 | ||
| 64 | - @app.get("/heroes/", response_model=List[HeroRead]) | ||
| 64 | + @app.get("/heroes/", response_model=List[HeroPublic]) | ||
| 65 | 65 | def read_heroes( | |
| 66 | 66 | *, | |
| 67 | 67 | session: Session = Depends(get_session), | |
@@ -72,15 +72,15 @@ def read_heroes( | |||
| 72 | 72 | return heroes | |
| 73 | 73 | ||
| 74 | 74 | ||
| 75 | - @app.get("/heroes/{hero_id}", response_model=HeroRead) | ||
| 75 | + @app.get("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 76 | 76 | def read_hero(*, session: Session = Depends(get_session), hero_id: int): | |
| 77 | 77 | hero = session.get(Hero, hero_id) | |
| 78 | 78 | if not hero: | |
| 79 | 79 | raise HTTPException(status_code=404, detail="Hero not found") | |
| 80 | 80 | return hero | |
| 81 | 81 | ||
| 82 | 82 | ||
| 83 | - @app.patch("/heroes/{hero_id}", response_model=HeroRead) | ||
| 83 | + @app.patch("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 84 | 84 | def update_hero( | |
| 85 | 85 | *, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate | |
| 86 | 86 | ): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,7 +16,7 @@ class HeroCreate(HeroBase): | |||
| 16 | 16 | pass | |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - class HeroRead(HeroBase): | ||
| 19 | + class HeroPublic(HeroBase): | ||
| 20 | 20 | id: int | |
| 21 | 21 | ||
| 22 | 22 | ||
@@ -50,7 +50,7 @@ def on_startup(): | |||
| 50 | 50 | create_db_and_tables() | |
| 51 | 51 | ||
| 52 | 52 | ||
| 53 | - @app.post("/heroes/", response_model=HeroRead) | ||
| 53 | + @app.post("/heroes/", response_model=HeroPublic) | ||
| 54 | 54 | def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): | |
| 55 | 55 | db_hero = Hero.model_validate(hero) | |
| 56 | 56 | session.add(db_hero) | |
@@ -59,7 +59,7 @@ def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): | |||
| 59 | 59 | return db_hero | |
| 60 | 60 | ||
| 61 | 61 | ||
| 62 | - @app.get("/heroes/", response_model=list[HeroRead]) | ||
| 62 | + @app.get("/heroes/", response_model=list[HeroPublic]) | ||
| 63 | 63 | def read_heroes( | |
| 64 | 64 | *, | |
| 65 | 65 | session: Session = Depends(get_session), | |
@@ -70,15 +70,15 @@ def read_heroes( | |||
| 70 | 70 | return heroes | |
| 71 | 71 | ||
| 72 | 72 | ||
| 73 | - @app.get("/heroes/{hero_id}", response_model=HeroRead) | ||
| 73 | + @app.get("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 74 | 74 | def read_hero(*, session: Session = Depends(get_session), hero_id: int): | |
| 75 | 75 | hero = session.get(Hero, hero_id) | |
| 76 | 76 | if not hero: | |
| 77 | 77 | raise HTTPException(status_code=404, detail="Hero not found") | |
| 78 | 78 | return hero | |
| 79 | 79 | ||
| 80 | 80 | ||
| 81 | - @app.patch("/heroes/{hero_id}", response_model=HeroRead) | ||
| 81 | + @app.patch("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 82 | 82 | def update_hero( | |
| 83 | 83 | *, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate | |
| 84 | 84 | ): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase): | |||
| 18 | 18 | pass | |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - class HeroRead(HeroBase): | ||
| 21 | + class HeroPublic(HeroBase): | ||
| 22 | 22 | id: int | |
| 23 | 23 | ||
| 24 | 24 | ||
@@ -52,7 +52,7 @@ def on_startup(): | |||
| 52 | 52 | create_db_and_tables() | |
| 53 | 53 | ||
| 54 | 54 | ||
| 55 | - @app.post("/heroes/", response_model=HeroRead) | ||
| 55 | + @app.post("/heroes/", response_model=HeroPublic) | ||
| 56 | 56 | def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): | |
| 57 | 57 | db_hero = Hero.model_validate(hero) | |
| 58 | 58 | session.add(db_hero) | |
@@ -61,7 +61,7 @@ def create_hero(*, session: Session = Depends(get_session), hero: HeroCreate): | |||
| 61 | 61 | return db_hero | |
| 62 | 62 | ||
| 63 | 63 | ||
| 64 | - @app.get("/heroes/", response_model=list[HeroRead]) | ||
| 64 | + @app.get("/heroes/", response_model=list[HeroPublic]) | ||
| 65 | 65 | def read_heroes( | |
| 66 | 66 | *, | |
| 67 | 67 | session: Session = Depends(get_session), | |
@@ -72,15 +72,15 @@ def read_heroes( | |||
| 72 | 72 | return heroes | |
| 73 | 73 | ||
| 74 | 74 | ||
| 75 | - @app.get("/heroes/{hero_id}", response_model=HeroRead) | ||
| 75 | + @app.get("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 76 | 76 | def read_hero(*, session: Session = Depends(get_session), hero_id: int): | |
| 77 | 77 | hero = session.get(Hero, hero_id) | |
| 78 | 78 | if not hero: | |
| 79 | 79 | raise HTTPException(status_code=404, detail="Hero not found") | |
| 80 | 80 | return hero | |
| 81 | 81 | ||
| 82 | 82 | ||
| 83 | - @app.patch("/heroes/{hero_id}", response_model=HeroRead) | ||
| 83 | + @app.patch("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 84 | 84 | def update_hero( | |
| 85 | 85 | *, session: Session = Depends(get_session), hero_id: int, hero: HeroUpdate | |
| 86 | 86 | ): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,7 +18,7 @@ class HeroCreate(HeroBase): | |||
| 18 | 18 | pass | |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - class HeroRead(HeroBase): | ||
| 21 | + class HeroPublic(HeroBase): | ||
| 22 | 22 | id: int | |
| 23 | 23 | ||
| 24 | 24 | ||
@@ -47,7 +47,7 @@ def on_startup(): | |||
| 47 | 47 | create_db_and_tables() | |
| 48 | 48 | ||
| 49 | 49 | ||
| 50 | - @app.post("/heroes/", response_model=HeroRead) | ||
| 50 | + @app.post("/heroes/", response_model=HeroPublic) | ||
| 51 | 51 | def create_hero(hero: HeroCreate): | |
| 52 | 52 | with Session(engine) as session: | |
| 53 | 53 | db_hero = Hero.model_validate(hero) | |
@@ -57,14 +57,14 @@ def create_hero(hero: HeroCreate): | |||
| 57 | 57 | return db_hero | |
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | - @app.get("/heroes/", response_model=List[HeroRead]) | ||
| 60 | + @app.get("/heroes/", response_model=List[HeroPublic]) | ||
| 61 | 61 | def read_heroes(offset: int = 0, limit: int = Query(default=100, le=100)): | |
| 62 | 62 | with Session(engine) as session: | |
| 63 | 63 | heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() | |
| 64 | 64 | return heroes | |
| 65 | 65 | ||
| 66 | 66 | ||
| 67 | - @app.get("/heroes/{hero_id}", response_model=HeroRead) | ||
| 67 | + @app.get("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 68 | 68 | def read_hero(hero_id: int): | |
| 69 | 69 | with Session(engine) as session: | |
| 70 | 70 | hero = session.get(Hero, hero_id) | |
@@ -73,7 +73,7 @@ def read_hero(hero_id: int): | |||
| 73 | 73 | return hero | |
| 74 | 74 | ||
| 75 | 75 | ||
| 76 | - @app.patch("/heroes/{hero_id}", response_model=HeroRead) | ||
| 76 | + @app.patch("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 77 | 77 | def update_hero(hero_id: int, hero: HeroUpdate): | |
| 78 | 78 | with Session(engine) as session: | |
| 79 | 79 | db_hero = session.get(Hero, hero_id) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,7 +16,7 @@ class HeroCreate(HeroBase): | |||
| 16 | 16 | pass | |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - class HeroRead(HeroBase): | ||
| 19 | + class HeroPublic(HeroBase): | ||
| 20 | 20 | id: int | |
| 21 | 21 | ||
| 22 | 22 | ||
@@ -45,7 +45,7 @@ def on_startup(): | |||
| 45 | 45 | create_db_and_tables() | |
| 46 | 46 | ||
| 47 | 47 | ||
| 48 | - @app.post("/heroes/", response_model=HeroRead) | ||
| 48 | + @app.post("/heroes/", response_model=HeroPublic) | ||
| 49 | 49 | def create_hero(hero: HeroCreate): | |
| 50 | 50 | with Session(engine) as session: | |
| 51 | 51 | db_hero = Hero.model_validate(hero) | |
@@ -55,14 +55,14 @@ def create_hero(hero: HeroCreate): | |||
| 55 | 55 | return db_hero | |
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | - @app.get("/heroes/", response_model=list[HeroRead]) | ||
| 58 | + @app.get("/heroes/", response_model=list[HeroPublic]) | ||
| 59 | 59 | def read_heroes(offset: int = 0, limit: int = Query(default=100, le=100)): | |
| 60 | 60 | with Session(engine) as session: | |
| 61 | 61 | heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() | |
| 62 | 62 | return heroes | |
| 63 | 63 | ||
| 64 | 64 | ||
| 65 | - @app.get("/heroes/{hero_id}", response_model=HeroRead) | ||
| 65 | + @app.get("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 66 | 66 | def read_hero(hero_id: int): | |
| 67 | 67 | with Session(engine) as session: | |
| 68 | 68 | hero = session.get(Hero, hero_id) | |
@@ -71,7 +71,7 @@ def read_hero(hero_id: int): | |||
| 71 | 71 | return hero | |
| 72 | 72 | ||
| 73 | 73 | ||
| 74 | - @app.patch("/heroes/{hero_id}", response_model=HeroRead) | ||
| 74 | + @app.patch("/heroes/{hero_id}", response_model=HeroPublic) | ||
| 75 | 75 | def update_hero(hero_id: int, hero: HeroUpdate): | |
| 76 | 76 | with Session(engine) as session: | |
| 77 | 77 | db_hero = session.get(Hero, hero_id) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments