Allan K Liu
Allan K Liu

Reputation: 503

Flask-appbuilder RESTful API vs Flask-RESTful API

I am trying to use Flask-appbuilder in an IoT project. So, FAB is used for rapid application buildup and we need dedicated RESTful API for Mobile App and 3rd party service suppliers.

In FAB, there is an implementation for RESTful API, as subclass of BaseCURDView. Most URL is defined as

http://host//api/list

If the mobile app acts as an user agent like browser, it collect username/password, login and access FAB's RESTful API, then permissions, url is not a big deal, everything can follow B/S programming. AKA, all security model is based upon cookie and session. Most of the request information are inside the flask.g.user/flask.request.*.

If the webapp has to support more standard style RESTful API, as described in flask books by miguel. The external webapp has to embed the api key/secret to specified url to exchange token, then use token in header or http parameters to access resources for CRUD operations.

http://host/api/v1/get_token
header:api_key:balabalabala
header:api_secret:abcdefxyz
return {'token':'1234567890'}


http://host/api/v1/resource
header:token:1234567890
return {'resource':'abcdefghijk'}

I have successfully merged them together in FAB's views.py.

from flask import render_template
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder import ModelView, BaseView, expose
from app import appbuilder, db

from flask import Flask, jsonify 
from flask import abort 
from flask import make_response 
from flask import request 
from flask import url_for 

tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good python tutorial',
        'done': False
    }
] 

def make_public_task(task):
    new_task = {}
    for field in task:
        if field == 'id':
            new_task['uri'] = url_for('get_task', task_id=task['id'], _external=True)
        else:
            new_task[field] = task[field]
    return new_task


class ApiView(BaseView):
    route_base = "/api/v1"
    default_view = "index"

    @expose("/index")
    def index(self):
        #return jsonify({'tasks': map(make_public_task, tasks)}) 
        print repr(request.args)
        print repr(request.method)
        print repr(request.headers)
        return jsonify(tasks)

    @expose("/get_token")
    def get_token(self):
        print repr(request.headers)
        return jsonify({'res': True})

    @expose("/get_resource")
    def get_resource(self):
        return jsonify({'res': False})

    @expose("/del_resource")
    def del_resource(self):
        return jsonify({'res': False})

"""
    Application wide 404 error handler
"""
@appbuilder.app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html', base_template=appbuilder.base_template, appbuilder=appbuilder), 404

db.create_all()

appbuilder.add_view_no_menu(ApiView())

Yes, I can implement standard RESTful API just I did in another flask project with http headers and custom queries with sqlalchemy. But I am not sure if it is the proper way to do that. Since most of the data are requested directly from sqlalchemy raw queries, they are quite different programming experiences.

Open for any suggestions, before moving forward.

Upvotes: 0

Views: 1563

Answers (1)

Allan K Liu
Allan K Liu

Reputation: 503

Actually FAB's REST API is designed for AJAX, so for mobile app and 3rd party applications, we need a seperate RESTful API, which can follow flask megatutorial and best practice and resue REST-auth library from Miguel.

FAB can work with both anyway.

Upvotes: 0

Related Questions