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.

Comments
  • 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
  • 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
  • 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 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
  • 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
  • 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
  • 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
  • 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
  • Support `user:self` or `user:$id` or `user:$uri` in `PrincipalsMixin`

    Support `user:self` or `user:$id` or `user:$uri` in `PrincipalsMixin`

    Currently, the PrincipalsMixin supports generating a UserNeed based on a ToOne reference field, e.g., user:owner.

    It doesn't, however, seem to let you restrict access to generate a similar UserNeed for restricting access to a User resource directly.

    Locally, I've hacked a solution that simply supports other field types here. Unfortunately, the downstream checks assume that the field has a resource attribute, which requires adding the resource onto the ItemUri field (whether at init or in the need method calls) or changing them.

    Any thoughts on the most elegant solution @lyschoening? Happy to submit a PR if this is wanted/useful functionality.

    opened by boydgreenfield 6
  • Add basic filters for fields.Datetime()

    Add basic filters for fields.Datetime()

    @lyschoening, it seems that filtering on datetime columns are not possible right now, is that correct? And do you agree that this is a project issue that should be fixed?

    opened by brunsgaard 6
  • 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
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
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 525 Jan 1, 2023
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
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 4, 2023
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
An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API.

django-rest-client An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API. Suitable for APIs made wit

Certego 4 Aug 25, 2022
Pyrin is an application framework built on top of Flask micro-framework to make life easier for developers who want to develop an enterprise application using Flask

Pyrin A rich, fast, performant and easy to use application framework to build apps using Flask on top of it. Pyrin is an application framework built o

Mohamad Nobakht 10 Jan 25, 2022
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 162 Dec 26, 2022
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.7k Jan 4, 2023
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
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 705 Jan 4, 2023
A public API written in Python using the Flask web framework to determine the direction of a road sign using AI

python-public-API This repository is a public API for solving the problem of the final of the AIIJC competition. The task is to create an AI for the c

Lev 1 Nov 8, 2021
Daniel Vaz Gaspar 4k Jan 8, 2023
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 32 Dec 24, 2022
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 4.2k Jan 7, 2023
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
Otter is framework for creating microservices in Flask like fassion using RPC communication via message queue.

Otter Framework for microservices. Overview Otter is framework for creating microservices in Flask like fassion using RPC communication via message qu

Volodymyr Biloshytskyi 4 Mar 23, 2022
A Flask API REST to access words' definition

A Flask API to access words' definitions

Pablo Emídio S.S 9 Jul 22, 2022
Lemon is an async and lightweight API framework for python

Lemon is an async and lightweight API framework for python . Inspired by Koa and Sanic .

Joway 29 Nov 20, 2022
Endpoints is a lightweight REST api framework written in python and used in multiple production systems that handle millions of requests daily.

Endpoints Quickest API builder in the West! Endpoints is a lightweight REST api framework written in python and used in multiple production systems th

Jay Marcyes 30 Mar 5, 2022