2013-10-01 21 views
9

Ho letto flask-sqlalchemy or sqlalchemy che consiglia l'uso del pallone-sqlalchemy con il pallone. Voglio seguire questo approccio.Come usare flask-sqlalchemy con il modello sqlalchemy esistente?

Tuttavia, ho un modello esistente scritto per gli script della riga di comando che si basa su declarative_base di SQLAlchemy, ad esempio,

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

voglio essere ancora in grado di utilizzare gli script della riga di comando con questo modello, ma anche vuoi creare un'applicazione web attorno al modello.

C'è un modo per estendere il modello esistente, per ottenere il vantaggio dell'utilizzo dell'estensione flask-sqlalchemy? O dovrei semplicemente lanciare il mio e usare la ScopedSession di sqlalchemy?

+0

sarebbe un problema riscrivere gli script della riga di comando utilizzando il modello flask-sqlalchemy? –

+0

Non so - non ho usato la fiaschetta prima, o l'alchimia delle fiasche e non conosco gli effetti collaterali. Gli script devono essere riscritti o solo il modello che viene importato? Avrei anche dovuto dire che ho usato l'alambicco per tenere traccia delle modifiche al database, nel caso in cui ci siano problemi di compatibilità lì. –

risposta

9

Attualmente, questo è qualcosa che non è ben supportato, ma non impossibile da fare. Vedere this issue nell'elenco dei problemi Flask-SQLAlchemy, che ammette che l'attuale implementazione dell'estensione rende questa situazione più mal di testa di quanto pensino dovrebbe. Speriamo che questo sia meglio supportato in futuro (una volta stabilito un solido percorso di migrazione e una nuova API).

Tale questione ha pronunciato la seguente codice di esempio:

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', '[email protected]')) 
    db.session.add(User('Joe Quimby', '[email protected]')) 
    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) 

Ci sono alcune cose da notare qui:

In primo luogo, si perde la capacità di fare User.query (perché l'utente è stato creato utilizzando la propria dichiarativa base), insieme a tutte le altre cose fornite da Flask-SQLAlchemy db.Model (ad esempio la possibilità di generare automaticamente i nomi e i metodi della tabella come first_or_404()).

In secondo luogo, ogni volta che è necessario eseguire operazioni che coinvolgono i metadati (ad esempio drop_all o create_all), non è possibile utilizzare i metodi Flask-SQLAlchemy. È necessario utilizzare i metadati originali, associati al motore Flask-SQLAlchemy.

Non l'ho provato da solo, quindi non sono sicuro che ci siano altri trucchi per questo approccio. Potresti voler partecipare a quel biglietto se ne trovi uno.

+0

Grazie per il puntatore al problema. Posso fare l'esperimento, ma sicuramente è più facile se si conosce questa risposta: Se riscrivo il modello usando db.model di flask-alchemy, piuttosto che Base, con quella interruzione degli script della riga di comando? –

+0

@Lou_K: Probabilmente non "interrompe" di per sé, ma quando provi a eseguirli potresti dover fare del lavoro aggiuntivo per configurare l'app Flask prima che la carne dello script possa essere eseguita. –

+0

@ Mark_Hildreth: potrei provarlo. Se diventa oneroso, forse posso far funzionare lo stesso file sorgente per il modello, ma dipende da alcune informazioni sull'ambiente (una sorta di configurazione esterna a python, impostata dalla riga di comando o dall'app Web) per importare le cose giuste, e dichiara Base in modo appropriato a seconda che venga usato dallo script della riga di comando o dall'app del pallone. Non si sente molto elegante, però. E questo deve essere pensato attentamente per assicurarsi che i due sistemi non si scontrino in qualche modo. –

Problemi correlati