dinho1597 commited on
Commit
e410613
·
verified ·
1 Parent(s): 8875b0b

update api

Browse files
Files changed (6) hide show
  1. .dockerignore +24 -0
  2. .gitignore +17 -0
  3. Dockerfile +27 -0
  4. README.md +96 -12
  5. app.py +134 -0
  6. requirements.txt +3 -0
.dockerignore ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ignorar el entorno virtual de Python
2
+ venv/
3
+ .venv/
4
+
5
+ # Ignorar cachés de Python
6
+ __pycache__/
7
+ *.pyc
8
+ *.pyo
9
+ *.pyd
10
+
11
+ # Ignorar archivos específicos del editor o sistema operativo
12
+ .vscode/
13
+ .idea/
14
+ .DS_Store
15
+
16
+ # Ignorar archivos de entorno (¡muy importante para la seguridad!)
17
+ .env
18
+
19
+ # Ignorar el directorio de git
20
+ .git/
21
+ .gitignore
22
+
23
+ # Archivos de configuración de herramientas
24
+ .pytest_cache/
.gitignore ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ignorar el entorno virtual de Python
2
+ venv/
3
+ .venv/
4
+
5
+ # Ignorar cachés de Python
6
+ __pycache__/
7
+ *.pyc
8
+ *.pyo
9
+ *.pyd
10
+
11
+ # Ignorar archivos específicos del editor o sistema operativo
12
+ .vscode/
13
+ .idea/
14
+ .DS_Store
15
+
16
+ # Ignorar archivos de entorno (¡muy importante para la seguridad!)
17
+ .env
Dockerfile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile
2
+
3
+ # 1. Usar una imagen base oficial de Python
4
+ # Usamos una versión "slim" para que la imagen sea más ligera
5
+ FROM python:3.9-slim
6
+
7
+ # 2. Establecer el directorio de trabajo dentro del contenedor
8
+ WORKDIR /app
9
+
10
+ # 3. Copiar el archivo de requerimientos al directorio de trabajo
11
+ COPY requirements.txt .
12
+
13
+ # 4. Instalar las dependencias de Python
14
+ # --no-cache-dir reduce el tamaño de la imagen
15
+ RUN pip install --no-cache-dir -r requirements.txt
16
+
17
+ # 5. Copiar todo el código de la aplicación al directorio de trabajo
18
+ COPY . .
19
+
20
+ # 6. Exponer el puerto en el que se ejecutará la aplicación
21
+ # Hugging Face Spaces espera que la app se ejecute en el puerto 7860, pero con Docker se puede remapear.
22
+ # Usaremos el 8000 que es el estándar de uvicorn.
23
+ EXPOSE 8000
24
+
25
+ # 7. Comando para ejecutar la aplicación cuando se inicie el contenedor
26
+ # --host 0.0.0.0 es crucial para que sea accesible desde fuera del contenedor
27
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,12 +1,96 @@
1
- ---
2
- title: My Api Fastapi
3
- emoji: 🌖
4
- colorFrom: indigo
5
- colorTo: blue
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- short_description: Como tener una pi en la nubre, despliegue con fast api
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Mi API Completa con FastAPI
3
+ emoji: 🚀
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: docker
7
+ app_port: 8000
8
+ ---
9
+
10
+ # 🚀 Mi API Completa con FastAPI
11
+
12
+ Este es un Space de demostración para una API creada con FastAPI que incluye todos los métodos HTTP comunes.
13
+
14
+ La API se ejecuta dentro de un contenedor Docker y te permite gestionar una lista de ítems.
15
+
16
+ ## Documentación Interactiva de la API
17
+
18
+ FastAPI genera automáticamente una documentación interactiva. Puedes acceder a ella agregando `/docs` a la URL de este Space.
19
+
20
+ - **Swagger UI**: [URL_DE_TU_SPACE/docs](URL_DE_TU_SPACE/docs)
21
+ - **ReDoc**: [URL_DE_TU_SPACE/redoc](URL_DE_TU_SPACE/redoc)
22
+
23
+ ## Cómo usar los Endpoints
24
+
25
+ Puedes usar `curl` o cualquier cliente HTTP para interactuar con la API. Reemplaza `URL_DE_TU_SPACE` con la URL de tu aplicación.
26
+
27
+ ### `GET /items` - Obtener todos los ítems
28
+ ```bash
29
+ curl -X 'GET' 'URL_DE_TU_SPACE/items' -H 'accept: application/json'
30
+ ```
31
+
32
+ ### POST /items - Crear un nuevo ítem
33
+ ```bash
34
+
35
+ curl -X 'POST' \
36
+ 'URL_DE_TU_SPACE/items' \
37
+ -H 'accept: application/json' \
38
+ -H 'Content-Type: application/json' \
39
+ -d '{
40
+ "id": 3,
41
+ "name": "Monitor Ultrawide",
42
+ "description": "Un monitor de 34 pulgadas",
43
+ "price": 499.99
44
+ }'
45
+ ```
46
+ ### GET /items/{item_id} - Obtener un ítem por ID
47
+ ```bash
48
+
49
+ curl -X 'GET' 'URL_DE_TU_SPACE/items/1' -H 'accept: application/json'
50
+ PUT /items/{item_id} - Actualizar un ítem completamente
51
+ Bash
52
+
53
+ curl -X 'PUT' \
54
+ 'URL_DE_TU_SPACE/items/1' \
55
+ -H 'accept: application/json' \
56
+ -H 'Content-Type: application/json' \
57
+ -d '{
58
+ "id": 1,
59
+ "name": "Laptop Gamer",
60
+ "description": "Un potente portátil con RTX 4080",
61
+ "price": 2500.00
62
+ }'
63
+ ```
64
+ ### DELETE /items/{item_id} - Eliminar un ítem
65
+ ```bash
66
+
67
+ curl -X 'DELETE' 'URL_DE_TU_SPACE/items/2' -H 'accept: application/json'
68
+ ```
69
+ ### Cómo Subirlo a Hugging Face Spaces
70
+
71
+ 1. **Crea una cuenta** en [Hugging Face](https://huggingface.co/).
72
+ 2. Ve a tu perfil y haz clic en **"New Space"**.
73
+ 3. Dale un **nombre** a tu Space (por ejemplo, `mi-api-fastapi`).
74
+ 4. Elige una **licencia**.
75
+ 5. Selecciona **"Docker"** como el SDK del Space.
76
+ 6. Haz clic en **"Create Space"**.
77
+ 7. Sigue las instrucciones para subir tus archivos. La forma más sencilla es:
78
+ * Ir a la pestaña **"Files and versions"**.
79
+ * Hacer clic en **"Add file"** y luego **"Upload files"**.
80
+ * Arrastra y suelta los cuatro archivos (`main.py`, `requirements.txt`, `Dockerfile`, `README.md`) que creaste.
81
+ * Escribe un mensaje de commit (ej. "Versión inicial") y haz clic en **"Commit changes to main"**.
82
+
83
+ Hugging Face detectará tu `Dockerfile` y `README.md`, construirá la imagen y desplegará tu aplicación. ¡En unos minutos, tu API estará en línea y lista para usar!
84
+ ### Probar en el local
85
+ python -m venv venv
86
+ .\venv\Scripts\Activate.ps1
87
+ pip install -r requirements.txt
88
+ uvicorn main:app --reload
89
+ http://127.0.0.1:8000/docs
90
+
91
+ ### Docker
92
+ docker build -t my_fast_api .
93
+ docker run -d -p 8000:8000 --name mi-api-container my_fast_api
94
+
95
+ http://127.0.0.1:8000/docs
96
+ http://127.0.0.1:8000/items
app.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py
2
+ from fastapi import FastAPI, HTTPException, status
3
+ from pydantic import BaseModel
4
+ from typing import Optional, List
5
+
6
+ # --- Modelos de Datos con Pydantic ---
7
+ # Pydantic se encarga de la validación y serialización de datos
8
+
9
+ class Item(BaseModel):
10
+ """Modelo base para un ítem. Todos los campos son requeridos."""
11
+ id: int
12
+ name: str
13
+ description: Optional[str] = None
14
+ price: float
15
+
16
+ class UpdateItem(BaseModel):
17
+ """Modelo para actualizar un ítem. Todos los campos son opcionales."""
18
+ name: Optional[str] = None
19
+ description: Optional[str] = None
20
+ price: Optional[float] = None
21
+
22
+ # --- Instancia de la Aplicación FastAPI ---
23
+ app = FastAPI(
24
+ title="API de Ejemplo Completa",
25
+ description="Una API de ejemplo con todos los métodos HTTP para demostrar FastAPI, Docker y Hugging Face Spaces.",
26
+ version="1.0.0",
27
+ )
28
+
29
+ # --- "Base de Datos" en Memoria ---
30
+ # Un diccionario simple para simular una base de datos.
31
+ db = {
32
+ 1: Item(id=1, name="Laptop", description="Un potente portátil para desarrollo", price=1200.50),
33
+ 2: Item(id=2, name="Teclado Mecánico", description="Un teclado con switches Cherry MX Blue", price=150.75),
34
+ }
35
+
36
+ # --- Endpoints de la API ---
37
+
38
+ @app.get("/", tags=["Root"])
39
+ def read_root():
40
+ """Endpoint principal de bienvenida."""
41
+ return {"message": "¡Bienvenido a la API de ejemplo con FastAPI!"}
42
+
43
+ # --- Métodos para la colección de ítems ---
44
+
45
+ @app.get("/items", response_model=List[Item], tags=["Items"])
46
+ def get_all_items():
47
+ """
48
+ GET: Obtiene una lista de todos los ítems en la base de datos.
49
+ """
50
+ return list(db.values())
51
+
52
+ @app.post("/items", response_model=Item, status_code=status.HTTP_201_CREATED, tags=["Items"])
53
+ def create_item(item: Item):
54
+ """
55
+ POST: Crea un nuevo ítem.
56
+ El ID del ítem en el cuerpo de la petición debe ser único.
57
+ """
58
+ if item.id in db:
59
+ raise HTTPException(
60
+ status_code=status.HTTP_400_BAD_REQUEST,
61
+ detail=f"El ítem con ID {item.id} ya existe."
62
+ )
63
+ db[item.id] = item
64
+ return item
65
+
66
+ # --- Métodos para un ítem específico ---
67
+
68
+ @app.get("/items/{item_id}", response_model=Item, tags=["Items"])
69
+ def get_item_by_id(item_id: int):
70
+ """
71
+ GET: Obtiene un ítem específico por su ID.
72
+ """
73
+ if item_id not in db:
74
+ raise HTTPException(
75
+ status_code=status.HTTP_404_NOT_FOUND,
76
+ detail=f"El ítem con ID {item_id} no fue encontrado."
77
+ )
78
+ return db[item_id]
79
+
80
+ @app.put("/items/{item_id}", response_model=Item, tags=["Items"])
81
+ def update_item_completely(item_id: int, item: Item):
82
+ """
83
+ PUT: Actualiza un ítem completamente.
84
+ Reemplaza toda la información del ítem existente con la nueva.
85
+ """
86
+ if item_id not in db:
87
+ raise HTTPException(
88
+ status_code=status.HTTP_404_NOT_FOUND,
89
+ detail=f"El ítem con ID {item_id} no fue encontrado."
90
+ )
91
+ # El ID no debe cambiar en una operación PUT
92
+ if item_id != item.id:
93
+ raise HTTPException(
94
+ status_code=status.HTTP_400_BAD_REQUEST,
95
+ detail="El ID del ítem en la URL no coincide con el ID en el cuerpo de la petición."
96
+ )
97
+ db[item_id] = item
98
+ return db[item_id]
99
+
100
+ @app.patch("/items/{item_id}", response_model=Item, tags=["Items"])
101
+ def update_item_partially(item_id: int, item_update: UpdateItem):
102
+ """
103
+ PATCH: Actualiza un ítem parcialmente.
104
+ Solo actualiza los campos proporcionados en el cuerpo de la petición.
105
+ """
106
+ if item_id not in db:
107
+ raise HTTPException(
108
+ status_code=status.HTTP_404_NOT_FOUND,
109
+ detail=f"El ítem con ID {item_id} no fue encontrado."
110
+ )
111
+
112
+ stored_item_data = db[item_id].dict()
113
+ update_data = item_update.dict(exclude_unset=True) # Obtiene solo los campos que se enviaron
114
+
115
+ updated_item_data = stored_item_data.copy()
116
+ updated_item_data.update(update_data)
117
+
118
+ db[item_id] = Item(**updated_item_data)
119
+ return db[item_id]
120
+
121
+ @app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT, tags=["Items"])
122
+ def delete_item(item_id: int):
123
+ """
124
+ DELETE: Elimina un ítem por su ID.
125
+ Devuelve un código 204 sin contenido si tiene éxito.
126
+ """
127
+ if item_id not in db:
128
+ raise HTTPException(
129
+ status_code=status.HTTP_404_NOT_FOUND,
130
+ detail=f"El ítem con ID {item_id} no fue encontrado."
131
+ )
132
+ del db[item_id]
133
+ # No se devuelve contenido, solo el código de estado 204
134
+ return
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # requirements.txt
2
+ fastapi
3
+ uvicorn[standard]