Browsable web APIs for Flask.

Related tags

Flaskflask-api
Overview

Flask API

Browsable web APIs for Flask.

Unix Build Status Coverage Status Scrutinizer Code Quality PyPI Version

Status: This project is in maintenance mode. The original author (Tom Christie) has shifted his focus to API Star. Passing PRs will still be considered for releases by the maintainer (Jace Browning).

Overview

Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what Django REST framework offers. It gives you properly content-negotiated responses and smart request parsing:

Screenshot

Installation

Requirements:

  • Python 3.6+
  • Flask 1.1.+

Install using pip:

$ pip install Flask-API

Import and initialize your application:

from flask_api import FlaskAPI

app = FlaskAPI(__name__)

Responses

Return any valid response object as normal, or return a list or dict.

@app.route('/example/')
def example():
    return {'hello': 'world'}

A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser, it'll default to the browsable API HTML.

Requests

Access the parsed request data using request.data. This will handle JSON or form data by default.

@app.route('/example/')
def example():
    return {'request data': request.data}

Example

The following example demonstrates a simple API for creating, listing, updating and deleting notes.

from flask import request, url_for
from flask_api import FlaskAPI, status, exceptions

app = FlaskAPI(__name__)


notes = {
    0: 'do the shopping',
    1: 'build the codez',
    2: 'paint the door',
}

def note_repr(key):
    return {
        'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key),
        'text': notes[key]
    }


@app.route("/", methods=['GET', 'POST'])
def notes_list():
    """
    List or create notes.
    """
    if request.method == 'POST':
        note = str(request.data.get('text', ''))
        idx = max(notes.keys()) + 1
        notes[idx] = note
        return note_repr(idx), status.HTTP_201_CREATED

    # request.method == 'GET'
    return [note_repr(idx) for idx in sorted(notes.keys())]


@app.route("/<int:key>/", methods=['GET', 'PUT', 'DELETE'])
def notes_detail(key):
    """
    Retrieve, update or delete note instances.
    """
    if request.method == 'PUT':
        note = str(request.data.get('text', ''))
        notes[key] = note
        return note_repr(key)

    elif request.method == 'DELETE':
        notes.pop(key, None)
        return '', status.HTTP_204_NO_CONTENT

    # request.method == 'GET'
    if key not in notes:
        raise exceptions.NotFound()
    return note_repr(key)


if __name__ == "__main__":
    app.run(debug=True)

Now run the webapp:

$ python ./example.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader

You can now open a new tab and interact with the API from the command line:

$ curl -X GET http://127.0.0.1:5000/
[{"url": "http://127.0.0.1:5000/0/", "text": "do the shopping"},
 {"url": "http://127.0.0.1:5000/1/", "text": "build the codez"},
 {"url": "http://127.0.0.1:5000/2/", "text": "paint the door"}]

$ curl -X GET http://127.0.0.1:5000/1/
{"url": "http://127.0.0.1:5000/1/", "text": "build the codez"}

$ curl -X PUT http://127.0.0.1:5000/1/ -d text="flask api is teh awesomez"
{"url": "http://127.0.0.1:5000/1/", "text": "flask api is teh awesomez"}

You can also work on the API directly in your browser, by opening http://127.0.0.1:5000/. You can then navigate between notes, and make GET, PUT, POST and DELETE API requests.

Comments
  • Towards 1.0

    Towards 1.0

    I've been doing some preliminary work on a new Flask API framework. Given that I've never maintained Flask-API, and it's only ever been a very weak port of a few bits of REST framework, I'm strongly considering using this project for the latest work, and releasing it as a 1.0 version.

    I'm really pleased with the incoming work, which is super simple, but features automatic client libraries & command line tool, plus schema generation in a nice & agnostic way (so, eg provide Swagger, API Blueprint, or any other schema type documentation out of the box)

    I figure it's worth raising the issue here to see how folks would feel about an incompatible 1.0 release, if it was something that was actually going to push things forwards and be a release that I was actually using and significantly invested in for a change.

    Any thoughts?

    question 
    opened by tomchristie 14
  • New maintainer?

    New maintainer?

    @tomchristie has mentioned in #31 and #32 that he is not currently maintaining this project. I'm interested in helping support a 0.6.x release with bug fixes. Can we talk about which of these options is best to move forward on this repo:

    1. contributors create pull requests and @tomchristie merges
    2. add additional collaborators with push permission
    3. transfer ownership of this repo to someone else
    4. create a GitHub organization for this repo and add collaborators to that
    opened by jacebrowning 11
  • AttributeError: 'tuple' object has no attribute 'items'

    AttributeError: 'tuple' object has no attribute 'items'

    Related to #58, I am now hitting a spot where blueprint_handlers and app_handlers are both empty tuples with Flask 0.11 and 0.11.1, so the fix in #59 actually causes a new issue:

    Traceback (most recent call last):
      File ".../env/lib/python3.5/site-packages/flask/app.py", line 2000, in __call__
        return self.wsgi_app(environ, start_response)
      File ".../env/lib/python3.5/site-packages/flask/app.py", line 1991, in wsgi_app
        response = self.make_response(self.handle_exception(e))
      File ".../env/lib/python3.5/site-packages/flask/app.py", line 1567, in handle_exception
        reraise(exc_type, exc_value, tb)
      File ".../env/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
        raise value
      File ".../env/lib/python3.5/site-packages/flask/app.py", line 1988, in wsgi_app
        response = self.full_dispatch_request()
      File ".../env/lib/python3.5/site-packages/flask/app.py", line 1641, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File ".../env/lib/python3.5/site-packages/flask_api/app.py", line 97, in handle_user_exception
        for typecheck, handler in chain(blueprint_handlers.items(), app_handlers.items()):
    AttributeError: 'tuple' object has no attribute 'items'
    
    help wanted 
    opened by jacebrowning 9
  • No content responses should accept not only an empty string

    No content responses should accept not only an empty string

    Is confusing, specially when trying to keep consistence beetwen returned data types, that to be able to send a 204 HTTP status code is needed to pass only an empty string not being valid and empty dictionary or None value for example.

    Could be more flexible to support other "empty/no content" values.

    help wanted 
    opened by jesugmz 7
  • Support for non-English string

    Support for non-English string

    I rewrite the notes in example.py

    notes = {
        0: '购物',
        1: 'build the codez',
        2: 'paint the door',
    }
    

    I get an exception: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 16: ordinal not in range

    opened by jacktan1991 7
  • v0.7.0 release breaks expected behavior

    v0.7.0 release breaks expected behavior

    One of the chief reasons we use FlaskAPI at Qualcomm is because of how easy it makes returning JSON content from a simple function. However, it seems something between v0.6.9 and v0.7.0 broke this behavior; if you try to return data that isn't a dict or list from a Flask handler, you get a text/html response back, whereas you used to get an application/json response back.

    In v0.6.9:

    [[email protected]]$ curl --include --insecure https://10.52.252.96:3519/api/v1/mapping/test_mapping/key1
    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 8
    Access-Control-Allow-Origin: *
    Server: Werkzeug/0.12.1 Python/3.5.3
    Date: Tue, 11 Apr 2017 03:40:13 GMT
    Connection: keep-alive
    
    "value1"
    

    In v0.7.0:

    [[email protected]]$ curl --include --insecure https://10.52.252.96:3519/api/v1/mapping/test_mapping/key1
    HTTP/1.0 200 OK
    Content-Type: text/html; charset=utf-8
    Content-Length: 6
    Access-Control-Allow-Origin: *
    Server: Werkzeug/0.12.1 Python/3.5.3
    Date: Tue, 11 Apr 2017 03:45:21 GMT
    Connection: keep-alive
    
    value1
    

    It's OK if the new behavior is intentional -- if so, just please provide a way to get the old behavior back, because we are depending on it.

    opened by skaven81 6
  • zip_safe flag not set; analyzing archive contents...ValueError: bad marshal data (unknown type code)

    zip_safe flag not set; analyzing archive contents...ValueError: bad marshal data (unknown type code)

    When installing Flask-API as a requirement for another application via python setup.py install I get:

    zip_safe flag not set; analyzing archive contents...
    flask_api.tests.__init__: module references __file__
    Traceback (most recent call last):
    

    ....

    ValueError: bad marshal data (unknown type code)
    
    opened by james-fanduel 6
  • Request.parser_classes and Request.renderer_classes are hardcoded to be default

    Request.parser_classes and Request.renderer_classes are hardcoded to be default

    This looks like a very strange hard-code of the request's configuration:

        def preprocess_request(self):
            request.parser_classes = self.api_settings.DEFAULT_PARSERS
            request.renderer_classes = self.api_settings.DEFAULT_RENDERERS
            return super(FlaskAPI, self).preprocess_request()
    

    so it makes it impossible to extend the Request class and set it's classes attributes to a different from default values

    opened by bubenkoff 6
  • JSONRendered to use app's json_encoder

    JSONRendered to use app's json_encoder

    It would be good if one could change the default json_encoder class used for serialization. The one which is currently used is flask.json.JSONEncoder. Trying to change it like so

    app = FlaskAPI('the_app')
    app.json_encoder = CustomJSONEncoder
    

    does not have any effect.

    https://github.com/tomchristie/flask-api/blob/1.0/flask_api/renderers.py#L15

    Wouldn't something like

            return json.dumps(data, cls=current_app.json_encoder, ensure_ascii=False)
    

    instead of

            return json.dumps(data, cls=JSONEncoder, ensure_ascii=False)
    

    solve the problem?

    help wanted 
    opened by lalstef 5
  • fix for #58

    fix for #58

    I came across the issue recently for #58 as well, and saw the change was relatively simple.

    I added some tests in there as well to check the custom error handler was working okay, looks good on my end.

    opened by dutronlabs 5
  • pypi package for 0.6.6 contains .pyc files.

    pypi package for 0.6.6 contains .pyc files.

    I am getting ValueError: bad marshal data (unknown type code) during install of an application with a requirement on 0.6.6.

    This looks like it could be due to the pypi package containing .pyc files.

    opened by james-fanduel 5
  • Bump certifi from 2022.9.24 to 2022.12.7

    Bump certifi from 2022.9.24 to 2022.12.7

    Bumps certifi from 2022.9.24 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies python 
    opened by dependabot[bot] 0
  • How could Flask 2.x's MethodView be used with this?

    How could Flask 2.x's MethodView be used with this?

    Since Flask 2.x there has been a MethodView class that allows users to define api method-based classes for entity management. Can an example be provided showing how to use these new class-centric routes with flask-api?

    Example MethodView:

    from flask import current_app as app
    from flask.views import MethodView
    
    class ExampleEndpoint(MethodView):
        """ Example of a class inheriting from flask.views.MethodView 
    
        All 5 request methods are available at /api/example/<entity>
        """
        def get(self, entity):
            """ Responds to GET requests """
            return "Responding to a GET request"
    
        def post(self, entity):
            """ Responds to POST requests """
            return "Responding to a POST request"
    
        def put(self, entity):
            """ Responds to PUT requests """
            return "Responding to a PUT request"
    
        def patch(self, entity):
            """ Responds to PATCH requests """
            return "Responding to a PATCH request"
    
        def delete(self, entity):
            """ Responds to DELETE requests """
            return "Responding to a DELETE request"
    
    app.add_url_rule("/api/example/<entity>", view_func=ExampleEndpoint.as_view("example_api"))
    
    
    opened by caffeinatedMike 1
  • Using it with flask-restful breaks rendering

    Using it with flask-restful breaks rendering

    Hi,

    I've tried the module using traditional route definition and it works perfectly.

    But when using flask-restful to build my API, the rendering is broken and I can't longer get the browsable API. I then just have a poor text (http response) on a blank page.

    I think that's because I use classes instead of functions for my routes, with HTTP methods directly defined as route's class methods, and therefore flask-api behaves an unexpectable way for rendering.

    Has someone here tried that please?

    Regards, Eugène NG

    opened by papiveron 3
  • PUT on the browsable API renderer actually performs POST

    PUT on the browsable API renderer actually performs POST

    Given a route that accepts PUT and GET but not POST, the browsable API renderer performs a POST despite the button very clearly showing PUT.

    image image

    from flask_api import FlaskAPI
    
    app = FlaskAPI(__name__)
    
    @app.route("/", methods=["PUT", "GET"])
    def index():
        return {}
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    requirements.txt

    bug help wanted 
    opened by andreareina 7
  • Flask API XML output?

    Flask API XML output?

    Hello, sorry if this would not be the place to ask for help..

    But could I use Flask API for XML output?

    Any chance for how I could modify the Flask Code to Flask API?

    from flask import Flask, Response
    
    
    class MyResponse(Response):
        default_mimetype = 'application/xml'
    
    class MyFlask(Flask):
        response_class = MyResponse
    
        
    app = MyFlask(__name__)
    
    
    @app.route('/')
    def get_data():
        return '''<?xml version="1.0" encoding="UTF-8"?>
    <person>
        <name>John Smith</name>
    </person>
    '''
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    question 
    opened by bbartling 0
Cross Origin Resource Sharing ( CORS ) support for Flask

Flask-CORS A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible. This package has a simple philosoph

Cory Dolphin 803 Jan 01, 2023
Adds Injector support to Flask.

Flask-Injector Adds Injector support to Flask, this way there's no need to use global Flask objects, which makes testing simpler. Injector is a depend

Alec Thomas 246 Dec 28, 2022
Rich implementation for Flask

Flask Rich Implements the Rich programming library with Flask. All features are toggleable, including: Better logging Colorful tracebacks Usage Import

BD103 13 Jun 06, 2022
Pf-flask-rest-com - Flask REST API Common Implementation by Problem Fighter Library

In the name of God, the Most Gracious, the Most Merciful. PF-Flask-Rest-Com Docu

Problem Fighter 3 Jan 15, 2022
A basic CRUD application built in flask using postgres as database

flask-postgres-CRUD A basic CRUD application built in flask using postgres as database Taks list Dockerfile Initial docker-compose - It is working Dat

Pablo Emídio S.S 9 Sep 25, 2022
SqlAlchemy Flask-Restful Swagger Json:API OpenAPI

SAFRS: Python OpenAPI & JSON:API Framework Overview Installation JSON:API Interface Resource Objects Relationships Methods Custom Methods Class Method

Thomas Pollet 365 Jan 06, 2023
A simple demo of using aiogram + async sqlalchemy 1.4+

aiogram-and-sqlalchemy-demo A simple demo of using aiogram + async sqlalchemy 1.4+ Used tech: aiogram SQLAlchemy 1.4+ PostgreSQL as database asyncpg a

Aleksandr 68 Dec 31, 2022
YAML-formatted plain-text file based models for Flask backed by Flask-SQLAlchemy

Flask-FileAlchemy Flask-FileAlchemy is a Flask extension that lets you use Markdown or YAML formatted plain-text files as the main data store for your

Siddhant Goel 20 Dec 14, 2022
Rubik's cube assistant on Flask webapp

webcube Rubik's cube assistant on Flask webapp. This webapp accepts the six faces of your cube and gives you the voice instructions as a response. Req

Yash Indane 56 Nov 22, 2022
A web application for a fake pizza store, built in Python with Flask and PostgreSQL.

✨ Pizza Pizza - Pizza Store ✨ A web application for a fake Pizza Store, the app let you create an account and order pizza, complements or drinks. Buil

Bonnie Fave 6 Dec 18, 2022
A python package for integrating ripozo with Flask

flask-ripozo This package provides a dispatcher for ripozo so that you can integrate ripozo with Flask. As with all dispatchers it is simply for getti

Vertical Knowledge 14 Dec 03, 2018
Forum written for learning purposes in flask and sqlalchemy

Flask-forum forum written for learning purposes using SQLalchemy and flask How to install install requirements pip install sqlalchemy flask clone repo

Kamil 0 May 23, 2022
REST API with mongoDB and Flask.

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

Luis Quiñones Requelme 3 Mar 05, 2022
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

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

PlanGrid 223 Dec 19, 2022
A web application that consists of a collection of board games

PyBoardGame About This website contains a collection of board games for users to enjoy, as well as various guides for the games. The web app is built

Larry Shi 0 Aug 11, 2021
A flask template with Bootstrap 4, asset bundling+minification with webpack, starter templates, and registration/authentication. For use with cookiecutter.

cookiecutter-flask A Flask template for cookiecutter. (Supports Python ≥ 3.6) See this repo for an example project generated from the most recent vers

4.3k Dec 29, 2022
Flask Apps - Open-Source And Paid | AppSeed

Flask Apps Open-Source web apps built with automation tools, HTML parsing and boilerplated code in Flask - - Provided by AppSeed App Generator. What i

App Generator 120 Oct 04, 2022
Set up a modern flask web server by running one command.

Build Flask App · Set up a modern flask web server by running one command. Installing / Getting started pip install build-flask-app Usage build-flask-

Kushagra Bainsla 5 Jul 16, 2022
Adds SQLAlchemy support to Flask

Flask-SQLAlchemy Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application. It aims to simplify using SQLAlchemy

The Pallets Projects 3.9k Dec 29, 2022
A YouTube webscraper made with flask.

YouTube Webscraper This website is for you to check all the stats on your favorite Youtube video! Technologies Python Flask HTML CSS Pafy Contributing

Proconsulates 3 Nov 25, 2021