turner-townsend / flask-pydantic-spec

An Flask OpenAPI library using Pydantic
Apache License 2.0
99 stars 19 forks source link

[QUESTION] Use with Flask-Restful #27

Closed GrinJ closed 2 years ago

GrinJ commented 2 years ago

Describe the bug Is it possible to use this with Flask-Restful

To Reproduce Steps to reproduce the behavior:

from flask import Flask, request, jsonify
from pydantic import BaseModel, Field, constr
from flask_pydantic_spec import FlaskPydanticSpec, Response, Request
from flask import Blueprint
from flask_restful import Api, Resource

class Profile(BaseModel):
    name: constr(min_length=2, max_length=40) # Constrained Str
    age: int = Field(
        ...,
        gt=0,
        lt=150,
        description='user age(Human)'
    )

    class Config:
        schema_extra = {
            # provide an example
            'example': {
                'name': 'very_important_user',
                'age': 42,
            }
        }

class Message(BaseModel):
    text: str

app = Flask(__name__)
fps = FlaskPydanticSpec('flask')

# Init the Flask blueprint
bp = Blueprint("app_v2", __name__)

# Init the Flask blueprint
api = Api(bp)

class User(Resource):
    @fps.validate(body=Request(Profile), resp=Response(HTTP_200=Message, HTTP_403=None), tags=['api'])
    def get(self):
        """
        verify user profile (summary of this endpoint)

        user's name, user's age, ... (long description)
        """
        print(request.context.json) # or `request.json`
        return jsonify(text='it works')

if __name__ == "__main__":
    api.init_app(app)

    # Register the BluePrint
    app.register_blueprint(bp)

    api.add_resource(User, "/user")

    fps.register(app) # if you don't register in api init step
    app.run(port=8000)

Expected behavior So I want to add a validation to a class method, and it works, but it does not generate the doc. https://i.imgur.com/2ZNhw9U.png

Additional context So is it possible to do that?

GrinJ commented 2 years ago

So I founded how to solve this problem.

It is not elegant, but it works. All you need is to replace this

api.add_resource(User, "/user")

to this

api.add_resource(User, "/user")
app.add_url_rule("/user", "User.get", User.get, methods=["GET"])

And documentation and validation works well.