Flask-Potion is a RESTful API framework for Flask and SQLAlchemy, Peewee or MongoEngine

Overview

Flask-Potion

https://img.shields.io/travis/biosustain/potion/master.svg?style=flat-square https://img.shields.io/coveralls/biosustain/potion/master.svg?style=flat-square https://img.shields.io/pypi/v/Flask-Potion.svg?style=flat-square https://img.shields.io/pypi/l/Flask-Potion.svg?style=flat-square Join the chat at https://gitter.im/biosustain/potion

Flask-Potion

Description

Flask-Potion is a powerful Flask extension for building RESTful JSON APIs. Potion features include validation, model resources and routes, relations, object permissions, filtering, sorting, pagination, signals, and automatic API schema generation.

Potion ships with backends for SQLAlchemy, peewee and MongoEngine models. It is possible to add backends for other data stores, or even to use a subset of Potion without any data store at all.

API client libraries for Python and JavaScript/TypeScript (generic Node as well as AngularJS and Angular) are available.

User's Guide

The user's guide and documentation is published here:

http://potion.readthedocs.org/

Versioning

Potion will use semantic versioning from v1.0.0. Until then, the minor version is used for changes known to be breaking.

Features

  • Powerful API framework both for data-store-linked and plain resources
  • JSON-based and fully self-documenting with JSON Hyper-Schema
  • Backend integrations:
    • Flask-SQLAlchemy
    • Peewee (contributed by Michael Lavers)
    • Flask-MongoEngine
  • Filtering, sorting, pagination, validation, built right in
  • Smart system for handling relations between resources
  • Natural keys for extra simple relation querying
  • Easy-to-use, yet highly flexible, optional permissions system
  • Signals for pre- and post-processing of requests
  • Very customizable — everything is just a resource, route, or schema
  • Access APIs more easily with client libraries for Python and JavaScript/TypeScript

Example (SQLAlchemy)

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_potion import Api, ModelResource, fields
from flask_potion.routes import ItemRoute

app = Flask(__name__)
db = SQLAlchemy(app)
api = Api(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(), nullable=False)

db.create_all()

class UserResource(ModelResource):
    class Meta:
        model = User

    @ItemRoute.GET
    def greeting(self, user) -> fields.String():
        return "Hello, {}!".format(user.name)

api.add_resource(UserResource)

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

Authors

Potion is written and maintained by Lars Schöning.

Peewee backend support has been contributed by Michael Lavers.

MongoEngine backend support has been contributed by João Cardoso.

See here for the full list of contributors.

Issues
  • Initial support for Blueprints

    Initial support for Blueprints

    All of the tests should pass, and I've tested moving an app from using Potion w/o Blueprints to Blueprints with no apparent adverse effects.

    Note: One change here is that Api.__init__ now joins unnamed routes with _ rather than . (see https://github.com/refgenomics/potion/blob/blueprints/flask_potion/init.py#L159-L162) if the Api is initialized with a Blueprint. This should potentially be simplified to always use _ (. does not work with Blueprints).

    Caveats: I have not experimented with registering the same Blueprint multiple times (and if that has any unintended consequences) or registering multiple Blueprints (which this comment indicates may require a few changes https://github.com/biosustain/potion/blob/master/flask_potion/init.py#L83).

    Closes #12.

    @lyschoening – would appreciate your review and any further suggested changes.

    opened by boydgreenfield 11
  • peewee backend

    peewee backend

    Trying my hand at a peewee backend for potion. The only part I haven't figured out is the relation_add and relation_remove methods. Peewee supports many-to-many relations using a playhouse extension, which is currently implemented. But for one-to-many, for example, the relation_* methods appear to be implemented in a reverse manner to what peewee expects. For example:

    class User(Model):
        parent = ForeignKeyField('self', null=True, related_name='children')
        name = CharField()
    

    You can't do:

    parent = User.create(name='foo')
    child = User.create(name='bar')
    parent.children.add(child)
    

    Instead you would do:

    child.parent = parent
    

    But relation_add/relation_remove only provide the item attribute and not the target attribute. So I'd have to figure out a way to get that attribute via peewee in some way. Haven't found a way to do this yet.

    opened by kolanos 10
  • fix: check to avoid BinaryExpression raising `TypeError: Boolean valu…

    fix: check to avoid BinaryExpression raising `TypeError: Boolean valu…

    fix: check to avoid BinaryExpression raising TypeError: Boolean value of this clause is not defined

    When updating a value to NULL, the expression get_value('location', item, None) != value evaluates to get_value('location', item, None) != None. The result, in case the value in db isn't NULL, is a IS NOT NULL BinaryExpression.

    As documented in here, under such circumstances, using <class 'sqlalchemy.sql.elements.BinaryExpression'> as python operator raises TypeError: Boolean value of this clause is not defined.

    opened by Alain1405 10
  • Fix issue with posting with no content

    Fix issue with posting with no content

    Check if there is no content before aborting the request.

    This fixes issues with posts to endpoints that have no parameters i.e.

    @routes.ItemRoute.POST('/mark_read')
        def mark_read(self, move_task) -> fields.DateTimeString():
            move_task.mark_read()
            return move_task.seen_at
    

    Without this fix, you'd have one of two issues:

    >> http POST :5000/v2/move_tasks/667/mark_read 'Authorization: Bearer '(cat mtoken) 'Content-type: application/json'
    HTTP/1.0 400 BAD REQUEST
    Content-Length: 111
    Content-Type: application/json
    Date: Tue, 16 May 2017 19:57:03 GMT
    Server: Werkzeug/0.12.1 Python/3.6.1
    
    {
        "message": "Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)",
        "status": 400
    }
    
    >> http POST :5000/v2/move_tasks/667/mark_read 'Authorization: Bearer '(cat mtoken)
    HTTP/1.0 415 UNSUPPORTED MEDIA TYPE
    Content-Length: 60
    Content-Type: application/json
    Date: Tue, 16 May 2017 19:57:09 GMT
    Server: Werkzeug/0.12.1 Python/3.6.1
    
    {
        "message": "Unsupported Media Type",
        "status": 415
    }
    
    opened by jas32096 9
  • Support filtering for Uri and ItemUri

    Support filtering for Uri and ItemUri

    Addresses #72. Second commit if you don't want ItemUri filters on by default @lyschoening (I'd lean towards leaving this on for consistency with $id handling and because, well, otherwise users may run into it and think filtering is broken – but up to you, using a custom manager here anyhow)

    opened by boydgreenfield 8
  • Exposed schema endpoints

    Exposed schema endpoints

    Even though I protect the generated API with authentication, the schema endpoints remain open:

    decorators = [jwt_authentication_dec]
    api_blueprint = Blueprint('api', __name__)
    api = Api(api_blueprint, decorators=decorators, default_manager=principals(SQLAlchemyManager))
    

    Any GET to http://example.com/api/schema or http://example.com/api/res/schema return the schema.

    opened by Alain1405 8
  • Use of pattern_properties is not clear

    Use of pattern_properties is not clear

    I want to define an Object with patternProperties, basically to return a schema-free dict.

    Looking at the doc it seems you'd do this with fields.Object(pattern_properties={'.*': MyValueSchema}), but this just returns a dict with ".*" as key.

    What's the correct way of defining an object with patternProperties?

    opened by albertodonato 8
  • Allow passing custom message to potion exceptions

    Allow passing custom message to potion exceptions

    This uses the exception message (if defined) instead of the status code message for potion exception, allowing to provide custom messages

    opened by albertodonato 7
  • Sort instances query stably, if applicable to underlying DB implementation

    Sort instances query stably, if applicable to underlying DB implementation

    ~I'm not 100% thrilled by the naming/implementation here (happy to take suggestions @lyschoening), but~ the current Flask-Potion code can lead to odd bugs for databases that do not guarantee the return order for queries without an ORDER BY clause (e.g., Postgres).

    Specifically, we were seeing issues where we'd get duplicate records in the paginated results. The underlying issue is (depending on one's perspective) either a bug or (under/mis)documentation in Flask-SQLAlchemy's paginate method on the query.

    This PR fixes this for the RelationalManager by ordering by the primary key if no other order by clause is provided.

    Note that it may be necessary to also add the primary key to the order clause in the general _query_order_by call for Postgres. I'll try to investigate this more tomorrow Pacific time.

    opened by boydgreenfield 7
  • Question: pagination not works for me

    Question: pagination not works for me

    I have this resource:

    class Goods(ModelResource):
        class Meta:
            name = 'goods'
            model = dal.Good
            include_id = True
    
        class Schema:
            category = fields.ToOne('good_categories')
    

    If I send GET request to http://localhost:5000/goods, response doesn't contain Links and X-Total-Countheaders.

    in instances.py there is some code like this:

    class PaginationMixin(object):
      def format_response(self, data):
            if not isinstance(data, self._pagination_types): 
                return self.format(data) # always RETURN THIS, break rest of the method
            .... 
    
    opened by KhodeN 7
  • Has the project been discontinued?

    Has the project been discontinued?

    Hi,

    Has the project been discontinued or has it been migrated to another repository?

    I didn't find anything about it, thank you.

    opened by danilolmoura 1
  • Adding a custom attribute to the instances

    Adding a custom attribute to the instances

    How can we define a custom attribute for instances?

    Using this route as example:

        @ItemRoute.GET
        def is_recent(self, book) -> fields.Boolean():
            return datetime.date.today().year <= book.year_published + 10
    

    How can we define is_recent at the instances level such as: http GET :5000/book/1 would return book attributes containing is_recent: True | False as well

    opened by matdrapeau 0
  • Query to only return specific fields set

    Query to only return specific fields set

    In order to reduce the amount of data being transferred from a resource, is it possible to provide a query args to return a set of fields? Sometimes, we don't need all attributes of an object but a couple of them. It would require too many custom routes to expose the different set of attributes we would need. Here a few examples to describe it:

    /users?include_fields=['first_name', 'last_name']
    /users?include_fields=['email']
    /users?include_fields=['city', 'country']
    
    opened by matdrapeau 1
  • example `peewee_simple.py` won't run (`AttributeError: 'Metadata' object has no attribute 'rel'`)

    example `peewee_simple.py` won't run (`AttributeError: 'Metadata' object has no attribute 'rel'`)

    by running the example peewee_simple.py as is, I get

    $ python peewee_simple.py
    Traceback (most recent call last):
      File "peewee_simple.py", line 42, in <module>
        api.add_resource(BookResource)
      File "/home/m/.local/share/virtualenvs/pano-vehicle-version-config-api-JCsed19j/lib/python3.6/site-packages/flask_potion/__init__.py", line 215, in add_resource
        resource.manager = self.default_manager(resource, resource.meta.get('model'))
      File "/home/m/.local/share/virtualenvs/pano-vehicle-version-config-api-JCsed19j/lib/python3.6/site-packages/flask_potion/contrib/peewee/manager.py", line 26, in __init__
        super(PeeweeManager, self).__init__(resource, model)
      File "/home/m/.local/share/virtualenvs/pano-vehicle-version-config-api-JCsed19j/lib/python3.6/site-packages/flask_potion/manager.py", line 27, in __init__
        self._init_model(resource, model, resource.meta)
      File "/home/m/.local/share/virtualenvs/pano-vehicle-version-config-api-JCsed19j/lib/python3.6/site-packages/flask_potion/contrib/peewee/manager.py", line 63, in _init_model
        if column.primary_key or name in model._meta.rel:
    AttributeError: 'Metadata' object has no attribute 'rel'
    
    opened by maxbellec 1
  • Use xenial build environment to have python3.7 available

    Use xenial build environment to have python3.7 available

    Fixes for the tests to bring explicit support for python3.7 are coming soon.

    opened by ticosax 0
  • Fix for sqlalchemy 1.3

    Fix for sqlalchemy 1.3

    Accessing a collection not yet set doesn't raise AttributeError anymore

    opened by ticosax 0
  • Requires werkzeug >= 0.15 during test execution

    Requires werkzeug >= 0.15 during test execution

    Because it fixes NotFound Error message

    opened by ticosax 0
  • python 3.4 reached end of life

    python 3.4 reached end of life

    https://www.python.org/dev/peps/pep-0429/

    opened by ticosax 0
  • Copy ModelResource schema to route request schema with extra fields

    Copy ModelResource schema to route request schema with extra fields

    I'm wondering if there is a way, to copy the schema from a ModelResource (Inline('self)) but add some extra fields onto it for another defined Route within that Resource, specifically the request_schema for said route.

    The reasoning behind this, is that I have a route that requires the exact same properties as say, the create route, however I have a few extra ones required. This would just save having to duplicate writing out a fieldSet with all the properties from that model, just to include an extra one, and I dont want to include these extra fields on the Schema of the resource, as these are only related to this specific route and not the model.

    Some way to do something even like

    def create(self, properties: FieldSet({"extract": Inline('self'), "taxonomy_id": fields.Integer(nullable=True)}) )
    
    opened by bolerodan 4
  • AttributeError: 'module' object has no attribute 'fields'

    AttributeError: 'module' object has no attribute 'fields'

    This error is raised when i try to instantiate the InlineModel class.

    Extension version: 0.16.0

    code

    from flask_potion.contrib import alchemy
    
    
        @ItemRoute.GET('/collapsed_credit_usage_user', Schema=FieldSet({
            'user': alchemy.fields.InlineModel({
                'id': fields.Integer(description='id do usuario')
            }, model=model_user.User)
            })
        )
        def collapsed_credit_usage_user(self, invoice, user):
            pass
    
    

    Can anyone explain why is this happening?

    opened by lohxx 0
Releases(v0.16.0)
  • v0.16.0(Jan 10, 2019)

    Breaking Changes

    • The timezone is now always included with fields.DateTimeString and defaults to UTC with native datetime objects. (Thanks @albertodonato)

    Features

    • The sort_attribute meta class attribute of a resource can be used to change the default pagination sort order, which otherwise is id_attribute ascending. Descending order is supported. (Thanks @albertodonato and @luord)
    class SpamResource(Resource):
        class Meta:
            model = Spam
            sort_attribute = 'name', True
    

    Bugfixes

    • Fix field.Object(pattern_properties={}) pattern definition
    • Fix JSONSchema of patchable fields. (Thanks @bjornt)
    Source code(tar.gz)
    Source code(zip)
  • v0.15.1(Oct 9, 2018)

    Features

    • Allow setting custom error message for PotionException
    • Allow setting success_code argument with route decorator for a custom HTTP status code

    Bugfixes

    • Fix schema reference for cross resource fields.Inline
    Source code(tar.gz)
    Source code(zip)
  • v0.14.0(Feb 24, 2017)

    Features

    • Improve debug error messages on IntegrityError in SQLAlchemy

    Bugfixes

    • Fix IntegrityError in SQLAlchemy on update, delete not being handled properly

    • Use ID column for stable sort defaults in SQLAlchemy

      This resolves issues with pagination when sorting by a non-unique column.

    Source code(tar.gz)
    Source code(zip)
  • v0.13.0(Jan 26, 2017)

    Breaking changes

    • Fixes Api.decorators not being applied to "/schema"

      This means if you have an authenticated API your "/schema" endpoint is no longer available to unauthenticated users.

    Features

    • Adds POTION_DECORATE_SCHEMA_ENDPOINTS configuration option

      Setting this option to False makes the "/schema" endpoint and "/{resource_name}/schema" endpoints available in an Api protected using Api.decorators.

    • Adds support for user:$id and user:$uri needs with Flask-Principal

    Bugfixes

    • Fixes TypeError when applying PATCH to some SQLAlchemy native values
    • Fixes various inconsistencies in the JSON schemas
    Source code(tar.gz)
    Source code(zip)
  • v0.12.6(May 25, 2016)

  • v0.12.4(Apr 12, 2016)

  • v0.12.3(Mar 16, 2016)

    Features

    • Filters are now inherited (e.g. Email and Uri work like String because they inherits from it)
    • Added filters for DateString, DateTimeString (Thanks, @boydgreenfield)
    • Implemented ItemUri.convert(). This means you can now specify filters for the "$uri" field. For more info, see below. (Thanks, @boydgreenfield)

    Bugfixes

    • Fixes specifying custom filters using Meta.filters

    Enabling filtering by "$uri" in a resource:

            class Meta:
                filters = {
                    '$uri': {
                        None: filters.EqualFilter,
                        'eq': filters.EqualFilter,
                        'ne': filters.NotEqualFilter,
                        'in': filters.InFilter
                    },
                    '*': True
                }
    

    Note that filters needs to correspond to the manager implementation you are using, e.g. flask_potion.contrib.alchemy.filters. If you want to enable the filter in multiple resources, you can use a Meta mixin.

    Source code(tar.gz)
    Source code(zip)
  • v0.12.2(Feb 24, 2016)

    Features

    • Adds fields.UUID field for UUID strings in canonical form
    • Support for PostgreSQL-dialect UUID columns in the SQLAlchemyManager

    (Thanks, @shipperizer for both features)

    Bugfixes

    • id_converter is now always inferred from id_field_class unless it is specified manually.
    Source code(tar.gz)
    Source code(zip)
  • v0.12.1(Feb 8, 2016)

  • v0.12.0(Jan 19, 2016)

    Features

    • Refactored logic for inferring the id attribute and its field class type

    • Support for decimal.Decimal used for Numeric fields by PostgreSQL drivers (Thanks, @brunsgaard)

    • Updated the configuration of fields when used with a FieldSet:

      The io attribute on fields can now have 'c' (create) and 'u' (update) in addition to 'r' and 'w'. This allows for e.g fields that can only be written once on create 'cr' or are generated by the server but can then be updated 'ru'.

    Source code(tar.gz)
    Source code(zip)
  • v0.11.2(Dec 31, 2015)

  • v0.11.1(Dec 2, 2015)

  • v0.11.0(Dec 1, 2015)

    Features

    • Rewrote the filters implementation. They are now class-based and can be extended much more easily. A couple of new built-in filters for dates and strings have been added.
    • Routes are now internally referenced by their "rel" instead of their attribute name on the resource
    • Added Meta.exclude_routes option for excluding routes

    Bugfixes

    • Fixes an issue with peewee 2.7

    Breaking changes

    • Moved all backends from backends.BACKEND_NAME to contrib.BACKEND_NAME
    • fields.sa.InlineModel moved to contrib.alchemy.fields.InlineModel
    • Removed PrincipalsManager and PrincipalsResource. Now need to make own manager using principals(SQLAlchemyManager)
    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Oct 22, 2015)

  • v0.9.0(Oct 12, 2015)

  • v0.8.1(Oct 7, 2015)

Owner
DTU Biosustain
The Novo Nordisk Foundation Center for Biosustainability
DTU Biosustain
Daniel Vaz Gaspar 3.5k Oct 22, 2021
NO LONGER MAINTAINED - A Flask extension for creating simple ReSTful JSON APIs from SQLAlchemy models.

NO LONGER MAINTAINED This repository is no longer maintained due to lack of time. You might check out the fork https://github.com/mrevutskyi/flask-res

null 1k Oct 20, 2021
NO LONGER MAINTAINED - A Flask extension for creating simple ReSTful JSON APIs from SQLAlchemy models.

NO LONGER MAINTAINED This repository is no longer maintained due to lack of time. You might check out the fork https://github.com/mrevutskyi/flask-res

null 1k Jan 15, 2021
Serverless Python

Zappa - Serverless Python About Installation and Configuration Running the Initial Setup / Settings Basic Usage Initial Deployments Updates Rollback S

Rich Jones 11.8k Oct 22, 2021
Serverless Python

Zappa - Serverless Python About Installation and Configuration Running the Initial Setup / Settings Basic Usage Initial Deployments Updates Rollback S

Rich Jones 11.7k Feb 17, 2021
APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects

APIFlask APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects. It's easy to use, highly customizable, ORM/O

Grey Li 316 Oct 15, 2021
Fully featured framework for fast, easy and documented API development with Flask

Flask RestPlus IMPORTANT NOTICE: This project has been forked to Flask-RESTX and will be maintained by by the python-restx organization. Flask-RESTPlu

Axel H. 2.6k Oct 20, 2021
Fully featured framework for fast, easy and documented API development with Flask

Flask RestPlus IMPORTANT NOTICE: This project has been forked to Flask-RESTX and will be maintained by by the python-restx organization. Flask-RESTPlu

Axel H. 2.5k Feb 17, 2021
Restful API framework wrapped around MongoEngine

Flask-MongoRest A Restful API framework wrapped around MongoEngine. Setup from flask import Flask from flask_mongoengine import MongoEngine from flask

Close 517 Jun 24, 2021
Restful API framework wrapped around MongoEngine

Flask-MongoRest A Restful API framework wrapped around MongoEngine. Setup from flask import Flask from flask_mongoengine import MongoEngine from flask

Close 505 Feb 11, 2021
Swagger/OpenAPI First framework for Python on top of Flask with automatic endpoint validation & OAuth2 support

Connexion Connexion is a framework that automagically handles HTTP requests based on OpenAPI Specification (formerly known as Swagger Spec) of your AP

Zalando SE 3.8k Oct 22, 2021
Swagger/OpenAPI First framework for Python on top of Flask with automatic endpoint validation & OAuth2 support

Connexion Connexion is a framework that automagically handles HTTP requests based on OpenAPI Specification (formerly known as Swagger Spec) of your AP

Zalando SE 3.5k Feb 17, 2021
Web APIs for Django. 🎸

Django REST framework Awesome web-browsable Web APIs. Full documentation for the project is available at https://www.django-rest-framework.org/. Fundi

Encode 22k Oct 15, 2021
The Python micro framework for building web applications.

Flask Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to co

The Pallets Projects 56.9k Oct 17, 2021
Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints.

Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints. check parameters and generate API documents automatically. Flask Sugar是一个基于flask,pyddantic,类型注解的API框架, 可以检查参数并自动生成API文档

null 53 Oct 20, 2021
A boilerplate Flask API for a Fullstack Project with some additional packages and configuration prebuilt. ⚙

Flask Boilerplate to quickly get started with production grade flask application with some additional packages and configuration prebuilt.

Yasser Tahiri 27 Oct 19, 2021
Official mirror of https://gitlab.com/pgjones/quart

Quart Quart is an async Python web microframework. Using Quart you can, render and serve HTML templates, write (RESTful) JSON APIs, serve WebSockets,

Phil Jones 951 Oct 15, 2021
Flask + Docker + Nginx + Gunicorn + MySQL + Factory Method Pattern

This Flask project is reusable and also an example of how to merge Flask, Docker, Nginx, Gunicorn, MySQL, new: Flask-RESTX, Factory Method design pattern, and other optional dependencies such as Dynaconf, Marshmallow, SQLAlchemy, Faker, PyMySQL, Pytest, etc... which are installed inside the virtual environment "env_flask".

Facundo Padilla 19 Sep 19, 2021
🔥 Fire up your API with this flamethrower

?? Fire up your API. Documentation: https://flama.perdy.io Flama Flama aims to bring a layer on top of Starlette to provide an easy to learn and fast

José Antonio Perdiguero 182 Oct 18, 2021