Python Flask Blueprints - Defining API Docs for multiple endpoints in one .yaml file

1.2k Views Asked by At

I have some endpoints in one of my blueprints, and I'm hoping to add all the API documentation for this blueprint into a single .yaml file. However, with my current .yaml file structure and blueprint code, it seems like flasgger is not recognizing the correct definition.

Blueprint code:

app_obj = Flask(name)
app_obj.register_blueprint(user_controller, url_prefix="/")
# ...

user_controller = Blueprint("controllers/user_controller", __name__)

@user_controller.route('/signup', endpoint='signup', methods=['POST'])
@swag_from('user.yml', endpoint=f'{user_controller.name}.signup')
def signup():
    response = RestResponse()
    try:
        if request.method == "POST":
            data = request.get_json()
            newly_created_user = UserService.create_user(data.get("username"), data.get("email"),
                                                         data.get("password"), data.get("name"))
            response.data = newly_created_user
        return jsonify(response.to_dict())
    except BadRequest as err:
        response.data = GenericException(message=err.description).to_dict()
        return jsonify(response.to_dict()), err.code

As for my user.yaml:

definitions:
  User:
    type: object
    properties:
      id:
        type: string
      name:
        type: string
      username:
        type: string
      email:
        type: string
      created_at:
        type: string
      updated_at:
        type: string

paths:
  "/signup":
    post:
      parameters:
        - name: name
          in: body
          type: string
          required: true
        - name: username
          in: body
          type: string
          required: true
        - name: password
          in: body
          type: string
          required: true
        - email: email
          in: body
          type: string
          required: true
      responses:
        200:
          description: Newly created user
          schema:
            $ref: '#/definitions/User'

This is what /apidocs looks like for me: enter image description here

Appreciate all the help i can get. Thanks!

1

There are 1 best solutions below

0
On

Not exactly what you want but a way to keep your specs on a single file is to define the template_file arg on the Swagger instance. The template_file indicates the full path of the spec file. For instance, if you have defined an application factory, I'm quite sure that you'll be able to achieve something with the following example:

app.py

from flask import Flask
from flasgger import Swagger

def create_app():
    """create_app function."""
    app = Flask(__name__)

    @app.shell_context_processor
    def _shell_context():
        return {"app": app}

    swagger = Swagger(app, template_file='my_spec.yaml')

    with app.app_context():
        app.register_blueprint(my_route)

    return app

Noticed the template_file argument? You must provide the full path of the spec file an it must be an yaml file. You can use the following as an example:

my_spec.yaml

swagger: '2.0'

################################################################################
#                              API Information                                 #
################################################################################
info:
  version: '1.0.0'
  title: My Api Swagger
  description: |
    This tests many paths for my swagger

################################################################################
#                  Host, Base Path, Schemes and Content Types                  #
################################################################################
# The host (name or ip) serving the API
host: localhost:3000

# The base path on which the API is served, relative to the host. Will be prefixed to all paths. Used to control versioning
basePath: /v1/

# The transfer protocol of the API
schemes:
  - http
# Format of bodies a client can send (Content-Type)
consumes:
  - application/json
# Format of the responses to the client (Accepts)
produces:
  - application/json

################################################################################
#                                    Paths                                     #
################################################################################
paths:
  /test:
    get:
      summary: Test 1
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: request
          description: request
          required: true
      responses:
        '200':
          description: OK
  /test2:
    get:
      summary: Test 2
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: request
          description: request
          required: true
      responses:
        '200':
          description: A User object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
          description: The user ID.
        username:
          type: string
          description: The user name.

With that, all of your configuration will rely on one single file. You don't even have to use swag_from() on every endpoint.

Important to inform that the default uri to access Flasgger is:
/apidocs/#/

So in our example above, to access the swagger you'll use:
http://localhost:3000/apidocs/#/

Other resources