committed by
GitHub
2 changed files with 334 additions and 0 deletions
@ -0,0 +1,333 @@ |
|||||
|
# Primeros pasos |
||||
|
|
||||
|
Un archivo muy simple de FastAPI podría verse así: |
||||
|
|
||||
|
```Python |
||||
|
{!../../../docs_src/first_steps/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
Copia eso a un archivo `main.py`. |
||||
|
|
||||
|
Corre el servidor en vivo: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ uvicorn main:app --reload |
||||
|
|
||||
|
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
||||
|
<span style="color: green;">INFO</span>: Started reloader process [28720] |
||||
|
<span style="color: green;">INFO</span>: Started server process [28722] |
||||
|
<span style="color: green;">INFO</span>: Waiting for application startup. |
||||
|
<span style="color: green;">INFO</span>: Application startup complete. |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
!!! note "Nota" |
||||
|
El comando `uvicorn main:app` se refiere a: |
||||
|
|
||||
|
* `main`: el archivo `main.py` (el "módulo" de Python). |
||||
|
* `app`: el objeto creado dentro de `main.py` con la línea `app = FastAPI()`. |
||||
|
* `--reload`: hace que el servidor se reinicie cada vez que cambia el código. Úsalo únicamente para desarrollo. |
||||
|
|
||||
|
En el output, hay una línea que dice más o menos: |
||||
|
|
||||
|
```hl_lines="4" |
||||
|
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
||||
|
``` |
||||
|
|
||||
|
Esa línea muestra la URL dónde se está sirviendo tu app en tu maquina local. |
||||
|
|
||||
|
### Revísalo |
||||
|
|
||||
|
Abre tu navegador en <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>. |
||||
|
|
||||
|
Verás la respuesta en JSON: |
||||
|
|
||||
|
```JSON |
||||
|
{"message": "Hello World"} |
||||
|
``` |
||||
|
|
||||
|
### Documentación interactiva de la API |
||||
|
|
||||
|
Ahora dirígete a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. |
||||
|
|
||||
|
Ahí verás la documentación automática e interactiva de la API (proveída por <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>): |
||||
|
|
||||
|
 |
||||
|
|
||||
|
### Documentación alternativa de la API |
||||
|
|
||||
|
Ahora, dirígete a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>. |
||||
|
|
||||
|
Aquí verás la documentación automática alternativa (proveída por <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>): |
||||
|
|
||||
|
 |
||||
|
|
||||
|
### OpenAPI |
||||
|
|
||||
|
**FastAPI** genera un "schema" con toda tu API usando el estándar para definir APIs, **OpenAPI**. |
||||
|
|
||||
|
#### "Schema" |
||||
|
|
||||
|
Un "schema" es una definición o descripción de algo. No es el código que la implementa, sino solo una descripción abstracta. |
||||
|
|
||||
|
#### "Schema" de la API |
||||
|
|
||||
|
En este caso, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> es una especificación que dicta como se debe definir el schema de tu API. |
||||
|
|
||||
|
La definición del schema incluye los paths de tu API, los parámetros que podría recibir, etc. |
||||
|
|
||||
|
#### "Schema" de datos |
||||
|
|
||||
|
El concepto "schema" también se puede referir a la forma de algunos datos, como un contenido en formato JSON. |
||||
|
|
||||
|
En ese caso haría referencia a los atributos del JSON, los tipos de datos que tiene, etc. |
||||
|
|
||||
|
#### OpenAPI y JSON Schema |
||||
|
|
||||
|
OpenAPI define un schema de API para tu API. Ese schema incluye definiciones (o "schemas") de los datos enviados y recibidos por tu API usando **JSON Schema**, el estándar para los schemas de datos en JSON. |
||||
|
|
||||
|
#### Revisa el `openapi.json` |
||||
|
|
||||
|
Si sientes curiosidad por saber cómo se ve el schema de OpenAPI en bruto, FastAPI genera automáticamente un (schema) JSON con la descripción de todo tu API. |
||||
|
|
||||
|
Lo puedes ver directamente en: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>. |
||||
|
|
||||
|
Esto te mostrará un JSON que comienza con algo como: |
||||
|
|
||||
|
```JSON |
||||
|
{ |
||||
|
"openapi": "3.0.2", |
||||
|
"info": { |
||||
|
"title": "FastAPI", |
||||
|
"version": "0.1.0" |
||||
|
}, |
||||
|
"paths": { |
||||
|
"/items/": { |
||||
|
"get": { |
||||
|
"responses": { |
||||
|
"200": { |
||||
|
"description": "Successful Response", |
||||
|
"content": { |
||||
|
"application/json": { |
||||
|
|
||||
|
|
||||
|
|
||||
|
... |
||||
|
``` |
||||
|
|
||||
|
#### ¿Para qué se usa OpenAPI? |
||||
|
|
||||
|
El schema de OpenAPI es lo que alimenta a los dos sistemas de documentación interactiva incluidos. |
||||
|
|
||||
|
También hay docenas de alternativas, todas basadas en OpenAPI. Podrías añadir fácilmente cualquiera de esas alternativas a tu aplicación construida con **FastAPI**. |
||||
|
|
||||
|
También podrías usarlo para generar código automáticamente, para los clientes que se comunican con tu API. Por ejemplo, frontend, móvil o aplicaciones de IoT. |
||||
|
|
||||
|
## Repaso, paso a paso |
||||
|
|
||||
|
### Paso 1: importa `FastAPI` |
||||
|
|
||||
|
```Python hl_lines="1" |
||||
|
{!../../../docs_src/first_steps/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
`FastAPI` es una clase de Python que provee toda la funcionalidad para tu API. |
||||
|
|
||||
|
!!! note "Detalles Técnicos" |
||||
|
`FastAPI` es una clase que hereda directamente de `Starlette`. |
||||
|
|
||||
|
También puedes usar toda la funcionalidad de <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>. |
||||
|
|
||||
|
### Paso 2: crea un "instance" de `FastAPI` |
||||
|
|
||||
|
```Python hl_lines="3" |
||||
|
{!../../../docs_src/first_steps/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
Aquí la variable `app` será un instance de la clase `FastAPI`. |
||||
|
|
||||
|
Este será el punto de interacción principal para crear todo tu API. |
||||
|
|
||||
|
Esta `app` es la misma a la que nos referimos cuando usamos el comando de `uvicorn`: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ uvicorn main:app --reload |
||||
|
|
||||
|
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Si creas un app como: |
||||
|
|
||||
|
```Python hl_lines="3" |
||||
|
{!../../../docs_src/first_steps/tutorial002.py!} |
||||
|
``` |
||||
|
|
||||
|
y lo guardas en un archivo `main.py`, entonces ejecutarías `uvicorn` así: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ uvicorn main:my_awesome_api --reload |
||||
|
|
||||
|
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
### Paso 3: crea un *operación de path* |
||||
|
|
||||
|
#### Path |
||||
|
|
||||
|
"Path" aquí se refiere a la última parte de una URL comenzando desde el primer `/`. |
||||
|
|
||||
|
Entonces, en una URL como: |
||||
|
|
||||
|
``` |
||||
|
https://example.com/items/foo |
||||
|
``` |
||||
|
|
||||
|
...el path sería: |
||||
|
|
||||
|
``` |
||||
|
/items/foo |
||||
|
``` |
||||
|
|
||||
|
!!! info "Información" |
||||
|
Un "path" también se conoce habitualmente como "endpoint", "route" o "ruta". |
||||
|
|
||||
|
Cuando construyes una API, el "path" es la manera principal de separar los <abbr title="en inglés: separation of concerns">"intereses"</abbr> y los "recursos". |
||||
|
|
||||
|
#### Operación |
||||
|
|
||||
|
"Operación" aquí se refiere a uno de los "métodos" de HTTP. |
||||
|
|
||||
|
Uno como: |
||||
|
|
||||
|
* `POST` |
||||
|
* `GET` |
||||
|
* `PUT` |
||||
|
* `DELETE` |
||||
|
|
||||
|
...y los más exóticos: |
||||
|
|
||||
|
* `OPTIONS` |
||||
|
* `HEAD` |
||||
|
* `PATCH` |
||||
|
* `TRACE` |
||||
|
|
||||
|
En el protocolo de HTTP, te puedes comunicar con cada path usando uno (o más) de estos "métodos". |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
Cuando construyes APIs, normalmente usas uno de estos métodos específicos de HTTP para realizar una acción específica. |
||||
|
|
||||
|
Normalmente usas: |
||||
|
|
||||
|
* `POST`: para crear datos. |
||||
|
* `GET`: para leer datos. |
||||
|
* `PUT`: para actualizar datos. |
||||
|
* `DELETE`: para borrar datos. |
||||
|
|
||||
|
Así que en OpenAPI, cada uno de estos métodos de HTTP es referido como una "operación". |
||||
|
|
||||
|
Nosotros también los llamaremos "**operación**". |
||||
|
|
||||
|
#### Define un *decorador de operaciones de path* |
||||
|
|
||||
|
```Python hl_lines="6" |
||||
|
{!../../../docs_src/first_steps/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
El `@app.get("/")` le dice a **FastAPI** que la función que tiene justo debajo está a cargo de manejar los requests que van a: |
||||
|
|
||||
|
* el path `/` |
||||
|
* usando una <abbr title="an HTTP GET method">operación <code>get</code></abbr> |
||||
|
|
||||
|
!!! info "Información sobre `@decorator`" |
||||
|
Esa sintaxis `@algo` se llama un "decorador" en Python. |
||||
|
|
||||
|
Lo pones encima de una función. Es como un lindo sombrero decorado (creo que de ahí salió el concepto). |
||||
|
|
||||
|
Un "decorador" toma la función que tiene debajo y hace algo con ella. |
||||
|
|
||||
|
En nuestro caso, este decorador le dice a **FastAPI** que la función que está debajo corresponde al **path** `/` con una **operación** `get`. |
||||
|
|
||||
|
Es el "**decorador de operaciones de path**". |
||||
|
|
||||
|
También puedes usar las otras operaciones: |
||||
|
|
||||
|
* `@app.post()` |
||||
|
* `@app.put()` |
||||
|
* `@app.delete()` |
||||
|
|
||||
|
y las más exóticas: |
||||
|
|
||||
|
* `@app.options()` |
||||
|
* `@app.head()` |
||||
|
* `@app.patch()` |
||||
|
* `@app.trace()` |
||||
|
|
||||
|
!!! tip "Consejo" |
||||
|
Tienes la libertad de usar cada operación (método de HTTP) como quieras. |
||||
|
|
||||
|
**FastAPI** no impone ningún significado específico. |
||||
|
|
||||
|
La información que está presentada aquí es una guía, no un requerimiento. |
||||
|
|
||||
|
Por ejemplo, cuando usas GraphQL normalmente realizas todas las acciones usando únicamente operaciones `POST`. |
||||
|
|
||||
|
### Paso 4: define la **función de la operación de path** |
||||
|
|
||||
|
Esta es nuestra "**función de la operación de path**": |
||||
|
|
||||
|
* **path**: es `/`. |
||||
|
* **operación**: es `get`. |
||||
|
* **función**: es la función debajo del "decorador" (debajo de `@app.get("/")`). |
||||
|
|
||||
|
```Python hl_lines="7" |
||||
|
{!../../../docs_src/first_steps/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
Esto es una función de Python. |
||||
|
|
||||
|
Esta función será llamada por **FastAPI** cada vez que reciba un request en la URL "`/`" usando una operación `GET`. |
||||
|
|
||||
|
En este caso es una función `async`. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
También podrías definirla como una función normal, en vez de `async def`: |
||||
|
|
||||
|
```Python hl_lines="7" |
||||
|
{!../../../docs_src/first_steps/tutorial003.py!} |
||||
|
``` |
||||
|
|
||||
|
!!! note "Nota" |
||||
|
Si no sabes la diferencia, revisa el [Async: *"¿Tienes prisa?"*](../async.md#in-a-hurry){.internal-link target=_blank}. |
||||
|
|
||||
|
### Paso 5: devuelve el contenido |
||||
|
|
||||
|
```Python hl_lines="8" |
||||
|
{!../../../docs_src/first_steps/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
Puedes devolver `dict`, `list`, valores singulares como un `str`, `int`, etc. |
||||
|
|
||||
|
También puedes devolver modelos de Pydantic (ya verás más sobre esto más adelante). |
||||
|
|
||||
|
Hay muchos objetos y modelos que pueden ser convertidos automáticamente a JSON (incluyendo ORMs, etc.). Intenta usar tus favoritos, es muy probable que ya tengan soporte. |
||||
|
|
||||
|
## Repaso |
||||
|
|
||||
|
* Importa `FastAPI`. |
||||
|
* Crea un instance de `app`. |
||||
|
* Escribe un **decorador de operación de path** (como `@app.get("/")`). |
||||
|
* Escribe una **función de la operación de path** (como `def root(): ...` arriba). |
||||
|
* Corre el servidor de desarrollo (como `uvicorn main:app --reload`). |
Loading…
Reference in new issue