Structure Flask-Restful API to use SQLAlchemy

2019-02-11 01:19发布

问题:

So I'm trying to make an API, using Flask-Restful, but all the examples I find put everything into one app.py file. I found information in the Flask-Restful docs explaining how to structure your API, but it doesn't include anything for using a database. I've posted what I've come up with, and it works if I hard-code some data, but when I import the db into users.py I get an error ImportError: cannot import name 'db'. So, what is the best way to structure an API to bring in your data from a database?

Structure

myapi
    run.py
    api
        __init__.py
        resources
            __init__.py
            user.py

myapi/run.py

from api import app
app.run()

myapi/__init__.py

from flask import Flask
from flask.ext.restful import Api
from flask.ext.sqlalchemy import SQLAlchemy
from api.resources.user import User

app = Flask(__name__)
app.debug = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/myapi'

api = Api(app)
db = SQLAlchemy(app)

api.add_resource(User, '/user')

../resources/user.py

from flask.ext.restful import Resource
from api import db


class User(Resource, db.Model):
    def get(self):
        return {'class': 'user', 'first': 'john', 'last': 'doe'}

回答1:

I ran into this same problem and it had me stumped for longer than I care to admit. Looks like this is the same problem here so despite the age of the question I'll give an answer in the hope that I can save someone else some time. The problem here is actually an order-of-packages thing. The db in the main init has to be instantiated before the user class is imported, because this imports the db itself. I think that this is a trap that a lot of people fall into because one's immediate reflex is to put all the package loaders at the top of the file - sadly, in this case, it doesn't work and you end up chasing your tail for ages...



回答2:

Move your resource/model import to below where you assign the db variable (since those modules/scripts rely on the db already being instantiated):

myapi/api/__init__.py

from flask import Flask
from flask.ext.restful import Api
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.debug = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/myapi'

api = Api(app)
db = SQLAlchemy(app)

from api.resources.user import User

api.add_resource(User, '/user')