flask-apispec MIT flask-apispec (🥉24 · ⭐ 520) - Build and document REST APIs with Flask and apispec. MIT

Related tags

Flask flask-apispec
Overview

flask-apispec

Latest version Documentation status Travis-CI Code coverage

flask-apispec is a lightweight tool for building REST APIs in Flask. flask-apispec uses webargs for request parsing, marshmallow for response formatting, and apispec to automatically generate Swagger markup. You can use flask-apispec with vanilla Flask or a fuller-featured framework like Flask-RESTful.

Install

pip install flask-apispec

Quickstart

from flask import Flask
from flask_apispec import use_kwargs, marshal_with

from marshmallow import Schema
from webargs import fields

from .models import Pet

app = Flask(__name__)

class PetSchema(Schema):
    class Meta:
        fields = ('name', 'category', 'size')

@app.route('/pets')
@use_kwargs({'category': fields.Str(), 'size': fields.Str()})
@marshal_with(PetSchema(many=True))
def get_pets(**kwargs):
    return Pet.query.filter_by(**kwargs)

flask-apispec works with function- and class-based views:

from flask import make_response
from flask_apispec.views import MethodResource

class PetResource(MethodResource):

    @marshal_with(PetSchema)
    def get(self, pet_id):
        return Pet.query.filter(Pet.id == pet_id).one()

    @use_kwargs(PetSchema)
    @marshal_with(PetSchema, code=201)
    def post(self, **kwargs):
        return Pet(**kwargs)

    @use_kwargs(PetSchema)
    @marshal_with(PetSchema)
    def put(self, pet_id, **kwargs):
        pet = Pet.query.filter(Pet.id == pet_id).one()
        pet.__dict__.update(**kwargs)
        return pet

    @marshal_with(None, code=204)
    def delete(self, pet_id):
        pet = Pet.query.filter(Pet.id == pet_id).one()
        pet.delete()
        return make_response('', 204)

flask-apispec generates Swagger markup for your view functions and classes. By default, Swagger JSON is served at /swagger/, and Swagger-UI at /swagger-ui/.

from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_apispec.extension import FlaskApiSpec

app.config.update({
    'APISPEC_SPEC': APISpec(
        title='pets',
        version='v1',
        plugins=[MarshmallowPlugin()],
    ),
    'APISPEC_SWAGGER_URL': '/swagger/',
})
docs = FlaskApiSpec(app)

docs.register(get_pets)
docs.register(PetResource)

Documentation

https://flask-apispec.readthedocs.io/

Notes

flask-apispec is strongly inspired by Flask-RESTful and Flask-RESTplus, but attempts to provide similar functionality with greater flexibility and less code.

Comments
  • Make compatible with Marshmallow >= 3.0.0b7

    Make compatible with Marshmallow >= 3.0.0b7

    Marshmallow has changed the return value of schema.dump(), as per the note in the API docs:

    http://marshmallow.readthedocs.io/en/latest/api_reference.html#marshmallow.Schema.dump
    

    "Changed in version 3.0.0b7: This method returns the serialized data rather than a (data, errors) duple. A ValidationError is raised if obj is invalid."

    This change just checks the return value of dump(). If it's a dict, it returns that as output, otherwise, it returns the .data attribute as before.

    opened by tonycpsu 13
  • Fix compatibility with webargs 6.0

    Fix compatibility with webargs 6.0

    Follow-up to https://github.com/jmcarp/flask-apispec/issues/176 : fix compatibility with the webargs >=6.0 and remove the version restriction in setup.py.

    help wanted 
    opened by sloria 12
  • fixing up missing static file issue on swagger-ui

    fixing up missing static file issue on swagger-ui

    I added missing static files for swagger ui. There is still a tiny issue that the link under the description now says: /swagger/ and that is wrong... not sure how to fix that one....

    opened by kozmaz87 12
  • Version 0.11.1 breaks swagger-ui

    Version 0.11.1 breaks swagger-ui

    Using flask-apispec 0.11.1, browsing to /swagger-ui gives an empty page and the following 404 errors on the server:

    192.168.1.11 - - [2022-03-30 09:42:39] "GET /swagger-ui/ HTTP/1.1" 200 1232 0.003990
    192.168.1.11 - - [2022-03-30 09:42:39] "GET /flask-apispec/static/swagger-ui.css HTTP/1.1" 404 356 0.000479
    192.168.1.11 - - [2022-03-30 09:42:39] "GET /flask-apispec/static/swagger-ui-bundle.js HTTP/1.1" 404 356 0.000257
    192.168.1.11 - - [2022-03-30 09:42:39] "GET /flask-apispec/static/swagger-ui-standalone-preset.js HTTP/1.1" 404 356 0.000201
    192.168.1.11 - - [2022-03-30 09:42:39] "GET /flask-apispec/static/favicon-16x16.png HTTP/1.1" 404 356 0.000442
    

    Downgrading to 0.11.0 fixes this issue. Since the 404 errors are coming from /flask-apispec/static files, it makes sense that the cause is probably this change: https://github.com/jmcarp/flask-apispec/pull/233/files#diff-94b40f070e00775bf4e586dd00cd651e54edeeefd229a83f07335dd1b3d935b1

    opened by myouds 9
  • Bump to webargs 6.0+; drop python 2 and marshmallow 2 compatibility

    Bump to webargs 6.0+; drop python 2 and marshmallow 2 compatibility

    Details for this PR are reported in #178

    Basically:

    • changed the locations parameter in use_kwargsto reflect changes in webargs 6.0.0+ => locations:tuple -> location:str

    • Fixed tests to add a location when missing (due to default location changed in webargs, now an explicit location is required more than before)

    • Dropped compatibility with python2 (removed six, conditional requirements in setup, replaced Classifiers with python_requires, removed # -- coding: utf-8 --, and other small changes).

    Open issue: I'm unable to make 4 tests to work, all have multiple use_kwargs. At the moment these tests are commented in test_views.py (Added a "# I'M UNABLE TO MAKE THIS WORK" comment to mark them) to let other tests on complete.

    opened by mdantonio 8
  • Adds support for marshmallow `@post_load`

    Adds support for marshmallow `@post_load`

    Fixes #103

    Marshmallow @post_load decorator can be used as an object factory, to directly return an instance instead of the usual dictionary.

    This PR adds support for it, based on https://github.com/jmcarp/flask-apispec/pull/104 plus tests.

    opened by elatomo 8
  • Allow function names for end points to be camelCased

    Allow function names for end points to be camelCased

    I have no idea what the rammifications of this change is in the larger scope of this code base and its user. All I really know is that this change to flask_apispec enables it to publish swagger documentation for my project, which uses camelCased function names.

    opened by Rovanion 8
  • Returning status code results in TypeError: <Response <n> bytes [<code>]> is not JSON serializable

    Returning status code results in TypeError: bytes []> is not JSON serializable

    I'm using apispec on top of Flask-RESTful.

    Traceback:

    Traceback (most recent call last):                                                                                                                                                                                                                                                                                                                                                   [3/1724]
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 2001, in __call__             
        return self.wsgi_app(environ, start_response)                                                                
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1992, in wsgi_app                                                                               
        response = self.make_response(self.handle_exception(e))                                                      
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask_restful/__init__.py", line 273, in error_router
        return original_handler(e)                                                                                   
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1567, in handle_exception
        reraise(exc_type, exc_value, tb)                                                                          
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise            
        raise value.with_traceback(tb)                                                                            
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1989, in wsgi_app             
        response = self.full_dispatch_request()                                                                      
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1642, in full_dispatch_request   
        rv = self.handle_user_exception(e)                                                                           
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask_restful/__init__.py", line 273, in error_router
        return original_handler(e)                                                                                
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1544, in handle_user_exception
        reraise(exc_type, exc_value, tb)                                                                              
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise            
        raise value.with_traceback(tb)                                                                                         
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1640, in full_dispatch_request
        rv = self.dispatch_request()                                                                            
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask/app.py", line 1626, in dispatch_request   
        return self.view_functions[rule.endpoint](**req.view_args)                                                    
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask_restful/__init__.py", line 489, in wrapper      
        return self.make_response(data, code, headers=headers)                                                                 
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask_restful/__init__.py", line 519, in make_response         
        resp = self.representations[mediatype](data, *args, **kwargs)                                                          
      File "/home/dstaplet/venv3/lib/python3.5/site-packages/flask_restful/representations/json.py", line 22, in output_json
        dumped = dumps(data, **settings) + "\n"                     
      File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
        **kw).encode(obj)
      File "/usr/lib/python3.5/json/encoder.py", line 200, in encode
        chunks = list(chunks)
      File "/usr/lib/python3.5/json/encoder.py", line 436, in _iterencode
        o = _default(o)
      File "/usr/lib/python3.5/json/encoder.py", line 179, in default
        raise TypeError(repr(o) + " is not JSON serializable")
    TypeError: <Response 23 bytes [200 OK]> is not JSON serializable
    

    This problem can be reproduced with the following code:

    from flask import Flask
    from flask_restful import Resource, Api
    from flask_apispec import MethodResource, FlaskApiSpec
    
    
    app = Flask(__name__)
    docs = FlaskApiSpec(app)
    api = Api(app)
    
    class HelloWorld(Resource, MethodResource):
        def get(self):
            return {'hello': 'world'}, 200
    
    api.add_resource(HelloWorld, '/')
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    I've tracked the problem down to the return value in flask_apispec/wrapper.py: return self.marshal_result(unpacked, status_code)

    That marshaled data is then being passed into Flask-RESTful's make_response() method, however it doesn't expect it to be marshaled, hence the JSON error.

    Returning the unpacked tuple solves the problem for me. I'd put a PR out with this fix, however I'm not sure what the implications are for non-flask-RESTful users, so if anyone could advise on that, that would be great.

    Thanks, David

    opened by DStape 8
  • dump parameter was removed in apispec 0.20

    dump parameter was removed in apispec 0.20

    This line

    https://github.com/jmcarp/flask-apispec/blob/2f8429ca8e4fa4dd9c0dee12a721f2abd36a9778/flask_apispec/apidoc.py#L70

    should be removed since that parameter was removed in apispec 0.20.0: https://github.com/marshmallow-code/apispec/commit/7009b17f4bc9c390427ebf51dd45f2fe41dfef8a.

    See the change I made in flask-rest-api: https://github.com/Nobatek/flask-rest-api/commit/4a239d5adfd56a865c4d4901edbd3373a86a4470.

    opened by lafrech 8
  • TypeError: fields2parameters() missing 1 required keyword-only argument: 'default_in'

    TypeError: fields2parameters() missing 1 required keyword-only argument: 'default_in'

    ➜ python petstore.py 
    Traceback (most recent call last):
      File "petstore.py", line 73, in <module>
        docs.register(get_pet)
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/extension.py", line 121, in register
        resource_class_args, resource_class_kwargs)
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/extension.py", line 68, in _defer
        bound()
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/extension.py", line 136, in _register
        paths = self.view_converter.convert(target, endpoint, blueprint)
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/apidoc.py", line 42, in convert
        return [self.get_path(rule, target, **kwargs) for rule in rules]
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/apidoc.py", line 42, in <listcomp>
        return [self.get_path(rule, target, **kwargs) for rule in rules]
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/apidoc.py", line 53, in get_path
        for method, view in six.iteritems(operations)
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/apidoc.py", line 54, in <dictcomp>
        if method.lower() in (set(valid_methods) - {'head'})
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/apidoc.py", line 66, in get_operation
        'parameters': self.get_parameters(rule, view, docs, parent),
      File "/tmp/apispectest/env/lib/python3.7/site-packages/flask_apispec/apidoc.py", line 97, in get_parameters
        extra_params += converter(schema, **options) if args else []
    TypeError: fields2parameters() missing 1 required keyword-only argument: 'default_in'
    
    pip freeze
    apispec==3.0.0
    Click==7.0
    Flask==1.1.1
    flask-apispec==0.8.3
    itsdangerous==1.1.0
    Jinja2==2.10.1
    MarkupSafe==1.1.1
    marshmallow==3.2.0
    six==1.12.0
    webargs==5.5.1
    Werkzeug==0.16.0
    

    halp

    opened by d42 7
  • Register existing endpoints, plus fixup empty parameters

    Register existing endpoints, plus fixup empty parameters

    Summary

    Register rules on Init

    On calling FlaskApiSpec(app), register rules which have already been registered on app. This means that in most cases FlaskApiSpec(app) should come after calls to @app.route() and app.register_blueprint() in an app's main method

    Changes to empty parameters

    Also return an empty list of parameters instead of an object specifying an empty "body" object if a rule does not have a use_kwargs decorator.

    From:

    "parameters": [
         {
            "in": "body", 
            "name": "body", 
            "required": false, 
            "schema": {
                  "type": "object"
            }
        }
    ]
    

    to:

    "parameters": []
    

    Notes

    I would have liked to have a register_blueprint function, but I could not for the life of me figure out how to extract the functions from a flask blueprint in the way I did with app.view_functions, so instead I opted to register all methods on app at init time.

    I can also break this PR up into 2 separate PRs if you think the 2 changes should be reviewed separately.

    Lastly, I am just starting to use this library in a large existing project so I may need to make more edits as I go along and discover more features I need.

    opened by henryfjordan 7
  • Documentation is out of date

    Documentation is out of date

    The documentation page at https://flask-apispec.readthedocs.io/en/latest/ is very outdated. It indicates that the current version is 0.7.0 which was released in 2018. Since this is the first result on DuckDuckGo (second on Google) when searching for flask-apispec it should probably be updated to reflect the most recent version.

    opened by mivade 0
  • Running Quickstart code got KeyError: 'petresource'

    Running Quickstart code got KeyError: 'petresource'

    Running Quickstart guide I got the following stack trace

    Traceback (most recent call last):
      File "/Users/mac_user/Library/Application Support/JetBrains/PyCharm2022.2/scratches/api_spec_sample.py", line 58, in <module>
        docs.register(PetResource)
      File "/Users/mac_user/PycharmProjects/web-app/venv/lib/python3.9/site-packages/flask_apispec/extension.py", line 127, in register
        self._defer(self._register, target, endpoint, blueprint,
      File "/Users/mac_user/PycharmProjects/web-app/venv/lib/python3.9/site-packages/flask_apispec/extension.py", line 71, in _defer
        bound()
      File "/Users/mac_user/PycharmProjects/web-app/venv/lib/python3.9/site-packages/flask_apispec/extension.py", line 147, in _register
        paths = self.resource_converter.convert(
      File "/Users/mac_user/PycharmProjects/web-app/venv/lib/python3.9/site-packages/flask_apispec/apidoc.py", line 38, in convert
        rules = self.app.url_map._rules_by_endpoint[endpoint]
    KeyError: 'petresource'
    

    Code

    from apispec import APISpec
    from apispec.ext.marshmallow import MarshmallowPlugin
    from flask import Flask, make_response
    from flask_apispec import use_kwargs, marshal_with, MethodResource, FlaskApiSpec
    from marshmallow import Schema
    
    
    class Pet:
        def __init__(self, name, type):
            self.name = name
            self.type = type
    
    
    app = Flask(__name__)
    
    
    class PetSchema(Schema):
        class Meta:
            fields = ('name', 'category', 'size')
    
    
    class PetResource(MethodResource):
    
        @marshal_with(PetSchema)
        def get(self, pet_id):
            return Pet.query.filter(Pet.id == pet_id).one()
    
        @use_kwargs(PetSchema)
        @marshal_with(PetSchema, code=201)
        def post(self, **kwargs):
            return Pet(**kwargs)
    
        @use_kwargs(PetSchema)
        @marshal_with(PetSchema)
        def put(self, pet_id, **kwargs):
            pet = Pet.query.filter(Pet.id == pet_id).one()
            pet.__dict__.update(**kwargs)
            return pet
    
        @marshal_with(None, code=204)
        def delete(self, pet_id):
            pet = Pet.query.filter(Pet.id == pet_id).one()
            pet.delete()
            return make_response('', 204)
    
    
    app.config.update({
        'APISPEC_SPEC': APISpec(
            openapi_version='2.0',
            title='pets',
            version='v1',
            plugins=[MarshmallowPlugin()],
        ),
        'APISPEC_SWAGGER_URL': '/swagger/',
    })
    
    docs = FlaskApiSpec(app)
    docs.register(PetResource)
    
    if __name__ == "__main__":
        app.run(port=5000)
    
    

    Package Version

    Flask==2.2.2
    flask-apispec==0.11.4
    marshmallow ==3.18.0
    apispec==6.0.0
    
    opened by khadkarajesh 0
  • Flask_apispec version of `@use_kwargs` not compatible with `unknown` parameter

    Flask_apispec version of `@use_kwargs` not compatible with `unknown` parameter

    When using @use_kwargs with the unknown parameter, to be able to use the unknown parameter of the schema, as described here in the webargs documentation:

    class RandomSchema(Schema):
        class Meta:
            unknown = EXCLUDE
    

    @use_kwargs(RandomSchema, location="json", unknown=None)

    The following exception is raised: TypeError: schema2parameters() got an unexpected keyword argument 'unknown' Would it be possible for flask_apispec version of @use_kwargs to support this parameter? I could use the webargs version of @use_kwargs but it won't annotate the schema for swagger isn't it?

    opened by quaxsze 0
  • Migrate ci to github actions

    Migrate ci to github actions

    Migrate CI from deprecated travis to github actions. You just need to specify your pypi token asPYPI_API_TOKEN in the project Settings > Secrets > Actions Releases are pushed to pypi on tag creation (i think thats how it currently works?)

    The workflow is completing on my local fork: https://github.com/stufisher/flask-apispec/actions/runs/2845107965

    opened by stufisher 0
  • [FIX] Fix register_existing_resources

    [FIX] Fix register_existing_resources

    This PR contains 2 changes in FlaskApiSpec.register_existing_resources:

    • Move skipping static rules to the beginning as there is no need to try splitting names if we want to continue loop
    • Change name.split -> name.rsplit(..., maxsplit=1) to handle nested blueprints because they produce more than one dot in name
    opened by paaanic 0
Owner
Joshua Carp
Joshua Carp
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

Flask-Rebar Flask-Rebar combines flask, marshmallow, and swagger for robust REST services. Features Request and Response Validation - Flask-Rebar reli

PlanGrid 223 Dec 19, 2022
Browsable web APIs for Flask.

Flask API Browsable web APIs for Flask. Status: This project is in maintenance mode. The original author (Tom Christie) has shifted his focus to API S

Flask API 1.3k Jan 5, 2023
Flask + marshmallow for beautiful APIs

Flask-Marshmallow Flask + marshmallow for beautiful APIs Flask-Marshmallow is a thin integration layer for Flask (a Python web framework) and marshmal

marshmallow-code 770 Jan 5, 2023
Flask + marshmallow for beautiful APIs

Flask-Marshmallow Flask + marshmallow for beautiful APIs Flask-Marshmallow is a thin integration layer for Flask (a Python web framework) and marshmal

marshmallow-code 659 Feb 15, 2021
A template for Flask APIs.

FlaskAPITempate A template for a Flask API. Why tho? I just wanted an easy way to create a Flask API. How to setup First, use the template. You can do

TechStudent10 1 Dec 28, 2021
Learn REST API with Flask, Mysql and Docker

Learn REST API with Flask, Mysql and Docker A project for you to learn to work a flask REST api with docker and the mysql database manager! Table of C

Aldo Matus 0 Jul 31, 2021
REST API with Flask and SQLAlchemy. I would rather not use it anymore.

Flask REST API Python 3.9.7 The Flask experience, without data persistence :D First, to install all dependencies: python -m pip install -r requirement

Luis Quiñones Requelme 1 Dec 15, 2021
REST API with mongoDB and Flask.

Flask REST API with mongoDB py 3.10 First, to install all dependencies: python -m pip install -r requirements.txt Second, into the ./src/ folder, cop

Luis Quiñones Requelme 3 Mar 5, 2022
Curso Desenvolvimento avançado Python com Flask e REST API

Curso Desenvolvimento avançado Python com Flask e REST API Curso da Digital Innovation One Professor: Rafael Galleani Conteudo do curso Introdução ao

Elizeu Barbosa Abreu 1 Nov 14, 2021
REST API built using flask framework that used for managing bookmarks by individual users.

Bookmarks REST API REST API built using flask framework that used for managing bookmarks by individual users. API Consumers Note This app is built usi

Venkatesh Tantravahi 1 Dec 27, 2021
RestApi_flask_sql.alchemy - Product REST API With Flask & SQL Alchemy

REST API With Flask & SQL Alchemy Products API using Python Flask, SQL Alchemy and Marshmallow Quick Start Using Pipenv # Activate venv $ pipenv shell

amirwahla 1 Jan 1, 2022
A weather report application build with Python, Flask, and Geopy.

A weather report application build with Python, Flask, and Geopy. Requirements Python 3

Brandon Wallace 6 May 7, 2022
An easy way to build your flask skeleton.

Flider What is Flider Flider is a lightweight framework that saves you time by creating a MVC compliant file structure and includes basic commonly use

Trevor Engen 8 Nov 17, 2022
Boilerplate template formwork for a Python Flask application with Mysql,Build dynamic websites rapidly.

Overview English | 简体中文 How to Build dynamic web rapidly? We choose Formwork-Flask. Formwork is a highly packaged Flask Demo. It's intergrates various

aswallz 81 May 16, 2022
Lightweight library for providing filtering mechanism for your APIs using SQLAlchemy

sqlalchemy-filters-plus is a light-weight extendable library for filtering queries with sqlalchemy. Install pip install sqlalchemy-fitlers-plus Usage

Karami El Mehdi 38 Oct 5, 2022
Brandnew-flask is a CLI tool used to generate a powerful and mordern flask-app that supports the production environment.

Brandnew-flask is still in the initial stage and needs to be updated and improved continuously. Everyone is welcome to maintain and improve this CLI.

brandonye 4 Jul 17, 2022
Flask pre-setup architecture. This can be used in any flask project for a faster and better project code structure.

Flask pre-setup architecture. This can be used in any flask project for a faster and better project code structure. All the required libraries are already installed easily to use in any big project.

Ajay kumar sharma 5 Jun 14, 2022
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 310 Dec 14, 2022
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 282 Feb 11, 2021