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
FPS, fast pluggable server, is a framework designed to compose and run a web-server based on plugins.

FPS, fast pluggable server, is a framework designed to compose and run a web-server based on plugins. It is based on top of fastAPI, uvicorn, typer, and pluggy.

Adrien Delsalle 1 Nov 16, 2021
The no-nonsense, minimalist REST and app backend framework for Python developers, with a focus on reliability, correctness, and performance at scale.

The Falcon Web Framework Falcon is a reliable, high-performance Python web framework for building large-scale app backends and microservices. It encou

Falconry 9k Jan 01, 2023
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
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 07, 2023
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框架

162 Dec 26, 2022
Web3.py plugin for using Flashbots' bundle APIs

This library works by injecting a new module in the Web3.py instance, which allows submitting "bundles" of transactions directly to miners. This is do

Flashbots 293 Dec 31, 2022
Embrace the APIs of the future. Hug aims to make developing APIs as simple as possible, but no simpler.

Read Latest Documentation - Browse GitHub Code Repository hug aims to make developing Python driven APIs as simple as possible, but no simpler. As a r

Hug API Framework 6.7k Dec 27, 2022
Free and open source full-stack enterprise framework for agile development of secure database-driven web-based applications, written and programmable in Python.

Readme web2py is a free open source full-stack framework for rapid development of fast, scalable, secure and portable database-driven web-based applic

2k Dec 31, 2022
An alternative serializer implementation for REST framework written in cython built for speed.

drf-turbo An alternative serializer implementation for REST framework written in cython built for speed. Free software: MIT license Documentation: htt

Mng 74 Dec 30, 2022
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.

Tornado Web Server Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking ne

20.9k Jan 01, 2023
JustPy is an object-oriented, component based, high-level Python Web Framework

JustPy Docs and Tutorials Introduction JustPy is an object-oriented, component based, high-level Python Web Framework that requires no front-en

927 Jan 08, 2023
A Python package to easily create APIs in Python.

API_Easy An Python Package for easily create APIs in Python pip install easy-api-builder Requiremnets: = python 3.6 Required modules -- Flask Docume

Envyre-Coding 2 Jan 04, 2022
A framework that let's you compose websites in Python with ease!

Perry Perry = A framework that let's you compose websites in Python with ease! Perry works similar to Qt and Flutter, allowing you to create componen

Linkus 13 Oct 09, 2022
Djask is a web framework for python which stands on the top of Flask and will be as powerful as Django.

Djask is a web framework for python which stands on the top of Flask and will be as powerful as Django.

Andy Zhou 27 Sep 08, 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
A microservice written in Python detecting nudity in images/videos

py-nudec py-nudec (python nude detector) is a microservice, which scans all the images and videos from the multipart/form-data request payload and sen

Michael Grigoryan 8 Jul 09, 2022
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
Web3.py plugin for using Flashbots' bundle APIs

This library works by injecting a new module in the Web3.py instance, which allows submitting "bundles" of transactions directly to miners. This is done by also creating a middleware which captures c

Georgios Konstantopoulos 294 Jan 04, 2023
FastAPI framework, high performance, easy to learn, fast to code, ready for production

FastAPI framework, high performance, easy to learn, fast to code, ready for production Documentation: https://fastapi.tiangolo.com Source Code: https:

Sebastián Ramírez 53k Jan 02, 2023
Screaming-fast Python 3.5+ HTTP toolkit integrated with pipelining HTTP server based on uvloop and picohttpparser.

Japronto! There is no new project development happening at the moment, but it's not abandoned either. Pull requests and new maintainers are welcome. I

Paweł Piotr Przeradowski 8.6k Dec 29, 2022