Giter Site home page Giter Site logo

luolingchun / flask-openapi3 Goto Github PK

View Code? Open in Web Editor NEW
162.0 7.0 31.0 7.78 MB

Generate REST API and OpenAPI documentation for your Flask project.

Home Page: https://luolingchun.github.io/flask-openapi3/

License: MIT License

Python 100.00%
flask swagger redoc openapi3 python3 pydantic openapi rest rapidoc python

flask-openapi3's Introduction

Hello WorldπŸš€

Anurag's GitHub stats

flask-openapi3's People

Contributors

barryrobison avatar bklynn avatar blackgad avatar boyanyk avatar candleindark avatar colin-b avatar costcofanboy avatar dependabot[bot] avatar dvaerum avatar luolingchun avatar ota42y avatar seekplum avatar stufisher avatar tarcisiojr avatar thebmw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

flask-openapi3's Issues

Working for v3.0

  • Upgrade pydantic to v2.
  • Switch to pyproject.toml.
  • #91
  • Remove **kwargs( in OpenAPI and APIBlueprint) and replace it with specific parameters, see class Flask and class Blueprint.
  • Remove **options(in APIScaffold's get, post, put ... ) and replace it with specific parameters, see class Rule in werkzeug.
  • #92
  • #93

Response validation when using http.HttpStatus

Just noticed that response vlaidation does not work for me.

Most of the code uses http.HttpStatus enums as status_code. I suppose flask does support that out-of-the-box....

I had a play around and patching validate_response in utils.py seems to do the trick:

    if isinstance(status_code, http.HttpStatus):
        status_code = status_code.value

If that adds unwanted dependencies this does work too, although I am not sure if it is too generic...

    if isinstance(status_code, enum.Enum):
        status_code = status_code.value

async routes not working

hi,

unfortunately async def routes are not working with an

app = OpenAPI(__name__)

simple route which should work

@app.get("/async_test")
async def async_test():
    return "hi"

if i change to app = Flask(__name__) the route returns "hi".

any chance this is only a small issue, so async routes can be used with OpenAPI3?

Enable sponsoring on the project

Open Source projects are great. But we all know the effort that goes into keeping things going. People that don't have the time to contribute in code might want to contribute to the maintainers in other ways, GitHub Sponsorships is an easy way to do that.

header parameter does not return request.headers

This is my code:

image

and this is the response:

image
image

What is expected:

image

There is also this case:

If I define my hello in Headers class as:

hello: str = Field("what's up")

then no matter what I place in my "hello" header, I always get the default "what's up" value.

image

P.D. Thanks so much for this great library!

support for response content types other than application/json

How would I specify a response similar to the following:

    responses:
       '200':
          description: OK
          content:
            # JSON data is an object
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
            # CSV data is a string of text
            text/csv:
              schema:
                type: string

Feature request: Optionally allow to configure additional oauth parameters

This is a swagger-ui specific feature - it would be nice to be able to configure additional OAuth configuration as supported in swagger-ui: https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/oauth2.md

Maybe an additional config on the Flask OpenAPI instance? Then those could be passed into the render method for swagger.html..

I tried this locally and it works fine :)

        window.ui.initOAuth({
            clientId: "{{ client_id }}",
        })

Add support for Blueprint.route()

While I am at it ...

The application I am working on makes extensive use of the blueprint route() method, so adding support for that in APIBlueprint would make a potential integration at lot easier.

Thanks for all the work!

Required header is not found

Environment:

  • Python version: 3.9.14
  • Operating system: Debian GNU/Linux 10 (buster)
  • Flask version:
  • flask-openapi3 version: 2.1.0

Not sure what is going wrong here. I followed the documentation for adding path parameters and json body information. I then noticed there was no example for headers, but I just made the same as the path.

class AuthHeader(BaseModel): api_key: str = Field(..., description="API Key")

and added it to the function as header: AuthHeader.

Checked the swagger UI and sure enough it showed up as a required field under parameters, and the generated curl command looks logical enough, adding it as expected -H "api_key: supersecretapikey". But it keep getting the following back if I keep the api_key field required.

[ { "loc": [ "api_key" ], "msg": "field required", "type": "value_error.missing" } ]

I get it from the "Try it out" on swagger UI, and from the curl command as well.

route parameter not found

Hi there,

I've been playing with the latest release (0.9.3) and I am having issues with path parameters. The error I am getting is

TypeError: missing 1 required positional argument

I've done some poking and debugging and it looks to me its coming from here: https://github.com/luolingchun/flask-openapi3/blob/master/flask_openapi3/openapi.py#L76

If I change that line to use kwargs (no trailing '_') things start working. Not sure what is the correct fix, though. Maybe initializing kwargs_ with the actual kwargs rather than {}?

Feature request - Optiona to add top-level extensions to openapi spec

Use case:

  • Different API gateway providers (AWS API Gateway, Google API GATEWAY) needs extensions in their openapi-spec to be able to function.

Requirement from Google API Gateway: https://cloud.google.com/endpoints/docs/openapi/openapi-extensions#x-google-backend (This gateway needs the OAS3 to be converted to OAS2 if someone comes here looking for help with that specific issue I recommend https://github.com/LucyBot-Inc/api-spec-converter in a GH action)

OpenAPI3 supports it: https://spec.openapis.org/oas/v3.0.3#specification-extensions

@luolingchun I will probably not have time to come up with a PR for this in the near future and will do a work around for my use case.

Feature Request - allow initialization variables in register_api_view

Hi!
Thank you for your great project, if I get time I'll try to come up with a PR for this feature.

In flask classful you had the option of adding initialization arguments to the view classes. As someone that comes from a DDD and DI background this is something I really want to do. It enables me to achieve poor man's Dependency Injection.
https://flask-classful.teracy.org/#well-more-words-on-register

app.register_api_view(v1_template_rest.api_view, some_init_argument="ABC123")

and in the api view:

@api_view.route("/example")
class ExampleApiView
    some_init_argument: str
    def __init__(self, some_init_argument:str):
        self.some_init_argument = some_init_argument
        
   def get():
       ....

FileStorage list is not supported

Hello,

I am trying to implement a multiple file upload endpoint.

I defined the file form as the following:

class FileForm(BaseModel):
    file: list[FileStorage]

And the endpoint as the following:

@app.post("/file/", tags=[app_tag])
def upload(form: FileForm):
    files = form.file

When I try to upload a file with this endpoint using Swagger, I am getting the following error:

[
  {
    "loc": ["file"],
    "msg": "value is not a valid list",
    "type": "type_error.list"
  }
]

Any suggestion on what I am doing wrong?

Thanks!

Supports both string, int, and HTTPStatus

Why did you use a custom library of strings instead of the official HTTPStatus lib built-in in Python everywhere?
flask_openapi3/http.py vs from http import HTTPStatus

There's inconsistencies vs HTTP Status as a string and HTTP Status as an int.
There's also from http import HTTPMethod for methods.

@CostcoFanboy We are here to discuss this issue.

Why did you use a custom library of strings instead of the official HTTPStatus lib built-in in Python everywhere?
flask_openapi3/http.py vs from http import HTTPStatus

At the beginning of the project, it was completely based on the OpenAPI Specification, so only the string was considered.
However, I am open to both int and HTTPStatus, and we can support both.

There's also from http import HTTPMethod for methods.

HTTPMethod was not supported until Python 3.11.

How to get the parsed Pydantic models of an endpoint globally?

I want to access the body of a request in a error handler, but right now I'm having to re-parse the body which is very inneficient.

If this is not possible yet then I leave this as a suggestion

# Not ideal:
@api.error_handler(400)
def log_error_payload(e: HTTPException):
    if flask.request.is_json:
        payload_dict = json.loads(flask.request.get_json())
        log_payload(payload_dict)

# Ideal:
@api.error_handler(400)
def log_error_payload(e: HTTPException):
    if flask.request.openapi.body:
        payload_dict = flask.request.openapi.body.dict()
        log_payload(payload_dict)

Feature Request - custom get_operation_id_for_path handler

Hi, thank you for your great work on this project!

I encountered a use case for being able to define custom handlers for generating the OpenAPI operation_id.
In a large api, where we are adding flask-openapi we run into situations where a method like:

@api.post("/logout", tags=[auth], ...)
def logout():
  ..

The current get_operation_id_for_path handler generates an operation_id as: logout_logout_post. Then, when generating a client library with https://openapi-generator.tech/ it creates the following library usage (JS example):

client.auth.logoutLogoutPost()
...

Which is just not that nice to use. Of course, this can be defined by setting operation_id on the endpoint but that means custom setting it for every endpoint.

I believe it would make sense to support adding a custom handler when creating Blueprint / View / OpenAPI instance.

I would have time this week to open a PR for this feature, though I would also ask for advice on the following:

  • What should the name for such a property be? Something like operation_id_callback perhaps?
  • Would it be alright to also open a PR to make this change for Flask-OpenAPI3 v1.x as maybe a small update to v1.1.4? We are still (unfortunately) currently using Flask 1.x so this would be quite important

extra_responses are requiring content key (and only keeping content)

According to the OpenAPI specification, content is not a required key within a response. However current code is requiring content to add an extra response:

extra_content = value.get("content", {})

And it also assume that extra_responses only contains content, discarding provided description, headers and links.

extra_responses is currently the only way to describe responses not containing a body (ie: HTTP 201 / HTTP 204) and thus should allow to set any information OpenAPI specification allow in a response.

Please tell me if you want me to draft a pull request for this bug fix / enhancement.

Thanks again

Endpoint with multiple paths and optional path parameters

Is it possible to have an endpoint that has two routes registered on it with different parameters?

For example (roughly pseudocode):

class GetObjectPath(BaseModel):
    id: int
    version: Optional[int]

@blueprint.get('<id>')
@blueprint.get('<id>/version/<version>')
def get_object(path: GetObjectPath):
    filters = {id: path.id}
    if path.version:
        filters['version'] = path.version
    return DB.filter(**filters).get().serialize()

I can make optional fields work in things like query or body, but is this not supported for the path and multiple routes on a single implementation?

Latest release dropped the required=True on request body by default

I can set it back to True thanks to the new extra_body argument.

The default value is supposed to be False in case it is not provided according to OpenAPI specifications but the code is actually expecting it to be provided.

IMO it should be considered as required by default in the code, set to required by default in the generated OpenAPI. However setting it to None or False should allow body not to be provided (set to None then when received in the endpoint).

flask-openapi3 looks like it needs a new version of flask (newer than 1.x at least)

Not a big deal but I had some errors like this:

2022-02-22 03:14:41,472 - werkzeug - INFO - 172.28.0.1 - - [22/Feb/2022 03:14:41] "GET /openapi/openapi.json HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/home/daniel/git/mas/.venv/lib/python3.7/site-packages/flask/app.py", line 1974, in make_response
    rv = self.response_class.force_type(rv, request.environ)
  File "/home/daniel/git/mas/.venv/lib/python3.7/site-packages/werkzeug/wrappers/base_response.py", line 269, in force_type
    response = BaseResponse(*_run_wsgi_app(response, environ))
  File "/home/daniel/git/mas/.venv/lib/python3.7/site-packages/werkzeug/wrappers/base_response.py", line 26, in _run_wsgi_app
    return _run_wsgi_app(*args)
  File "/home/daniel/git/mas/.venv/lib/python3.7/site-packages/werkzeug/test.py", line 1119, in run_wsgi_app
    app_rv = app(environ, start_response)
TypeError: 'dict' object is not callable

that updating to flask 2.x fixed. If that's an accurate assessment it would be good to have the dependency specified :)

Request: Support List[pydantic.BaseModel] as response

Environment:

  • Python version: 3.9.13
  • Operating system: MacOS Monterey 12.4
  • Flask version: 2.1.3
  • flask-openapi3 version: 2.2.2

Request

Add support of List[] in responses.

Explanation

I'm trying to migrate an existing Flask API to Flask-OpenAPI, and I'm hitting an issue.

  • Most of my endpoints return a JSON object, with the proper content type. This is compatible with the responses parameter in the @app.get decorator βœ…
  • Other endpoints return a simple string, with text content type. This is compatible with the extra_responses parameter βœ…
  • However, I do have a number of endpoints that return a JSON encoded list of objects, with content type JSON. This is not compatible with responses.

Since this API is used in production:

  • I can't afford to wrap these lists in "dummy" object with a data key that would contain the list.
  • I also don't really want to have to write a special dictionary to use in extra_responses. I tried using pydantic's schema_of function inside extra_responses, but that's not compatible because of the use of definitions.

Note that pydantic.schema_of(List[<child of pydantic.BaseModel>]) does work.

[Feature Request] Support for Nested APIBlueprint

Hey flask-openapi3 project :)

Are there any plans for adding support for nested APIBlueprint, similar to the Blueprint from Flask?
Link to docs: https://flask.palletsprojects.com/en/2.1.x/api/?highlight=register_blueprint#flask.Blueprint.register_blueprint

I have been trying to play around with an implementation for this. Currently, it looks like this.

# ...

from urllib.parse import urljoin

# ...

class APIBlueprint

# ...

    def register_api(self: APIBlueprint, api: APIBlueprint) -> None:
        # Don't know if this will work, have not really used tags πŸ˜… 
        for tag in api.tags:
            if tag.name not in self.tag_names:
                self.tags.append(tag)

        # This seems to work, pretty well
        for path, path_item in api.paths.items():
            path: str
            path_item: PathItem
            joined_path = urljoin(self.url_prefix, path.lstrip("/"))
            self.paths[joined_path] = path_item

        # I could imagion that this could give some problems with classes name overlapping, but it is early testing
        self.components_schemas.update(**api.components_schemas)

        self.register_blueprint(api)

Update the text for making a pull request

When making a merge request, you have the message

- [ ] Run `flake8 flask-openapi3 tests examples` and no failed.

but I think you meant to write flask_openapi3 not flask-openapi3 because the folder flask-openapi3 doesn't exist πŸ˜‰

I just spend 10-15mins trying to figure what this missing folder flask-openapi3 was, but I am now convinced that it is a mix-up of the package name and the library folder πŸ˜ƒ

Body throws exception when receiving str instead of dict

First off thank you very much for your great library. Exactly what I was looking for!!!

Environment:

  • Python version: 3.10
  • Operating system: Ubuntu
  • Flask version: 2.0.3
  • flask-openapi3 version: 1.1.4

Using for example this model

class MyModel(BaseModel):
   text: str

and the flask server is looking for the model as body

@page.post("/path/")
def post(body: MyModel):
   pass

, but the user sends the model json formated (thus as str instead of a dict)

response = requests.post(url="localhost:5000/path/", json=mymodel.json())

The wrapper throws an exception, since a str can't be mapped to the MyModel like a dict

ERROR:app:Exception on /path/ [POST]
Traceback (most recent call last):
  File "/home/user/project/venv/lib/python3.10/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/user/project/venv/lib/python3.10/site-packages/flask/app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/user/project/venv/lib/python3.10/site-packages/flask/app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/user/project/venv/lib/python3.10/site-packages/flask/app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/home/user/project/venv/lib/python3.10/site-packages/flask_openapi3/api_blueprint.py", line 231, in wrapper
    resp = _do_wrapper(
  File "/home/user/project/venv/lib/python3.10/site-packages/flask_openapi3/do_wrapper.py", line 96, in _do_wrapper
    body_ = body(**request.get_json(silent=True) or {})
TypeError: MyModel() argument after ** must be a mapping, not str

An alternative would be to either do attempt a json.loads() before doing a body(**value) or to return 422?

Parameters in blueprint `url_prefix`

I may be missing something obvious with this, however: in 'regular' Flask, I can put a parameter in a URL prefix, and have something like:

project_bp= Blueprint(
    "project", __name__, url_prefix="/projects/<project_name>"
)

@project_bp.route("/")
def index(project_name: str):
    logger.info(f"Called GET for project {project_name}")


tag_bp = Blueprint("tag", _name__, url_prefix="/tags")

@route("/")
def index(project_name: str):
    logger.info(f"Called GET tags for {project_name}")

project_bp.register_blueprint(tag_bp)

The net result of this being that both /project/<name> and /project/<name>/tags would end up as routes. Everything in the tag_bp automatically gets supplied with the project_name argument.

I'm trying to do something similar with flask-openapi3 but it's not quite working. I'm not yet nesting, but

api = APIBlueprint(
    "project",
    __name__,
    url_prefix="/project/<name>",
    abp_tags=[Tag(name="project_tag", description="Some project API")],
    # disable openapi UI
    doc_ui=True,
)

@api.get(rule="/", responses={"200": Project})
def get_project(path: ProjectPath) -> Project:
    _logger.info(f"Called get_project with {path}")
    result = Project(name=path.name, description="No description set")
    return result.json()

doesn't work - the path argument is always set to <name>. To get it to function as I want, I have to define things like this:

api = APIBlueprint(
    "project",
    __name__,
    url_prefix="/project/",
    abp_tags=[Tag(name="project_tag", description="Some project API")],
    # disable openapi UI
    doc_ui=True,
)

@api.get(rule="/<name>", responses={"200": Project})
def get_project(path: ProjectPath) -> Project:
    _logger.info(f"Called get_project with {path}")
    result = Project(name=path.name, description="No description set")
    return result.json()

If I then try nesting this, I'm not going to be able to 'collect up' the parameters from higher up in the blueprint hierarchy.... I have a feeling I'm missing something.

Thanks in advance.

Add support to protect the spec endpoint

There is already a flag to disable the UI. In addition it would be nice to be able to somehow protect/control access to the spec endpoint itself.
Alternative, the ability to easily write the spec to a file on the command line (and a way to disable the openapi blueprint altogether) could work too...

Trailing slash isn't showing up in the generated docs

It leads to wrong documentation

Example:

api = APIBlueprint(..., url_prefix='...users/') # tried with or without the trailing slash 

api.post("/")
def add_user():
    ....

Tried to find where it gets stripped, probably in the file openapi.py line 231:

...
# strip the right slash
uri = uri.rstrip('/')
...

security_schemes(SecurityScheme) supports json format

from flask_openapi3 import Info
from flask_openapi3 import OpenAPI

info = Info(title='book API', version='1.0.0')
# Basic Authentication Sample
basic = {
  "type": "http",
  "scheme": "basic"
}
# JWT Bearer Sample
jwt = {
  "type": "http",
  "scheme": "bearer",
  "bearerFormat": "JWT"
}
# API Key Sample
api_key = {
  "type": "apiKey",
  "name": "api_key",
  "in": "header"
}
# Implicit OAuth2 Sample
oauth2 = {
  "type": "oauth2",
  "flows": {
    "implicit": {
      "authorizationUrl": "https://example.com/api/oauth/dialog",
      "scopes": {
        "write:pets": "modify pets in your account",
        "read:pets": "read your pets"
      }
    }
  }
}
security_schemes = {"jwt": jwt, "api_key": api_key, "oauth2": oauth2, "basic": basic}

app = OpenAPI(__name__, info=info, security_schemes=security_schemes)

see Security Scheme Object Example

DeprecationWarning:
HTTPBearer, OAuth2, OAuthFlows, OAuthFlowImplicit, APIKey, HTTPBase will be deprecated in v3.x

should doc strings render as markdown?

Environment:

  • Python version: 3.7
  • Operating system: windows or ubuntu 18.04
  • Flask version: 1.1.4
  • flask-openapi3 version:

Should get_operation add </br> to doc strings? If the description has line feeds \n vs </br> the description renders as markdown.

doc_description = lines[0] if len(lines) == 0 else "</br>".join(lines[1:]) or None
else:
doc_description = "</br>".join(lines) or None

code diff

index fd194d8..c5f0db9 100644
--- a/flask_openapi3/utils.py
+++ b/flask_openapi3/utils.py
@@ -24,9 +24,9 @@ def get_operation(func: Callable, *, summary: Optional[str] = None, description:
     lines = doc.split("\n")
     doc_summary = lines[0] or None
     if summary is None:
-        doc_description = lines[0] if len(lines) == 0 else "</br>".join(lines[1:]) or None
+        doc_description = lines[0] if len(lines) == 0 else "\n".join(lines[1:]) or None
     else:
-        doc_description = "</br>".join(lines) or None
+        doc_description = "\n".join(lines) or None
     operation = Operation(
         summary=summary or doc_summary,
         description=description or doc_description

example endpoint:

@blueprint.post('/test', responses={...})
def test(body: ....):
    """
    my summary

   Examples:
   test with `some param`
   ...
   
   """
   return {}

With \n vs </br> the above example will render the markdown from the docstring into HTML. This is useful when providing some additional usage/example to the endpoint's documentation.

Custom Response description

I am having a hard time finding where to customize the response description.

Having Success as decription for a 401 - Unauthorized response looks pretty weird :)

If it is not possible to explicitely set it, maybe having a different value for 2xx, 3xx, ... could be a good start?

Response validation fails due to missing optional elements

Hi,

I do have a data type using Optional like in the example below. What is wrong here?

class PackageData(BaseModel):
    """Single package data."""

    id: UUID = Field(..., description="UUID")
    title: str = Field(..., description="Title")
    visibility: Optional[str] = Field(..., description="Visibility of the package")

Tests are failing with this, though:

E   visibility
E     field required (type=value_error.missing)

CORS does not work with OpenAPI

With using flask-cors I cannot reach my endpoints via my web app. If I change to normal Flask cors settings work.

Environment:

  • Python version: 3.9.1
  • Operating system: Windows 10
  • Flask version: 2.2.2
  • flask-openapi3 version: 2.2.0

Response cannot be a simple type like int

Environment:

  • Python version: 3.10
  • Operating system: tested it on Windows 10 and Ubuntu 22.04
  • Flask version: 2.0.3
  • flask-openapi3 version: 2.0.0

I cannot create an endpoint that is returning an int (or any other native type)

@app.get("/path", responses={"200": int})
def apicall():
    return 1

gives error TypeError: <class 'int'> is invalid pydantic.BaseModel.

I could leave the responses out, but this makes the generated doc incomplete

Request with headers using pydantic alias not working

By setting a custom header using dashes in a request, the attribute alias from the Pydantic Field must be used.
When performing a request with the header, it's not detected by the application.

Code example:

from pydantic import BaseModel, Field

from flask_openapi3 import Info, Tag
from flask_openapi3 import OpenAPI

info = Info(title='header API', version='1.0.0')
app = OpenAPI(__name__, info=info)

book_tag = Tag(name='book', description='Some Book')


class Headers(BaseModel):
    hello: str = Field(..., max_length=12, description='Header with alias to support dash', alias="x-hello")


@app.get('/book', tags=[book_tag])
def get_book(header: Headers):
    print(header)
    return header.hello


if __name__ == '__main__':
    app.run(debug=True)

Requesting with the custom dashed header:

curl -X 'GET' \
  'http://127.0.0.1:5000/book' \
  -H 'accept: */*' \
  -H 'x-hello: dummy value'

Error response:

[
  {
    "loc": [
      "x-hello"
    ],
    "msg": "field required",
    "type": "value_error.missing"
  }
]

In this example expected behaviour is the output of the header value.

Environment:

  • Python version: 3.9.5
  • Operating system: Ubuntu 20.04
  • Flask version: 2.2.3
  • flask-openapi3 version: 2.3.1

Support for other JSON libraries?

Environment:

  • Python version: 3.9
  • Operating system: Arch Linux
  • Flask version: 2.1.2
  • flask-openapi3 version: 2.0.0

Hi there! Congratulations, this is a remarkable library and it's helping me a lot to get my Flask-based app documented with OpenAPI.

Let me ask something though: is there any plan to allow different JSON to be used for data serialization, like orjson or ujson? I'm asking because for larger amounts of data they make a lot of difference in performance compared to the stdlib json module.

Thanks!

TypeError: ModelMetaclass object argument after ** must be a mapping, not Response

When configuring a 200 respone the actual API will fail with

TypeError: ModelMetaclass object argument after ** must be a mapping, not Response

in this line: https://github.com/luolingchun/flask-openapi3/blob/v0.9.3/flask_openapi3/utils.py#L266

Looks like on master the code has changed a bit - is it worth updating for this?

EDIT: master does the same thing ...

Does the message mean you cannot return a response? If so, why? Can't the code grab the body of the response to validate against the model? Or am I completely down the wrong path here?

Support APIView

Support class based restful API, such as flask-restful.

Syntax:

app = OpenAPI(__name__)

api_view = APIView(url_prefix="/api/v1")

class BookQuery(BaseModel):
    age: Optional[int] = Field(None, description='Age')


class BookBody(BaseModel):
    age: Optional[int] = Field(..., ge=2, le=4, description='Age')
    author: str = Field(None, min_length=2, max_length=4, description='Author')


@api_view.route("/book")
class BookListAPIView:
    a = 1

    @api_view.doc(summary="get book list")
    def get(self, query: BookQuery):
        print(self.a)
        return query.json()

    @api_view.doc(summary="create book")
    def post(self, body: BookBody):
        """description for create book"""
        return body.json()


@api_view.route("/book/<id>")
class BookAPIView:
    @api_view.doc(summary="get book", deprecated=True)
    def get(self):
        return "get"

    @api_view.doc(summary="update book")
    def put(self):
        return "put"

    @api_view.doc(summary="delete book")
    def delete(self):
        return "delete"

app.register_api_view(api_view)

Complete Example:

https://github.com/luolingchun/flask-openapi3/blob/APIView/examples/api_view_demo.py

Welcome to provide better ideas!

BaseModel Config support `openapi_extra`

class BookBody(BaseModel):
    age: Optional[int] = Field(..., ge=2, le=4, description='Age')
    author: str = Field(None, min_length=2, max_length=4, description='Author')

    class Config:
        openapi_extra = {
            "description": "This is post RequestBody",
            "example": {
                "age": 12,
                "author": "author"
            },
            "examples": {
                "example1": {
                    "summary": "example summary1",
                    "description": "example description1",
                    "value": {
                        "age": 24,
                        "author": "author1"
                    }
                },
                "example2": {
                    "summary": "example summary2",
                    "description": "example description2",
                    "value": {
                        "age": 48,
                        "author": "author2"
                    }
                }
            }
        }

DeprecationWarning:
extra_form , extra_body and extra_responses will be deprecated in v3.x ???

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.