jfinkels / flask-restless

NO LONGER MAINTAINED - A Flask extension for creating simple ReSTful JSON APIs from SQLAlchemy models.
https://flask-restless.readthedocs.io
GNU Affero General Public License v3.0
1.02k stars 301 forks source link

error in api creation with delayed application creation #673

Open antoine-gallix opened 6 years ago

antoine-gallix commented 6 years ago

After struggling with this problem in my application, I managed to recreate the smallest application that triggers this error. The smallest application using flask restless I could think about is this one:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restless import APIManager

app = Flask(__name__)

db = SQLAlchemy(app)

class Thing(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.Text, primary_key=True)

api = APIManager(app, flask_sqlalchemy_db=db)

api.create_api(Thing, methods=['POST'])

print(app.url_map)

It works. Now I want to use an application factory pattern. I want to handle models in one file, api blueprints in another, and create my application in a function. I refactor the previous application into this:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restless import APIManager

db = SQLAlchemy()

class Thing(db.Model):
    id = db.Column(db.Integer, primary_key=True)

api = APIManager()

# api.create_api(Thing, methods=['POST'])  # this line causes crash
# api.create_api(Thing, methods=['GET'])  # this line works
api.create_api(Thing)  # this line works

def create_app():

    app = Flask(__name__)

    db.init_app(app)
    # crash happens at this moment
    api.init_app(app, flask_sqlalchemy_db=db)

    return app

if __name__ == '__main__':
    app = create_app()
    print(app.url_map)

I get the following error:

RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.

Strangely, this only happens when I want to use the POST method, not when only using GET

seafoodfriedrice commented 6 years ago

I've been having this same problem on Flask-Restless==0.17.0. I don't know if this is the correct way to solve this, but putting create_api with the app keyword argument inside an application context seemed to work for me:

def create_app():
    app = Flask(__name__)
    db.init_app(app)
    api.init_app(app, flask_sqlalchemy_db=db)

    with app.app_context():
        api.create_api(Thing, methods=['GET', 'POST'], app=app)

    return app

Though I'm able to test my application I'd still like to know the real cause of this issue.

agnjunio commented 6 years ago

It seems to be the same issue found earlier: https://github.com/jfinkels/flask-restless/issues/409

TL;DR: Workaround i'm using right now:

db = SQLAlchemy()

def create_app():
...
  db.app = app
  db.init_app(app)