Fastapi: Validation error when use alias in pydantic return model

Created on 27 Jun 2020  路  4Comments  路  Source: tiangolo/fastapi

First check

  • [x] I added a very descriptive title to this issue.
  • [x] I used the GitHub search to find a similar issue and didn't find it.
  • [x] I searched the FastAPI documentation, with the integrated search.
  • [x] I already searched in Bing "How to X in FastAPI" and didn't find any information.
  • [x] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [x] I already checked if it is not related to FastAPI but to Pydantic.
  • [x] I already checked if it is not related to FastAPI but to Swagger UI.
  • [x] I already checked if it is not related to FastAPI but to ReDoc.
  • [x] After submitting this, I commit to one of:

    • Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.

    • I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.

    • Implement a Pull Request for a confirmed bug.

Example

Here's a self-contained, minimal, reproducible, example with my use case:

import fastapi
import starlette.testclient
from pydantic import BaseModel, Field

app = fastapi.FastAPI()


class InModel(BaseModel):
    start_time: str = Field(alias='start_hms')


class OutModel(BaseModel):
    end_time: str = Field(alias='end_hms')


@app.post('/test', response_model=OutModel)
def test(query_body: InModel):
    print(query_body)  # start_time='14:00:00'
    print(query_body.dict())  # {'start_time': '14:00:00'}
    out_model = {'end_time': '12:00:00'}
    return out_model


with starlette.testclient.TestClient(app) as test_client:
    try:
        response = test_client.post('/test', json={'start_hms': '14:00:00'})
        print(response.json())
    except Exception as exc:
        print(exc)

Description


A wonderful framework! Very happy to use it to coding. Here is a little problem that make me really confused. I can easily change the name for request body from public name to field name by add alias in pydantic model (just what i did to InModel in the code), but when I do the same thing to the return model (OutModel in the code), an error occurred.

  • Run the code.
  • It ends up with an exception:
1 validation error for OutModel
response -> end_hms
  field required (type=value_error.missing).
  • But I expected it to return {"end_hms": "14:00:00"}.

Environment

  • OS: Ubuntu 20.04
  • FastAPI version: 0.58.0
  • Python version: 3.8.2
  • Pydantic version: 1.5.1
  • Starlette version: 0.13.4
question

Most helpful comment

Hi @zihaooo you could do it like this.

class OutModel(BaseModel):
    end_time: str = Field(alias='end_hms')

    class Config:
        # so we can use either the 'end_time' attribute or the alias attribute in this case 'end_hms'
        allow_population_by_field_name = True

All 4 comments

Hi @zihaooo you could do it like this.

class OutModel(BaseModel):
    end_time: str = Field(alias='end_hms')

    class Config:
        # so we can use either the 'end_time' attribute or the alias attribute in this case 'end_hms'
        allow_population_by_field_name = True

@MacMacky Many thanks~

For someone has the same question: https://pydantic-docs.helpmanual.io/usage/model_config/

And I complete the example with @MacMacky 's code:

import fastapi
import starlette.testclient
from pydantic import BaseModel, Field

app = fastapi.FastAPI()


class InModel(BaseModel):
    start_time: str = Field(alias='start_hms')


class OutModel(BaseModel):
    end_time: str = Field(alias='end_hms')
    class Config:
        # so we can use either the 'end_time' attribute or the alias attribute in this case 'end_hms'
        allow_population_by_field_name = True

@app.post('/test', response_model=OutModel)
def test(query_body: InModel):
    print('Enter server side...')
    print(f'Query body: {query_body.dict()}')  # {'start_time': '14:00:00'}
    out_model = {'end_time': '20:00:00'}
    print(f'Return value: {out_model}')
    print('Making response...\n')
    return out_model


with starlette.testclient.TestClient(app) as test_client:
    try:
        print('Enter client side...')
        query_body = {'start_hms': '14:00:00'}
        print(f'Query body: {query_body}')
        print('Making request...\n')
        response = test_client.post('/test', json=query_body)
        print('Back to client side...')
        print(f'Return value: {response.json()}')
        print('Exit client side.\n')
    except Exception as exc:
        print(exc)

Output:

Enter client side...
Query body: {'start_hms': '14:00:00'}
Making request...

Enter server side...
Query body: {'start_time': '14:00:00'}
Return value: {'end_time': '20:00:00'}
Making response...

Back to client side...
Return value: {'end_hms': '20:00:00'}
Exit client side.

@zihaooo You're welcome, man. Glad that I helped you.
Will you please close this issue. Thanks.

Thanks for the help here everyone! :clap: :bow:

Thanks for reporting back and closing the issue :+1:

Was this page helpful?
0 / 5 - 0 ratings