Introducción a FastAPI

1

¿Qué es FastAPI? con Sebastián Ramírez @Tiangolo

2

Instalación de FastAPI y creación de tu primera aplicación

3

Documentación automática con Swagger

4

Métodos HTTP en FastAPI

FastAPI Path Operations

5

Método GET en FastAPI

6

Crear parámetros de ruta en FastAPI

7

Parámetros Query en FastAPI

8

Método POST en FastAPI

9

Métodos PUT y DELETE en FastAPI

Validaciones con Pydantic

10

Creación de esquemas con Pydantic

11

Validaciones de tipos de datos con Pydantic

12

Validaciones de parámetros con Pydantic

13

JSONResponse: Tipos de respuestas en FastAPI

14

Códigos de estado HTTP en FastAPI

Autenticación en FastAPI

15

Flujo de autenticación en FastAPI

16

Generando tokens con PyJWT

17

Validando tokens con PyJWT

18

Middlewares de autenticación en FastAPI

Conexión con bases de datos en FastAPI

19

SQLAlchemy: el ORM de FastAPI

20

Instalación y configuración de SQLAlchemy

21

Creación de modelos con SQLAlchemy

22

Registro de datos con SQLAlchemy

23

Consulta de datos con SQLAlchemy

24

Modificación y eliminación de datos con SQLAlchemy

25

SQLModel: el futuro ORM de FastAPI

Modularización

26

Manejo de errores y middlewares en FastAPI

27

Creación de routers en FastAPI

28

Servicios para consultar datos

29

Servicios para registrar y modificar datos

Despliegue de Aplicación en FastAPI

30

Preparando el proyecto para desplegar a producción

31

¿Cómo elegir entre GitHub y GitLab?

32

Crear repositorio en GitLab

33

Crear Droplet en Digital Ocean

34

Instalación de herramientas para el servidor

35

Ejecutando FastAPI con NGINX

Próximos pasos

36

¿Quieres más cursos de FastAPI?

Bonus

37

Cómo crear una API de alto rendimiento en tiempo récord - Sebastián Ramírez

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de FastAPI

Curso de FastAPI

Pablo España

Pablo España

Método POST en FastAPI

8/37
Recursos

Explorando el uso del método POST en FastAPI

Adentrarse en la construcción de una API implica familiarizarse con diversos métodos para el manejo de datos. Uno de los métodos fundamentales es el POST, esencial para crear o modificar registros en una base de datos. Aprender a implementarlo correctamente puede ser decisivo para el éxito de una API. En esta ocasión, desglosaremos cómo hacer uso del método POST en FastAPI y afrontaremos el desafío de construir un endpoint para registrar películas.

¿Cómo recibir datos en nuestra API mediante POST?

Recibir datos a través de POST es una práctica común para enviar información que no debe ir en la URL, como cuando registramos o modificamos datos sensibles. En FastAPI, trabajar con el método POST es sencillo y permite mantener la seguridad de los datos transmitidos. Te mostraremos cómo definir el método en tu API para recibir datos de manera efectiva.

Pasos para implementar el método POST en FastAPI

Utilizar el método POST en FastAPI implica seguir una serie de pasos claros y definidos que aseguran la correcta recepción y manejo de la data enviada. Aquí te detallo cómo llevarlo a cabo:

  • Definir la ruta: Usa el decorador correspondiente para especificar el endpoint al cual se enviarán los datos.
  • Crear la función asociada: Define la función que manejará la petición POST. Aquí se especificarán los parámetros que esperas recibir.
  • Establecer los tipos de datos: Cada dato debe tener un tipo definido para garantizar que se maneje correctamente.
  • Añadir los datos al listado: Una vez recibidos los datos, debes añadirlos al listado de registros mediante una función que permita la inserción.

Solución al reto: filtrando películas por categoría

Antes de avanzar, vamos a revisar la solución al reto de filtrado de películas por categoría. Implementar un filtro a través de un parámetro QUERY es un excelente ejercicio para profundizar en cómo FastAPI maneja los parámetros. El uso de un bucle FOR en línea permitió filtrar y devolver las películas que coincidieran con la categoría deseada, simplificando la tarea considerablemente.

Mejoras en la recepción de datos mediante body

Inicialmente, se podía incurrir en el error de recibir datos como parámetros query en lugar de en el cuerpo de la petición. Esto se soluciona especificando que los datos deben recibir la clase body, mejorando así la estructura de la petición y la seguridad de los datos transmitidos.

Desafío para el estudiante: ¿Puedes manejar la edición y eliminación de películas?

Ahora que has aprendido a registrar películas utilizando el método POST, te animo a que tomes el siguiente escalón y pruebes a implementar los métodos PUT y DELETE. Estos serán cruciales para editar y eliminar registros de manera eficiente. La documentación de FastAPI será tu aliada en este desafío, así que no dudes en consultarla.

En resumen

El método POST en FastAPI es poderoso y flexible, permitiéndote manejar datos de forma segura y eficiente. Con la solución al reto de filtrado y los pasos para implementar correctamente el método POST, estas herramientas son esenciales para seguir construyendo tu API. Acepta el desafío de los métodos PUT y DELETE y recuerda que cada paso que das es un avance en tu camino de aprendizaje en el desarrollo de aplicaciones y APIs. ¡Adelante con tu proyecto!

Aportes 25

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Para tener un poco más ordenado el código, para éste método creé una carpeta model, y dentro de esta creé una clase llama movie.py de la siguiente manera: ```js from pydantic import BaseModel class Movie(BaseModel): id: int title: str overview: str year: int rating: float category: str ```
El reto de la clase anterior lo resolví de la siguiente manera: ```js @app.get('/movies/', tags=['movies']) def FilterByCategory(category : str): return list(filter(lambda item:item['category']==category,movies)) ```Realicé anteriormente un for para recorrerlo, y luego realicé esta solución usando filter y lambda function, para poder utilizar lo que he ido estudiando y que no se me olvide jajaja
Optimización del código y validaciones para que no me pongan el mismo id: ![](https://static.platzi.com/media/user_upload/image-11439f04-0ca7-47fe-9ece-ebc7a92ca63b.jpg)
Hacer otra prueba interesante que creo se le escapa al profesor para profundizar y hacer que se parezca a lo que hacemos en el dia a dia es hacer que el id se calcule solo, porque no siempre podemos saber cual el ultimo "id" creado o cuales ya existen por eso me parece que esta podria ser una solucion valida: @app.post('/movies', tags=\['movies'])def create\_movie(id: int = Body(), title: str = Body(), overview:str = Body(), year:int = Body(), rating: float = Body(), category: str = Body()): *#Calculamos el ID maximo para hacer que se agregue de manera automatica*    max\_value = max(movies\_list, key=lambda x:x\['id'])    max\_id = max\_value\['id']    id = max\_id+1    movies\_list.append({        "id": id,         "title": title,        "overview": overview,         "year": year,        "rating": rating,        "category": category       })        return movies\_list ```js @app.post('/movies', tags=['movies']) def create_movie(id: int = Body(), title: str = Body(), overview:str = Body(), year:int = Body(), rating: float = Body(), category: str = Body()): #Calculamos el ID maximo para hacer que se agregue de manera automatica max_value = max(movies_list, key=lambda x:x['id']) max_id = max_value['id'] id = max_id+1 movies_list.append({ "id": id, "title": title, "overview": overview, "year": year, "rating": rating, "category": category }) return movies_list ```
Creamos una ruta con el método POST para Crear una Pelicula y retornar su información con base en el id ```python from fastapi import FastAPI, Body @app.post("/movies", tags = ["movies"]) def create_movie(id: int = Body(), title: str = Body(), overview: str = Body(), year: int = Body(), rating: float = Body(), category: str = Body()): movies.append( { "id": id, "title": title, "overview": overview, "year": year, "rating": rating, "category": category } ) return [movie for movie in movies if movie["id"] == id] ```
```python @app.put('/movies/{id}', tags=['Movies']) def update_movie( id: int, title: str = Body(), overview: str = Body(), year: str = Body(), rating: int = Body(), category: int = Body() ): for movie in movies: if movie['id'] == id: movie.update({ 'id': id, 'title': title, 'overview': overview, 'year': year, 'rating': rating, 'category': category, }) return movies @app.delete('/movies/{id}', tags=['Movies']) def delete_movie(id: int): global movies filtered_movies = list(filter(lambda movie: movie['id'] != id, movies)) movies = filtered_movies return movies ```
Me gusto esta clase. No imagine que crear apis en este framework fuera tan sencillo que no genera ningun problema.
```python @app.put('/movies', tags=['movies']) def update_movie(id: int, title: str, overview:str, year:int, rating: float, category: str): for movie in movies: if movie['id'] == id: movie['title'] = title movie['overview'] = overview movie['year'] = year movie['rating'] = rating movie['category'] = category return movie @app.delete('/movies/{id}', tags=['Movies']) def delete_movie(id: int): movie = ... for i in movies: if i['id'] == id: movie = i movies.remove(movie) return movies ```
@app.put("/movies/{movie\_id}", tags=\["Movies"])def update\_movie(movie\_id: int, title: str = Body(), year: int = Body(), rating: int = Body(), category: str = Body()):    new\_movie = next((movie for movie in movies if movie\["id"] == movie\_id), None)    if new\_movie:        new\_movie\["title"] = title        new\_movie\["release\_year"] = year        new\_movie\["rating"] = rating        new\_movie\["category"] = category    return new\_movie @app.delete("/movies/{id}",tags = \["movies"])def delete\_movie(id: int):    #el next busca dentro de un iterable el primer elemento con el que coincide, si no retorna un none    movie\_to\_delete= next((movie for movie in movies if movie\["id"] == id), None)    if movie\_to\_delete is None:        raise HTTPException(status\_code=404, detail="Movie not found")    movies.remove(movie\_to\_delete)    return {"mensaje": "movie delated succesfully", "movies": movies}
```js from fastapi import FastAPI, Body from fastapi.responses import HTMLResponse app = FastAPI() app.title = "nueva version de la api" app.version = "0.0.1" movies = [ { "id": 1, "title": "The Shawshank Redemption", "release_year": 1994, "duration": 142, "description": "Two imprisoned", "director": "Frank Darabont", }, { "id": 2, "title": "The Godfather", "release_year": 1972, "duration": 175, "description": "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.", "director": "Francis Ford Coppola", }, { "id": 3, "title": "The Dark Knight", "release_year": 2008, "duration": 152, "description": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, Batman must accept one of the greatest psychological and physical tests of his ability to fight injustice.", "director": "Christopher Nolan", }, { "id": 4, "title ": "12 Angry" , "release_year": 1957, "duration": 96, "description": "A jury holdout attempts to prevent a miscarriage of justice by forcing his colleagues to reconsider the evidence.", "director": "Sidney Lumet", }, { "id": 5, "title": "Schindler's List", "release_year": 1993, "duration": 195, "description": "In German-occupied Poland during World War II, industrialist Oskar Schindler gradually becomes concerned for his Jewish workforce after witnessing their persecution ", "director": "Steven Spielberg", }, ] @app.get("/", tags=["Root"]) def read_root(): return HTMLResponse(content="

FastAPI

") @app.get("/movies", tags=["Movies"]) def read_movies(): return (movies) @app.get("/movies/{movie_id}", tags=["Movies"]) def read_movie(movie_id: int): return next((movie for movie in movies if movie["id"] == movie_id), None) @app.get ("/movies/filter", tags=["Movies"]) def read_movie_by_category(category: str, year: int, duration: int): return next((movie for movie in movies if movie["category"] == category and movie["year"] == year and movie["duration"] == duration), None) @app.post("/movies", tags=["Movies"]) def create_movie(id: int = Body (), title: str = Body(), release_year: int = Body(), duration: int = Body(), description: str = Body(), director: str = Body()): movie = { "id": id, "title": title, "release_year": release_year, "duration": duration, "description": description, "director": director, } movies.append(movie) return movie @app.put("/movies/{movie_id}", tags=["Movies"]) def update_movie(movie_id: int, title: str = Body(), release_year: int = Body(), duration: int = Body(), description: str = Body(), director: str = Body()): movie = next((movie for movie in movies if movie["id"] == movie_id), None) if movie: movie["title"] = title movie["release_year"] = release_year movie["duration"] = duration movie["description"] = description movie["director"] = director return movie @app.delete("/movies/{movie_id}", tags=["Movies"]) def delete_movie(movie_id: int): movie = next((movie for movie in movies if movie["id"] == movie_id), None) if movie: movies.remove(movie) return movie ```from fastapi import FastAPI, Bodyfrom fastapi.responses import HTMLResponse app = FastAPI()app.title = "nueva version de la api"app.version = "0.0.1" movies = \[{        "id": 1,    "title": "The Shawshank Redemption",    "release\_year": 1994,    "duration": 142,    "description": "Two imprisoned",    "director": "Frank Darabont",},          {    "id": 2,    "title": "The Godfather",    "release\_year": 1972,    "duration": 175,    "description": "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.",    "director": "Francis Ford Coppola",},          {    "id": 3,    "title": "The Dark Knight",    "release\_year": 2008,    "duration": 152,    "description": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, Batman must accept one of the greatest psychological and physical tests of his ability to fight injustice.",    "director": "Christopher Nolan",},          {    "id": 4,    "title ": "12 Angry" ,    "release\_year": 1957,    "duration": 96,    "description": "A jury holdout attempts to prevent a miscarriage of justice by forcing his colleagues to reconsider the evidence.",    "director": "Sidney Lumet",    },          {    "id": 5,    "title": "Schindler's List",    "release\_year": 1993,    "duration": 195,    "description": "In German-occupied Poland during World War II, industrialist Oskar Schindler gradually becomes concerned for his Jewish workforce after witnessing their persecution ",    "director": "Steven Spielberg",},]    @app.get("/", tags=\["Root"])def read\_root():    return HTMLResponse(content="\

FastAPI\

") @app.get("/movies", tags=\["Movies"])def read\_movies():    return (movies) @app.get("/movies/{movie\_id}", tags=\["Movies"])def read\_movie(movie\_id: int):    return next((movie for movie in movies if movie\["id"] == movie\_id), None) @app.get ("/movies/filter", tags=\["Movies"])def read\_movie\_by\_category(category: str, year: int, duration: int):    return next((movie for movie in movies if movie\["category"] == category and movie\["year"] == year and movie\["duration"] == duration), None) @app.post("/movies", tags=\["Movies"])def create\_movie(id: int = Body (), title: str = Body(), release\_year: int = Body(), duration: int = Body(), description: str = Body(), director: str = Body()):    movie = {        "id": id,        "title": title,        "release\_year": release\_year,        "duration": duration,        "description": description,        "director": director,    }    movies.append(movie)    return movie @app.put("/movies/{movie\_id}", tags=\["Movies"])def update\_movie(movie\_id: int, title: str = Body(), release\_year: int = Body(), duration: int = Body(), description: str = Body(), director: str = Body()):    movie = next((movie for movie in movies if movie\["id"] == movie\_id), None)    if movie:        movie\["title"] = title        movie\["release\_year"] = release\_year        movie\["duration"] = duration        movie\["description"] = description        movie\["director"] = director    return movie @app.delete("/movies/{movie\_id}", tags=\["Movies"])def delete\_movie(movie\_id: int):    movie = next((movie for movie in movies if movie\["id"] == movie\_id), None)    if movie:        movies.remove(movie)    return movie

esta fue una implementacion que utilice para el metodo put que se usa para modificar un elemento ya existente el value : str | int se usa para indicarle que ese parametro puede ser un string o un int, esta implementacion funciona para cambiar de a un key:value en el diccionario estoy analizando como estructurar el codigo para actualizar mas de un elemento en una sola interaccion… ideas?

Mi solucion

@app.get('/movies/', tags=['movies'])
def getMoviesByCategory(category: str, year: int):
    return list(filter(lambda item : item['year'] == year or item['category'] == category, movies))
Este es mi código: ```js from fastapi import FastAPI, Body from fastapi.responses import HTMLResponse app = FastAPI() app.title = "My app with FastAPI" app.version = "0.0.1" movies = [ { "id":1, "title":"Avatar", "overview":"On a lush planet called Pandora live the Na'vi, beings who...", "year":2009, "rating":7.8, "category":"Action" }, { "id":2, "title":"Titanic", "overview":"Titanic, launched on May 31, 1911, and set sail on its maiden...", "year":1997, "rating":7.9, "category":"Romantic/Adventure" } ] @app.get("/", tags=["home"]) def message(): return HTMLResponse("

Hello world

") @app.get("/movies", tags=["movies"]) def get_movies(): return movies @app.get("/movies/{id}", tags=["movies"]) def get_movie(id: int): result = [item for item in movies if item["id"] == id] return result[0] if result else {"error": "id does not exist in our database"} @app.get("/movies/", tags=["movies"]) def get_movie_by_category(category: str): result = [item for item in movies if item["category"] == category] return result[0] if result else {"error": "category does not exist in our database"} @app.post("/movies", tags=["movies"]) def create_movie(id: int = Body(), title: str = Body(), overview: str= Body(), year: int= Body(), rating: float= Body(), category: str= Body()): movies.append({ "id": id, "title": title, "overview": overview, "year": year, "rating": rating, "category": category }) return movies @app.put("/movies/{id}", tags=["movies"]) def update_movie(id: int, title: str = Body(), overview: str= Body(), year: int= Body(), rating: float= Body(), category: str= Body()): updated_movies = [{**item, **{"title": title, "overview": overview, "year": year, "rating": rating, "category": category}} if item["id"] == id else item for item in movies] if updated_movies != movies: movies[:] = updated_movies return {"message": "Movie details updated successfully"} else: return {"error": "id does not exist in our database"} @app.delete("/movies/{id}", tags=["movies"]) def delete_movie(id: int): deleted_movie = [item for item in movies if item["id"] != id] if deleted_movie != movies: movies[:] = deleted_movie return {"message": "Movie deleted successfully"} else: return {"error": "id does not exist in our database"} ```from fastapi import FastAPI, Bodyfrom fastapi.responses import HTMLResponse app = FastAPI()app.title = "My app with FastAPI"app.version = "0.0.1" movies = \[    {   "id":1,         "title":"Avatar",         "overview":"On a lush planet called Pandora live the Na'vi, beings who...",         "year":2009,         "rating":7.8,         "category":"Action"    },    {   "id":2,         "title":"Titanic",         "overview":"Titanic, launched on May 31, 1911, and set sail on its maiden...",         "year":1997,         "rating":7.9,         "category":"Romantic/Adventure"    }] @app.get("/", tags=\["home"])def message():    return HTMLResponse("\

Hello world\

") @app.get("/movies", tags=\["movies"])def get\_movies():    return movies @app.get("/movies/{id}", tags=\["movies"])def get\_movie(id: int):    result = \[item for item in movies if item\["id"] == id]    return result\[0] if result else {"error": "id does not exist in our database"} @app.get("/movies/", tags=\["movies"])def get\_movie\_by\_category(category: str):    result = \[item for item in movies if item\["category"] == category]    return result\[0] if result else {"error": "category does not exist in our database"} @app.post("/movies", tags=\["movies"])def create\_movie(id: int = Body(), title: str = Body(), overview: str= Body(), year: int= Body(), rating: float= Body(), category: str= Body()):    movies.append({        "id": id,        "title": title,        "overview": overview,        "year": year,        "rating": rating,        "category": category        })    return movies @app.put("/movies/{id}", tags=\["movies"])def update\_movie(id: int, title: str = Body(), overview: str= Body(), year: int= Body(), rating: float= Body(), category: str= Body()):    updated\_movies = \[{\*\*item, \*\*{"title": title, "overview": overview, "year": year, "rating": rating, "category": category}} if item\["id"] == id else item for item in movies]        if updated\_movies != movies:        movies\[:] = updated\_movies        return {"message": "Movie details updated successfully"}    else:        return {"error": "id does not exist in our database"} @app.delete("/movies/{id}", tags=\["movies"])def delete\_movie(id: int):    deleted\_movie = \[item for item in movies if item\["id"] != id]     if deleted\_movie != movies:        movies\[:] = deleted\_movie        return {"message": "Movie deleted successfully"}    else:        return {"error": "id does not exist in our database"}
En el archivo main.py importe el objeto Movie ```js from model.movie import Movie ```Agregué el objeto a la lista y retorné el listado de películas ```js @app.post('/movies', tags=['movies']) def create_movie(id: int = Body(), title: str = Body(), overview: str = Body(), year: int = Body(), rating: float = Body(), category: str = Body()): movie = Movie(id = id, title=title, overview= overview, year= year, rating= rating, category= category) movies.append(movie.model_dump()) return movies ```
```python Response body Download [ { "id": 1, "title": "Avatar", "overview": "En un exuberante planeta llamado Pandora viven los Na'vi, seres que ...", "year": "2009", "rating": 7.8, "category": "Acción" }, { "id": 2, "title": "Avatar", "overview": "En un exuberante planeta llamado Pandora viven los Na'vi, seres que ...", "year": "2009", "rating": 7.8, "category": "Terror" }, { "id": 3, "title": "Spider-Man: sin camino a casa", "overview": "With Spider-Man's identity now revealed, Peter asks Doctor Strange for help. When a spell goes wrong, dangerous foes from other worlds start to appear, forcing Peter to discover what it truly means to be Spider-Man.", "year": 2021, "rating": 8.2, "category": "Fantasía" } ] ``` Response body Download\[ { ` "id": 1`, ` "title": "Avatar"`, ` "overview": "En un exuberante planeta llamado Pandora viven los Na'vi, seres que ..."`, ` "year": "2009"`, ` "rating": 7.8`, ` "category": "Acción"` }, { ` "id": 2`, ` "title": "Avatar"`, ` "overview": "En un exuberante planeta llamado Pandora viven los Na'vi, seres que ..."`, ` "year": "2009"`, ` "rating": 7.8`, ` "category": "Terror"` }, { ` "id": 3`, ` "title": "Spider-Man: sin camino a casa"`, ` "overview": "With Spider-Man's identity now revealed, Peter asks Doctor Strange for help. When a spell goes wrong, dangerous foes from other worlds start to appear, forcing Peter to discover what it truly means to be Spider-Man."`, ` "year": 2021`, ` "rating": 8.2`, ` "category": "Fantasía"` } `]`
Así resolví el reto de la anterior clase Con este buco las categorías: `@app.get('/movies/', tags=["movies"])` `async def get_movies_by_category(category: str):` ` return movies_category(category)` Gracias a este método que me cree: `def movies_category(category: str):` ` movie = filter(lambda el: el.category == category, movies_list)` ` try: return list(movie)[0]` ` except: return {"error": "Movies Not Found"}` Así resolví el reto de esta clase: `@app.post('/movies', tags=["movies"])` `async def create_movies(movie: Movies):` ` if type(movies_exist(movie.id)) == Movies:` ` return "Movies exist"` ` movies_list.append(movie)` ` return movie.title` `@app.put('/movies', tags=['movies'])` `async def movies(movie: Movies):` ` found: bool = False` ` for i, saved_movies in enumerate(movies_list):` ` if saved_movies.id == movie.id:` ` movies_list[i] = movie` ` found = True` ` if not found:` ` return {"error": "Could not update"}` ` return movie` ` ` `@app.delete('/movies/{id}', tags=['movies'])` `async def delete_movies(id: int):` ` found: bool = False` ` for i, saved_movies in enumerate(movies_list):` ` if saved_movies.id == id:` ` del movies_list[i]` ` found = True` ` if not found:` ` return {"error": "Could not delete"}` ` return {"message": "Delete successfully"}`
```python @app.put('/movies/{id}', tags=['movies']) def update_movie(id: int, title: str = Body(), overview: str = Body(), year: int = Body(), rating: float = Body(), category: str = Body()): movie = next((m for m in movies if m["id"] == id), None) if movie: movie["title"] = title movie["overview"] = overview movie["year"] = year movie["rating"] = rating movie["category"] = category return movies @app.delete('/movies/{id}', tags=['movies']) def delete_movie(id: int): movie = next((m for m in movies if m["id"] == id), None) if movie: movies.remove(movie) return movies ```
![]()![](https://static.platzi.com/media/user_upload/Screenshot%20from%202024-01-19%2016-54-12-1c769813-08e3-4d72-9c1c-5437442fb333.jpg) Tome en cuenta la posibilidad de que la categoria no existiera entonce usara el query del año
file:///home/santyamaya98/Pictures/Screenshots/Screenshot%20from%202024-01-19%2016-54-12.png tome en cuenta la posibilidad de que la categoria no hiciera match asi que buscara por el año... <3
Mi solución de la clase anterior y tome encuenta la posi![](https://static.platzi.com/media/user_upload/Screenshot%20from%202024-01-19%2016-54-12-217197be-d306-44a8-8ff5-f3b630e26f83.jpg)
También puedes crear un archivo `models.py` y allí definir la estructura de movie: ```python # models.py from pydantic import BaseModel class MovieModel(BaseModel): id: int title: str overview: str year: int rating: float category: str ```Luego lo pasa en como parámetro de la función ```python from models import MovieModel def create_movie(movie: MovieModel): # ..... ```
Solucioné el reto creando una lista vacia, la cual se irá llenando con los elementos que cumplen la condición, pára esto es necesario importar la clase "List". ```python @app.get('/movies/', tags=['Movies']) def get_movies_by_category(category: str): matching_movies = [] for item in movies: if item['category'] == category: matching_movies.append(item) return matching_movies or HTMLResponse('<h5>No hay películas con este género.</h5>') ```@app.get('/movies/', tags=\['Movies'])def get\_movies\_by\_category(category: str):    matching\_movies = \[]    for item in movies:        if item\['category'] == category:            matching\_movies.append(item)    return matching\_movies or HTMLResponse('\<h5>No hay películas con este género.\</h5>')

Código generado por una IA

from fastapi import FastAPI, Body, HTTPException
from pydantic import BaseModel

class Movie(BaseModel):
    id: int
    name: str
    year: int
    category: str

app = FastAPI()

movies = []

@app.post("/movies/", tags=["Movies"])
def create_movie(movie: Movie):
    movies.append(movie.dict())
    return {"message": "Película creada correctamente"}

@app.put("/movies/{id}", tags=["Movies"])
def update_movie(id: int, movie: Movie = Body(...)):
    for index, stored_movie in enumerate(movies):
        if stored_movie["id"] == id:
            movies[index] = movie.dict()
            return {"message": "Película actualizada correctamente"}
    raise HTTPException(status_code=404, detail="Película no encontrada")

@app.delete("/movies/{id}", tags=["Movies"])
def delete_movie(id: int):
    for movie in movies:
        if movie["id"] == id:
            movies.remove(movie)
            return {"message": "Película eliminada correctamente"}
    raise HTTPException(status_code=404, detail="Película no encontrada")

Para actualizar y eliminar una pelicula…

# Actualizar una pelicula
@app.put("/movies/{id}", tags=["Movies"])
def update_movie(id: int, name: str = Body(), year: int = Body(), category: str = Body()):
    for movie in movies:
        if(movie["id"] == id):
            movie["name"] = name
            movie["year"] = year
            movie["category"] = category
            return movie
    return {"No existe la pelicula"}

# Eliminar una pelicula
@app.delete("/movies/{id}", tags=["Movies"])
def delete_movie(id: int):
    for movie in movies:
        if(movie["id"] == id):
            movies.remove(movie)
            return {"message": "Pelicula eliminada correctamente"}
    return {"No existe la pelicula"}
La siguiente fue una forma en la que encontré que se podían implementar los métodos put y delete: ```js @app.put('/movies/{1}', tags=['movies']) def modify_movie( id: int, title: str = Body(), overview: str = Body(), year: str = Body(), rating: float = Body(), category: str = Body() ): for movie in movies: if movie['id'] == id: movie['title'] = title movie['overview'] = overview movie['year'] = year movie['rating'] = rating movie['category'] = category return movies @app.delete('/movies/{1}', tags=['movies']) def delete_movie(id: int): global movies movies = [ movie for movie in movies if movie['id'] != id] return movies ```