3

I have a function generating a dict template. This function consists of several generators and requires one parameter (i.e., carrier) and has many optional parameters (keyword arguments - **kwargs).

def main_builder(carrier, **params):
    output = SamplerBuilder(DEFAULT_JSON)
    output.generate_flight(carrier)
    output.generate_airline_info(carrier)
    output.generate_locations()
    output.generate_passengers()
    output.generate_contact_info()
    output.generate_payment_card_info()
    output.configs(**params)
    result = output.input_json
    return result 

# example of function call
examplex = main_builder("3M", proxy="5.39.69.171:8888", card=Visa, passengers={"ADT":2, "CHD":1}, bags=2)

I want to deploy this function to FastAPI endpoint. I managed to do it for carrier but how can I set **kwargs as params to the function?

@app.get("/carrier/{carrier_code}", response_class=PrettyJSONResponse) # params/kwargs??
async def get_carrier(carrier_code):
    output_json = main_builder(carrier_code)
    return airline_input_json
Chris
  • 18,724
  • 6
  • 46
  • 80
PetrSevcik
  • 89
  • 1
  • 9

1 Answers1

3

Using Pydantic Model

Since your function "..has many optional parameters" and passengers parameter requires a dictionary as an input, I would suggest creating a Pydantic model, where you define the parameters, and which would allow you sending the data in JSON format and getting them automatically validated by Pydantci as well. Once the endpoint is called, you can use Pydantic's dict() method to convert the model into a dictionary.

Example

from pydantic import BaseModel
from typing import Optional

class MyModel(BaseModel):
    proxy: Optional[str] = None
    card: Optional[str] = None
    passengers: Optional[dict] = None 
    bags: Optional[int] = None

@app.post("/carrier/{carrier_code}")
async def get_carrier(carrier_code: int, m: MyModel):
    return main_builder(carrier_code, **m.dict())

Sending arbitrary JSON data

In case you had to send arbitrary JSON data, and hence, pre-defining the parameters of an endpoint wouldn't be possible, you could use an approach similar to the one described in this answer (see Options 3 and 4), as well as this answer and this answer.

Chris
  • 18,724
  • 6
  • 46
  • 80
  • Thanks for the comment. When I run the API (`docker-compose up`) it works but when I try to get to `http://0.0.0.0:8080/carrier/3M` (3M is carrier code) without any parameters I get reponse code 422: `422 Unprocessable Entity` and in browser I get an error `{"detail":[{"loc":["body"],"msg":"field required","type":"value_error.missing"}]}` Am I missing something? – PetrSevcik Mar 24 '22 at 09:45
  • @PetrSevcik I think you need to use default values, `carrier_code: int = None` ...worked for me. – mfeyx Aug 03 '22 at 14:34