bauerji / flask-pydantic

flask extension for integration with the awesome pydantic package

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Validation for Array of Models fails

ckwojai opened this issue · comments

from typing import List
from flask_pydantic import validate

api = Blueprint("lineage-collector", __name__)

class EntityPayload(BaseModel):
    attributes: dict
    typeName: str

class EntityPayloadBulk(BaseModel):
    __root__:  List[EntityPayload]

@api.route('/entity/bulk', methods=["POST"])
@validate()
def entity_bulk(body: EntityPayloadBulk):
    return "Hello World"

Call to this endpoint returns the following error:

` File "/usr/local/lib/python3.9/site-packages/flask_pydantic/core.py", line 158, in wrapper
b = body_model(**body_params)
TypeError: api.routes.EntityPayloadBulk() argument after ** must be a mapping, not list

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2464, in call
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functionsrule.endpoint
File "/usr/local/lib/python3.9/site-packages/flask_pydantic/core.py", line 164, in wrapper
raise JsonBodyParsingError()
flask_pydantic.exceptions.JsonBodyParsingError`

Hi,

Thank you for pointing out. To be honest I did not know about pydantic's custom root types using __root__ attribute. I will modify functionality to take care of them.

Jirka

I added this feature to support as many pydantic's feature as possible.

However I strongly encourage you not to use custom root types.

The preferred way of achieving the same result is using validate's request_body_many attribute

from typing import List
from flask_pydantic import validate

api = Blueprint("lineage-collector", __name__)

class EntityPayload(BaseModel):
    attributes: dict
    typeName: str

@api.route('/entity/bulk', methods=["POST"])
@validate(request_body_many=True)
def entity_bulk(body: EntityPayload):
    return "Hello World"

I think using List[EntityPayload] will be better, like

def entity_bulk(body: List[EntityPayload]):

By using request_body_many=True we get an array of EntityPayload in body, not an object of EntityPayload. This messes up autocomplete in IDEs.