No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Nombre y descripci贸n de una path operation

12/25
Recursos

Aportes 21

Preguntas 1

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

creo que me acabo de dar cuenta de lo aburrido que es hacer la documentaci贸n xd

Los aspectos para hacer el docstring de las path operations:

  • T铆tulo

  • Descripci贸n

  • Par谩metros

  • Resultado

VS Code tiene una extensi贸n que genera la estructura de un Docstring autom谩ticamente. Se llama:
Python Docstring Generator.
Tambi茅n anexo el link https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring

Reconozco que Github Copilot me ayud贸 un poco en la labor.

Es un poco tedioso realizar la documentaci贸n, pero haciendo la labor puedes entender much铆simo mejor tu mismo c贸digo, es un muy buen ejercicio para comprender a totalidad tu propio c贸digo.

Aqu铆 se listan los principales formatos de Docstrings que existe. Yo por lo general utilizo el recomendado por Google, aunque noto que no es del todo 鈥Markdown friendly鈥, asi que le hago unos leves cambios.

Dejo alguno algunos de mis resultados por aqu铆, se acepta feedback 馃槃

Create person

Validate person

Update person

Un poco largo, esto es lo que hice:

@app.get(
    path = "/",
    status_code = status.HTTP_200_OK,
    tags = ["Home"],
    summary = "Home page",
    ) #path operation decorator
def home(): #path operation function
    """
    Home page of the API

    This path returns the home page of the API.

    No parameters are required.
    """
    return {"message": "Hello World, I'm using Python and FastAPI 馃悕"}


# Request and Response Body

@app.post(
    path = "/person/new",
    response_model = PersonOut,
    status_code = status.HTTP_201_CREATED,
    tags = ["Persons"],
    summary = "Create Person in the app"
    )
def create_person(person: Person = Body(...)): # Los '...' indican que es obligatorio
    """
    Create Person

    This path operation creates a person in the app and save the information in the database

    Parameters:
    - Request body parameter:
        - **person: Person** -> A person model with first name, last name, age, hair color, is married, email, payment card number, favorite color and password.

    Returns a person model with first name, last name, age, hair color, is married, email, payment card number, favorite color and password.
    """
    return person


# Validaciones: Query Parameters

@app.get(
    path = "/person/detail",
    status_code = status.HTTP_200_OK,
    tags = ["Persons"],
    summary = "Get Person detail",
    )
def show_person(
    name: Optional[str] = Query(
        None,
        min_length=1,
        max_length=50,
        title="Person name.",
        description="This is the person name. It's between 1 and 50 characters.",
        example="Miguel"
        ),
    age: int = Query(
        ...,
        title="Person age",
        description="This is the person age. It's required",
        gt=0,
        example=23
        )
):
    """
    Show Person

    This path operation shows the person's name and age in the app from the database.

    Parameters:
    - Query parameter:
        - **name: str** -> This is the person name. It's between 1 and 50 characters.
        - **age: int** -> This is the person age. It's required.

    Returns a JSON with the person's name and age.
    """
    return {"name": name, "age": age}


# Validaciones: Path Parameters

persons = [1,2,3,4,5]

@app.get(
    path = "/person/detail/{person_id}",
    status_code = status.HTTP_200_OK,
    tags = ["Persons"],
    summary = "Get Person ID",
    )
def show_person(
    person_id: int = Path(
        ...,
        gt=0,
        title="Person ID.",
        description="This is the person ID. It's required and must be greater than 0.",
        example=1
    )
):
    """
    Show Person

    This path operation shows the person's ID in the app from the database.

    Parameters:
    - Path parameter:
        - **person_id: int** -> This is the person ID. It's required and must be greater than 0.

    Returns a JSON with the person's ID.
    """
    if person_id not in persons:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Person not found"
        )
    return {"person_id": person_id}


# Validations: Request Body

@app.put(
    path = "/person/{person_id}",
    status_code = status.HTTP_204_NO_CONTENT,
    tags = ["Persons"],
    summary = "Update Person",
    )
def update_person(
    person_id: int = Path(
        ...,
        title="Person ID.",
        description="This is the person ID.",
        gt=0,
        example=123
    ),
    person: Person = Body(...),
    location: Location = Body(...),
):
    """
    Update Person

    This path operation updates the person's information from the database.

    Parameters:
    - Path parameter:
        - **person_id: int** -> This is the person ID. It's required and must be greater than 0.
    - Request body parameter:
        - **person: Person** -> A person model with first name, last name, age, hair color, is married, email, payment card number, favorite color and password.
        - **location: Location** -> A location model with city, state and country.

    Returns a JSON with the person's ID, its model and location.
    """
    return {
        "person_id": person_id,
        "person:": person,
        "location": location,
    }

#! Para formularios
@app.post(
    path = "/login",
    response_model = LoginOut,
    status_code = status.HTTP_200_OK,
    tags = ["Persons"],
    summary = "Login",
)
def login(username: str = Form(...), password: str = Form(...)):
    """
    User login

    This path operation allows you to login in the app.

    Parameters:
    - Request body parameter:
        - **username: str** -> This is the username to enter in the form. It's required.
        - **password: str** -> This is the password to enter in the form. It's required.

    Returns a JSON with the username and a message.
    """
    return LoginOut(username=username) #* Regresa un Dictionary o bien, un JSON


#! Cookies and Headers Parameters
@app.post(
    path = "/contact",
    status_code = status.HTTP_200_OK,
    tags = ["Contact"],
    summary = "Contact",
)
def contact(
    first_name: str = Form(
        ...,
        max_length = 20,
        min_length = 1,
    ),
    last_name: str = Form(
        ...,
        max_length = 20,
        min_length = 1,
    ),
    email: EmailStr = Form(...),
    message: str = Form(
        ...,
        min_length = 20,
    ),
    user_agent: Optional[str] = Header(default=None),
    ads: Optional[str] = Cookie(default=None),
):
    """
    Contact

    This path operation allows the user to contact the company.

    Parameters:
    - user_agent: The browser that the user is using.
    - ads: The cookies that this website uses.
    - Request body parameter:
        - **first_name: str** -> This is the first name to enter in the form. It's required.
        - **last_name: str** -> This is the last name to enter in the form. It's required.
        - **email: EmailStr** -> This is the email to enter in the form. It's required.
        - **message: str** -> This is the message to enter in the form. It's required.

    """
    return user_agent


#! Files
@app.post(
    path = "/post-image",
    status_code = status.HTTP_201_CREATED,
    tags = ["Images"],
    summary = "Post Image",
)
def post_image(
    image: UploadFile = File(...)
):
    """
    Post image

    This path operation allows you to post an image in the app to the database.

    Parameters:
    - Request body parameter:
        - **image: UploadFile** -> This is the image to upload. It's required.

    Returns a JSON with the image's name, format and size in kb.
    """
    return {
        "Filename": image.filename,
        "Format": image.content_type,
        "Size(kb)": round(len(image.file.read())/1024, ndigits=2),
    }

Va tomando forma
![](

驴Qu茅 es un docstring en Python?

Es un String literal de toda la vida que ocurre como el primer statement en el m贸dulo, funci贸n, clase o m茅todo definido. En este caso con fastApi autom谩ticamente podemos ver los docstrings en la documentaci贸n interactiva, pero si quisi茅ramos ver el docstring cualquiera podemos usar el m茅todo聽doc. Un ejemplo ser铆a:

def nothing(self):
	''' This function do nothing'''
	pass
print(nothing.__doc__)
// El resultado ser铆a This function do nothing

Al final su func铆贸n es la de documentar el c贸digo de cada funci贸n y cada clase.

# [Person Detail]

This path operation show a person in the app

### Parameters
	- Request body parameter: 
		- **name: str** -> The name of person
        	- **age: int** -> The age of person
        	- **email: EmailStr** -> The email of person
### Returns
A name and age

Yo utilizo esta extensi贸n de vsc , aqu铆

ufff excelente ajajjaa genial genial.

Mi c贸digo

@app.get(
    path='/',
    status_code=status.HTTP_200_OK,
    tags=['Home']
    )
def home():
    """
    Home Page
    
    This Path operation shows a JSON message with keys: "Hello" and "world" as values.
    
    Parameters:
    - This function doesn't receive parameters

    Returns a JSON with key: "hello", value: "world"
    """
    return {'Hello': 'World'}

# Request and response body

@app.post(
    path='/person/new', 
    response_model=Person,
    status_code=status.HTTP_201_CREATED,
    tags=['Persons'],
    summary='Create Persons in the app'
    )
def create_person(
    person: Person = Body(...)
    ):
    """
    Create Person
    
    This Path operation creates a person in the app and saves the information in the database
    
    Parameters:
    - Request body parameter
        - **person: Person** -> A person model with first name, last name, birthday, hair_color, is_married
    
    Returns a person model with first name, last name, birthday, hair_color, marital_status
    """
    return person

# Validations: Query Parameters
# min_length and max_length both are query validators

@app.get(
    path='/person/detail',
    status_code=status.HTTP_200_OK,
    tags=['Persons']
    )
def show_person(
    name: Optional[str] = Query(
        default=None,
         min_length=1,
        max_length=50,
        title='Person Name',
        description='This is the person name, It\'s between 1 and 50 characters',
        example='Rocio'
        ),
    born_day: Optional[date_type] = Query(
        default= None,
        title='Person Age',
        description='This is the person age. It\'s required',
        example='2022-05-08'
        ),
):
    """
    Show Person
    
    This Path operation Shows a person in the app
    
    Parameters:
    - Request body parameter
        - **name: Str** -> A optional person name
        - **born_day: Date_type** A optional birthday

    Returns a person's data with first name, birthday
    """
    return {name: born_day}

# Validations: Path parameters

persons = [1, 2, 3, 4, 5]

@app.get(
    path='/person/detail{person_id}',
    status_code=status.HTTP_200_OK,
    tags=['Persons']
    )
def show_person(
    person_id: int = Path(
        ...,
        gt=0,
        title='User id',
        description='This is the User Id, It\'s required',
        example=3
        )
):
    """
    Show Person
    
    This Path operation validates if a person exists in the database
    
    Parameters:
    - Request body parameter
        - **id: int** -> A person id
    
    Returns a message with id, message if it exists or doesn't exist
    """
    if person_id not in persons:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail='This id doesn\'t exist'
        )
    return {person_id: 'It exists!'}


# Validations: Request Body

@app.put(
    path='/person/{person_id}',
    status_code=status.HTTP_200_OK,
    tags=['Persons']
    )
def update_person(
    person_id: int = Path(
        ...,
        title='Person ID',
        description='This is the person ID',
        gt=0,
        example=3
    ),
    person: Person = Body(...),
    location: Location = Body(...)
):
    """
    Update Person

    Gets a person id, Person Model with the first name, last name, birthday, hair color, marital status and update information in a database
    
    Parameters:
    - Request body parameter
        - **person_id: int** -> an id from an user
        - **person: Person** -> A person model with first name, last name, birthday, hair color, marrital status
        - **location: Location** -> A location Model that receives an city, country and status
    
    Returns a New Person model with first name, last name, birthday, hair color, married status, and Location with city, status, and country
    """
    result = dict(person)
    result.update(dict(location))
    return result

# Forms

@app.post(
    path='/login',
    response_model=LoginOut,
    status_code=status.HTTP_200_OK,
    tags=['Forms']
    )
def login(
    Username: str = Form(...),
    Password: str = Form(...)
    ):
    """
    Login

    This Path operation gets the username and password to validate the user account
    
    Parameters:
    - Request Body
        - **Username: str** -> Obligatory Form model
        - **Password: str** -> Obligatory Form model
    
    returns a LoginOut model with a username
    """
    return LoginOut(username=Username)

# Coockie & Header

@app.post(
    path='/contact',
    status_code=status.HTTP_200_OK,
    tags=['Support']
)
def contact(
    first_name: str = Form(
        ...,
        max_length=20,
        min_length=1,
    ),
    last_name: str = Form(
        ...,
        max_length=20,
        min_length=1,
    ),
    email: EmailStr = Form(
        ...,
    ),
    message: str = Form(
        ...,
        min_length=20
    ),
    user_agent: Optional[str] = Header(default=None),
    ads: Optional[str] = Cookie(default=None),
):
    """
    Contact

    This Path operation gets information to contact developers.
    
    Parameters:
    - Request Body:
        - **First_name: str** -> Obligatory Form Object, Person's last name
        - **Last_name: str** -> Obligatory Form Object. Person's last name
        - **Email: EmailStr** -> Person's email adress, Obligatory
        - **message: str** -> Form obligatory object, gets user message
        - **user_agent: Optional[str]** -> gets parameter HEADER.
        - **ads: Optional[str]** -> Cookie's from user
    
    Returns user_agent model with first name, last name, email, header, cookies
    """
    return user_agent

@app.post(
    path='/post-image',
    status_code=status.HTTP_202_ACCEPTED,
    tags=['Upload']
    )
def post_image(
    image: UploadFile = File(...),
):
    """
    Post Image

    This Path Operator gets a user image with Filename, size, and format.

    Parameters:
    - Request Body:
        - **Image: UploadFile** -> Gets an obligatory user image

    returns a JSON of an image with filename, format, and size.
    """
    return {
        'Filename': image.filename,
        'Format': image.content_type,
        'Size(kb)': round((len(image.file.read()) / 1024), ndigits=2)
    }

Quiero que coloques este docstring en todas las path operations鈥

El c贸digo completo desde que iniciamos:

#Python
from typing import Optional
from enum import Enum

#Pydantic
from pydantic import BaseModel
from pydantic import Field
from pydantic import EmailStr

#FastAPI
from fastapi import FastAPI
from fastapi import status
from fastapi import HTTPException
from fastapi import Body, Query, Path, Form, Header, Cookie, UploadFile, File

app = FastAPI()

# Models

class HairColor(Enum):
    white = "white"
    brown = "brown"
    black = "black"
    blonde = "blonde"
    red = "red"

class Location(BaseModel):
    city: str
    state: str
    country: str

class PersonBase(BaseModel):
    first_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Miguel"
        )
    last_name: str = Field(
        ...,
        min_length=1,
        max_length=50,
        example="Torres"
    )
    age: int = Field(
        ...,
        gt=0,
        le=115,
        example=48
    )
    hair_color: Optional[HairColor] = Field(default=None, example="red")
    is_married: Optional[bool] = Field(default=None, example=False)

class Person(PersonBase):
    password: str = Field(..., min_length=8)

    # class Config:
    #     schema_extra = {
    #         "example": {
    #             "first_name": "Facundo",
    #             "last_name": "Garc铆a Martoni",
    #             "age": 21,
    #             "hair_color": "blonde",
    #             "is_married": False
    #         }
    #     }


class PersonOut(PersonBase):
    pass

class LoginOut(BaseModel):
    username: str = Field(..., max_length=20, example="miguel2022")
    message: str = Field(default="Login successfully!")

# Home

@app.get(
    path="/",
    status_code=status.HTTP_200_OK,
    tags=["Home"],
    summary="Homepage"
    )
def home():
    """
    Title: This is Home

    Description: This path operation addresses us to Home

    Parameters: No parameters so far

    Result: It returns us to Home
    """
    return {
        "Hello": "world",
        "Message": "Scaling up izipizicourse.com",
        "Author": "Emanuel Castillo",
        "Company": "mylearny.com"
    }

# Request and Response Body

@app.post(
    path="/person/new",
    response_model=PersonOut,
    status_code=status.HTTP_201_CREATED,
    tags=["Persons"],
    summary="Creates a person in the APP"
    )
def create_person(person: Person = Body(...)):
    """
    Title: It creates a Person

    Description: This path operation creates a person in the app and saves the information in the database

    Parameters: 
    - Request body parameter:
        - **person: Person** -> A person model with first name, last name, age, hair color and marital status

    Result: it returns a person model with first name, last name, age, hair color and marital status
    """
    return person

# Validaciones: Query Parameters

@app.get(
    path="/person/detail",
    status_code=status.HTTP_200_OK,
    tags=["Persons"],
    summary="It shows a name and their age"
    )
def show_person(
    name: Optional[str] = Query(
        None,
        min_length=1,
        max_length=50,
        title="Person Name",
        description="This is the person name. It's between 1 and 50 characters.",
        example="Roc铆o"
        ),
    age: str = Query(
        ...,
        title="Person Age",
        description="This is the person age. It's required.",
        example=25
        )
):
    """
    Title: It shows some name with their respective age

    Description: This path operation shows a name with their age in the app

    Parameters:
        - Request query parameter:
            - **name: age**

    Result: It shows a name with their age
    """
    return { name: age }

# Validaciones: Path Parameters

persons = [1, 2, 3, 4, 5]

@app.get(
    path="/person/detail/{person_id}",
    status_code=status.HTTP_200_OK,
    tags=["Persons"],
    summary=f"It shows whether a person exists among our values in {persons}"
    )
def show_person(
    person_id: int = Path(
        ...,
        gt=0,
        example=123
        )
):
    """
    Title: It shows whether a person exists in a list

    Description: This path operation shows whether a person exists among a list called <<persons>>

    Parameters:
        - Request path parameter:
            - **person_id** -> A value inside the <<persons>> list

    Result: It returns a bool whether the person_id is inside the list or not.
    """
    if person_id not in persons:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="This person doesn't exist!!!"
        )

    return { person_id: "It exists" }

# Validaciones: Request Body.

@app.put(
    path="/person/{person_id}",
    status_code=status.HTTP_201_CREATED,
    tags=["Persons"],
    summary="It updates a person"
    )
def update_person(
    person_id: int = Path(
        ...,
        title="Person ID",
        description="This is the person ID",
        gt=0,
        example=123
    ),
    person: Person = Body(...),
    # location: Location = Body(...)
):
    """
    Title: It updates a person

    Description: This path operation updates a person in the app and saves the information into the database.

    Parameters: 
        - Request body parameters:
            - **person: Person** -> A person model with their first name, last name, age, hair color and marital status.

    Result: It updates a person model with their first name, last name, age, hair color and marital status.
    """

    return person

# Forms

@app.post(
    path="/login",
    response_model=LoginOut,
    status_code=status.HTTP_200_OK,
    tags=["Persons"],
    summary="It shows a correctly logged in"
)
def login(username: str = Form(...), password: str = Form(...)):
    """
    Title: It shows a correctly logged in from some user

    Description: This path operation shows a message of a correctly logged in from an user.

    Parameters:
        - Request form parameters:
            - **username**
            - **password**

    Result: It returns a successfully message of a correctly logged in.
    """
    return LoginOut(username=username)

# Coookies and Headers Parameters

@app.post(
    path="/contact",
    status_code=status.HTTP_200_OK,
    tags=["Cookies"],
    summary="It creates an user agent"
)
def contact(
    first_name: str = Form(
        ...,
        max_length=20,
        min_length=1
    ),
    last_name: str = Form(
        ...,
        max_length=20,
        min_length=1,
    ),
    email: EmailStr = Form(...),
    message: str = Form(
        ...,
        min_length=20,
    ),
    user_agent: Optional[str] = Header(default=None),
    ads: Optional[str] = Cookie(default=None)
):
    """
    Title: It creates an user agent

    Description: This path operation returns an user agent

    Parameters:
        - Request form parameters:
            - **contact: ** -> A contact with first name, last name, email, message, user_agent and ads (cookie)

    Result: It returns an "user_agent" with first name, last name, email, message, user_agent and ads (cookie)
    """
    return user_agent


# Files

@app.post(
    path="/post-image",
    tags=["Media Content"],
    summary="It allows to upload an image"
)
def post_image(
    image: UploadFile = File(...)
):
    """
    Title: It allows to upload an image

    Description: Tis path operation allows us to upload an image and saves the information and the image itself in the database.

    Parameters:
        - Request file parameter: **image**

    Result: It allows us to upload an image and returns us its name, format and size in kb with 2 decimal digits.
    """
    return {
        "Filename": image.filename,
        "Format": image.content_type,
        "Size(kb)": round(len(image.file.read())/1024, ndigits=2)
    }

Si usan Visual Studio Code pueden habilitar pydocstyle (pueden configurarlo a gusto como se ve en la documentacion) y dejarle al linter la responsabilidad de recordar el PEP 257

Nombre y descripci贸n de una path operation

En Python existe algo llamado Docstring.

Estrctura recomendada:

  1. T铆tulo de la funci贸n (qu茅 es lo que hace).
  2. Descripci贸n de la funci贸n (c贸mo usarla).
  3. Par谩metros de la funci贸n (se puede usar markdown).
  4. Resultado que devuelve la funci贸n.

El docstring es la documentaci贸n de las funciones.

Para crear un docstring se usan triples comillas ''', que dentro de Python indica que dentro hay un docstring, y dentro de las triples comillas se documenta la funci贸n.

Para hacer el docstring de las funciones se debe considerar lo siguiente:

  • T铆tulo de la funci贸n (t铆tulo o nombre de la funci贸n).
  • Descripci贸n (c贸mo se usa y qu茅 es lo que hace).
  • Par谩metros (par谩metros de la funci贸n).
  • Resultado (lo que devuelve la funci贸n).

Cabe mencionar que se puede usar Markdown para darle formato.
Adicionalmente, en el path operation decorator se puede agregar el par谩metro summary para poner una breve descripci贸n o t铆tulo a la path operation.

@app.post(
    path='/person/new',
    response_model=PersonOut,
    status_code=status.HTTP_201_CREATED,
    tags=['Persons'],
    summary='Create Person in the app'
    )
def create_person(person: Person = Body(...)):
    '''
        Create Person

        This path operation creates a person in the app and save the information in the database
        
        Parameters:
        - Request body parameter:
            - **person: Person** -> A person model with first name, last name, age, hair color and marital status
        
        Returns a person model with first name, last name, age, hair color and marital status
    '''
    return person

En la documentaci贸n interactiva aparecer谩 de la siguiente manera:

@app.post(
    path="/person/new", 
    response_model=PersonOut,
    status_code=status.HTTP_201_CREATED,
    tags=["Persons"],
    summary="Create Person in the app"
    )
def create_person(person: Person = Body(...)):  # BD usando Body
    """
    # [Create Person]

    This path operation creates a person in the app and save the information in the database

    ### Parameters
    - Request body parameter: 
        - **person: Person** -> A person model with first name, last name, age, hair color and marital stauts

    ### Returns
    A person model with first name, last name, age, hair color and marital status
    """
    return person

Tambi茅n se recomienda agregar al docstring el tipo de excepciones que eleva la funci贸n, como en 茅ste ejemplo: 馃憞