flasgger / flasgger

Easy OpenAPI specs and Swagger UI for your Flask API
http://flasgger.pythonanywhere.com/
MIT License
3.61k stars 524 forks source link

Enable adding schema definitions not linked to a specific endpoint #128

Open roo-oliv opened 7 years ago

roo-oliv commented 7 years ago

Currently, when you have endpoints for managing an entity, the entity's schema which will be used in these endpoints needs to be explicitly defined in the specs of one of these endpoints. For all the other endpoints you can just reference the schema with the $ref: '#/definitions/Entity' syntax. But it would be nicer to be able to just reference the schema in all the endpoints, avoiding to bloat the docstring of one of the endpoints with the entity's schema.

The way I see to solve this is to enable providing definitions apart the endpoint specs. So you can declare the schemas independent from the endpoints.

I don't have a clear idea on how is the best way to do this.

A method to include a definition may be a good approach:

# dogs_api.py
from flask import Blueprint, jsonify
from flasgger import Swagger
from my_project import db

swagger = Swagger()
dogs = Blueprint('dogs', __name__)

# include Dog schema definition
swagger.include_definition('dog_schema.yml')

@dogs.route('/post', methods=['POST'])
@swagger.validate('Dog')
def create_dog():
    """
    Dog creation endpoint
    ---
    tags:
      - dogs
    summary: Creates a dog
        consumes:
          - application/json
        produces:
          - application/json
        parameters:
          - in: body
            name: body
            description:
              Dog object that needs to be persisted to the database
            required: true
            schema:
              $ref: '#/definitions/Dog'
        responses:
          200:
            description: Successful operation
          400:
            description: Invalid input
    """
    dog = db.insert(request.json)
    return jsonify(dog), HTTPStatus.OK

Another approach (non exclusive with the prior approach) would be allowing people to use the module's docstring to declare swagger specifications as well:

# dogs_api.py
"""
Dogs API
---
definitions:
  Dog:
    required:
      - name
      - address
    properties:
      name:
        description: The dog's name
        type: string
        example: Tobby
      address:
        description: The dog's house address
        type: string
        example: Water St., 226 - San Francisco, CA
"""
from flask import Blueprint, jsonify
from flasgger import Swagger
from my_project import db

swagger = Swagger()
dogs = Blueprint('dogs', __name__)

@dogs.route('/post', methods=['POST'])
@swagger.validate('Dog')
def create_dog():
    """
    Dog creation endpoint
    ---
    tags:
      - dogs
    summary: Creates a dog
        consumes:
          - application/json
        produces:
          - application/json
        parameters:
          - in: body
            name: body
            description:
              Dog object that needs to be persisted to the database
            required: true
            schema:
              $ref: '#/definitions/Dog'
        responses:
          200:
            description: Successful operation
          400:
            description: Invalid input
    """
    dog = db.insert(request.json)
    return jsonify(dog), HTTPStatus.OK
mtronrd commented 7 years ago

See https://github.com/rochacbruno/flasgger/pull/40 and https://github.com/rochacbruno/flasgger/issues/108

roo-oliv commented 7 years ago

Thanks @mtronrd, I missed the Swagger::definition decorator because it was removed from README at: https://github.com/rochacbruno/flasgger/commit/c2b660fa7c745286d1222d55c34cd524a20c7919

I'm not sure why it was removed, but I think it was unintentionally removed when @rochacbruno was making some broad changes to the README file. I'll double check and then open a PR to re-add it to the README.