admin管理员组

文章数量:1391999

I have two endpoints below, one that accepts two integers and another that accepts tow lists of integers.

I also have two post requests that I am making using Python requests. The request for the list of ints endpoint works fine, but the one that just accepts the two ints does not.

I know that if I pass the two ints in the URL (i.e, the query string), the endpoint will work. However, could you tell me why it doesn't work when passed as JSON?

endpoints.py

from fastapi import FastAPI

app = FastAPI()

@app.post('/ints')
def post_int(x: int, y: int):
    return x, y

@app.post('/lists')
def post_list(x: list[int], y: list[int]):
    return x, y

requests.py

import requests

r = requests.post('http://127.0.0.1:8000/ints', json={'x': 1, 'y': 2})
print(r.json()) # returns an error saying that x and y are missing

r = requests.post('http://127.0.0.1:8000/ints?x=1&y=2')
print(r.json()) # returns the two ints

r = requests.post('http://127.0.0.1:8000/lists', json={'x': [1, 2, 5], 'y': [1, 2, 3]})
print(r.json()) # returns the two lists

To start server, run "fastapi dev /path/to/endpoints.py" in terminal. Run requests.py in another terminal for output.

I have two endpoints below, one that accepts two integers and another that accepts tow lists of integers.

I also have two post requests that I am making using Python requests. The request for the list of ints endpoint works fine, but the one that just accepts the two ints does not.

I know that if I pass the two ints in the URL (i.e, the query string), the endpoint will work. However, could you tell me why it doesn't work when passed as JSON?

endpoints.py

from fastapi import FastAPI

app = FastAPI()

@app.post('/ints')
def post_int(x: int, y: int):
    return x, y

@app.post('/lists')
def post_list(x: list[int], y: list[int]):
    return x, y

requests.py

import requests

r = requests.post('http://127.0.0.1:8000/ints', json={'x': 1, 'y': 2})
print(r.json()) # returns an error saying that x and y are missing

r = requests.post('http://127.0.0.1:8000/ints?x=1&y=2')
print(r.json()) # returns the two ints

r = requests.post('http://127.0.0.1:8000/lists', json={'x': [1, 2, 5], 'y': [1, 2, 3]})
print(r.json()) # returns the two lists

To start server, run "fastapi dev /path/to/endpoints.py" in terminal. Run requests.py in another terminal for output.

Share Improve this question edited Mar 14 at 5:35 Chris 35.5k10 gold badges104 silver badges251 bronze badges asked Mar 13 at 15:46 JayJay 591 silver badge7 bronze badges 3
  • @jabaa have included the imports and additional code required to reproduce. – Jay Commented Mar 13 at 16:39
  • 1 In the first case, the data are expected as query params (if also defined in the endpoint's path, as in this, they would be expected as path parameters). If you need them to be expected as JSON data in the request's body instead, have a look at this answer for the various approaches. In the second case, FastAPI would interpret the list parameters as body data by default. To use them as query params instead, you need to explicitly use Query – Chris Commented Mar 13 at 17:52
  • Thanks @Chris, this is really helpful! – Jay Commented Mar 13 at 22:22
Add a comment  | 

1 Answer 1

Reset to default 0

could you tell me why it doesn't work when passed as JSON?

When you register a route with

@app.post('/ints')
def post_int(x: int, y: int):
    return x, y

in FastApi, the route is analyzed and added in

decorator (routing.py)
add_api_route (routing.py)
__init__ (routing.py)
get_dependant (dependencies/utils.py)
analyze_param (dependencies/utils.py)

Near the end of analyze_param, you can find

elif field_info is None and depends is None:
    default_value = value if value is not inspect.Signature.empty else RequiredParam
    if is_path_param:
        # We might check here that `default_value is RequiredParam`, but the fact is that the same
        # parameter might sometimes be a path parameter and sometimes not. See
        # `tests/test_infer_param_optionality.py` for an example.
        field_info = params.Path(annotation=use_annotation)
    elif is_uploadfile_or_nonable_uploadfile_annotation(
        type_annotation
    ) or is_uploadfile_sequence_annotation(type_annotation):
        field_info = params.File(annotation=use_annotation, default=default_value)
    elif not field_annotation_is_scalar(annotation=type_annotation):
        field_info = params.Body(annotation=use_annotation, default=default_value)
    else:
        field_info = params.Query(annotation=use_annotation, default=default_value)

https://github/fastapi/fastapi/blob/master/fastapi/dependencies/utils.py#L460

There you can see that scalar parameters have field info type query. Lists aren't scalar values and have field info type body.

本文标签: pythonPassing Integers to FastAPI post endpointStack Overflow