Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
279 views
in Technique[技术] by (71.8m points)

python - How to use flask-sqlalchemy with existing sqlalchemy model?

I've read flask-sqlalchemy or sqlalchemy which recommends use of flask-sqlalchemy with flask. I want to follow this approach.

However, I have an existing model written for command line scripts which is based on sqlalchemy's declarative_base, e.g.,

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()   # create sqlalchemy Base class
              :
class Runner(Base):
    etc.

I want to still be able to use the command line scripts with this model, but also want to build a web application around the model.

Is there a way to extend the existing model, to gain the benefit of using the flask-sqlalchemy extension? Or should I just roll my own, and use sqlalchemy's ScopedSession?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Currently, this is something that is not well supported, but not impossible to do. See this issue on the Flask-SQLAlchemy issue list, which admits that the current implementation of the extension makes this situation more of a headache than they think it should. Hopefully this will be better supported in the future (once a solid migration path and new API is determined).

That issue gives the following code sample:

from flask import Flask
from models import Base, User # Your non-Flask-SQLAlchemy models...
from flask_sqlalchemy import SQLAlchemy

app =  Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

@app.before_first_request
def setup():
    # Recreate database each time for demo
    Base.metadata.drop_all(bind=db.engine)
    Base.metadata.create_all(bind=db.engine)
    db.session.add(User('Bob Jones', 'bob@gmail.com'))
    db.session.add(User('Joe Quimby', 'eat@joes.com'))
    db.session.commit()

@app.route('/')
def root():
    users = db.session.query(User).all()
    return u"<br>".join([u"{0}: {1}".format(user.name, user.email) for user in users])

if __name__ == '__main__':
    app.run('127.0.0.1', 5000) 

There are a few things to note here:

First, you lose the ability to do User.query (because User was created using its own declarative base), along with all of the other stuff that Flask-SQLAlchemy's db.Model gives you (such as the ability to auto-generate the table names and methods like first_or_404()).

Second, any time you need to do things that involve the metadata (such as drop_all or create_all), you cannot use the Flask-SQLAlchemy methods. You must use the original metadata, bound to the Flask-SQLAlchemy engine.

I haven't tried this myself, so I'm not sure if there are any other gotchas to this approach. You might want to participate in that ticket if you find any.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...