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
You can use the mvc pattern in your flask application using this extension.

You can use the mvc pattern in your flask application using this extension. Installation Run the follow command to install mvc_flask: $ pip install mv

Marcus Pereira 37 Dec 17, 2022
The web framework for inventors

Emmett is a full-stack Python web framework designed with simplicity in mind. The aim of Emmett is to be clearly understandable, easy to be learned an

Emmett 796 Dec 26, 2022
Persistent remote applications for X11; screen sharing for X11, MacOS and MSWindows.

Table of Contents About Installation Usage Help About Xpra is known as "screen for X" : its seamless mode allows you to run X11 programs, usually on a

xpra.org 785 Dec 30, 2022
Asita is a web application framework for python based on express-js framework.

Asita is a web application framework for python. It is designed to be easy to use and be more easy for javascript users to use python frameworks because it is based on express-js framework.

Mattéo 4 Nov 16, 2021
Async Python 3.6+ web server/framework | Build fast. Run fast.

Sanic | Build fast. Run fast. Build Docs Package Support Stats Sanic is a Python 3.6+ web server and web framework that's written to go fast. It allow

Sanic Community Organization 16.7k Dec 28, 2022
Distribution Analyser is a Web App that allows you to interactively explore continuous distributions from SciPy and fit distribution(s) to your data.

Distribution Analyser Distribution Analyser is a Web App that allows you to interactively explore continuous distributions from SciPy and fit distribu

Robert Dzudzar 46 Nov 08, 2022
Flask like web framework for AWS Lambda

lambdarest Python routing mini-framework for AWS Lambda with optional JSON-schema validation. ⚠️ A user study is currently happening here, and your op

sloev / Johannes Valbjørn 91 Nov 10, 2022
Async Python 3.6+ web server/framework | Build fast. Run fast.

Sanic | Build fast. Run fast. Build Docs Package Support Stats Sanic is a Python 3.6+ web server and web framework that's written to go fast. It allow

Sanic Community Organization 16.7k Jan 08, 2023
A Simple Kivy Greeting App

SimpleGreetingApp A Simple Kivy Greeting App This is a very simple GUI App that receives a name text input from the user and returns a "Hello" greetin

Mariya 40 Dec 02, 2022
The Web framework for perfectionists with deadlines.

Django Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Thanks for checking it out. All docu

Django 67.9k Dec 29, 2022
A simple Tornado based framework designed to accelerate web service development

Toto Toto is a small framework intended to accelerate web service development. It is built on top of Tornado and can currently use MySQL, MongoDB, Pos

Jeremy Olmsted-Thompson 61 Apr 06, 2022
A tool for quickly creating REST/HATEOAS/Hypermedia APIs in python

ripozo Ripozo is a tool for building RESTful/HATEOAS/Hypermedia apis. It provides strong, simple, and fully qualified linking between resources, the a

Vertical Knowledge 198 Jan 07, 2023
A high-level framework for building GitHub applications in Python.

A high-level framework for building GitHub applications in Python. Core Features Async Proper ratelimit handling Handles interactions for you (

Vish M 3 Apr 12, 2022
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 24.7k Jan 03, 2023
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
🔥 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 216 Dec 26, 2022
🦍 The Cloud-Native API Gateway

Kong or Kong API Gateway is a cloud-native, platform-agnostic, scalable API Gateway distinguished for its high performance and extensibility via plugi

Kong 33.8k Jan 09, 2023
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 61.5k Jan 06, 2023
A familiar HTTP Service Framework for Python.

Responder: a familiar HTTP Service Framework for Python Powered by Starlette. That async declaration is optional. View documentation. This gets you a

Taoufik 3.6k Dec 27, 2022
An easy-to-use high-performance asynchronous web framework.

中文 | English 一个易用的高性能异步 web 框架。 Index.py 文档 Index.py 实现了 ASGI3 接口,并使用 Radix Tree 进行路由查找。是最快的 Python web 框架之一。一切特性都服务于快速开发高性能的 Web 服务。 大量正确的类型注释 灵活且高效的

Index.py 264 Dec 31, 2022