2015-12-15 9 views
6

Mi piacerebbe usare Flask-Migrate e sto guardando il loro esempio:Come faccio a dividere i modelli Flask da app.py senza passare l'oggetto db dappertutto?

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 
from flask.ext.script import Manager 
from flask.ext.migrate import Migrate, MigrateCommand 

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

db = SQLAlchemy(app) 
migrate = Migrate(app, db) 

manager = Manager(app) 
manager.add_command('db', MigrateCommand) 

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(128)) 

if __name__ == '__main__': 
    manager.run() 

Questo funziona come un semplice esempio di gioco, ma ho più di un modello unico e non voglio definire i modelli sia in questo script sia in quello che definisce il mio codice applicazione. Quindi, voglio inserirli in un file di modello che posso condividere tra i due.

Sto tentando di farlo, inserendo la classe User in un models.py e quindi importando Utente da lì. Sfortunatamente, quello lancia un NameError: name 'db' is not defined.

La mia domanda (s) sono:

  • ho bisogno per utilizzare db = SQLAlchemy(app) nel mio models.py, e in tal caso questo sarà disponibile sia in mio script di migrazione e l'applicazione pallone in sé?
  • Se non posso (o non dovrei) metterlo in models.py, come posso utilizzare i miei modelli nel loro file senza passare db dappertutto?
+0

Controllare questo https://realpython.com/blog/python/python-web-applications-with-flask-part-ii/ – PetarP

risposta

10

Il partizionamento di una piccola applicazione in moduli è complicato, perché si trovano molti casi in cui i due moduli creati devono essere reciprocamente importati, creando dipendenze circolari.

Si consiglia di osservare come è possibile strutturare correttamente un'applicazione più grande, utilizzando una funzione di fabbrica dell'app e l'inizializzazione ritardata di tutti gli interni. Un'applicazione di esempio che fa questa è l'app Flasky descritta nel mio libro.

Tutto ciò detto, è possibile separare l'applicazione in due parti, è sufficiente fare attenzione a dove si posizionano le istruzioni di importazione. Nell'esempio seguente, ho deciso di spostare la creazione dell'istanza db e il modello User in un file models.py.

Ecco modulo della principale dell'applicazione:

from flask import Flask 
from flask.ext.script import Manager 
from flask.ext.migrate import Migrate, MigrateCommand 

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

from models import db # <-- this needs to be placed after app is created 
migrate = Migrate(app, db) 

manager = Manager(app) 
manager.add_command('db', MigrateCommand) 

if __name__ == '__main__': 
    manager.run() 

Ed ecco i modelli.py:

from __main__ import app 
from flask.ext.sqlalchemy import SQLAlchemy 

db = SQLAlchemy(app) 

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(128)) 

Qui il modulo principale creerà app, e solo allora importare models.py. Quando model.py tenta di importare app dal modulo principale, è già stato creato. Se si sposta from models import db nella parte superiore del file con le altre importazioni, questo codice si interrompe.

+1

Capisco il tuo esempio ma cosa succede se voglio dividere models.py in diversi .pys? ad esempio User.py, Foo.py, Bar.py. Sto lottando per trovare un modo per farlo. –

+1

@VitorHugo è possibile creare un pacchetto 'models', creare l'istanza' db' nel file '__init __. Py' del pacchetto, quindi aggiungere un modulo per modello, con tutti questi moduli che importano l'istanza' db' come 'from. importazione db'. – Miguel

+0

Questo ha funzionato, ma quando eseguo un db.create_all() sul modulo principale dell'applicazione dopo "dai modelli import db" non crea le tabelle che è ciò che accade quando faccio models.py. Dovrebbe essere una cosa separata o dovrei preoccuparmi? –

0

Ecco un'idea. È possibile creare un pacchetto model in cui si definiscono le classi come singoli file .py. Ad esempio, user.py contiene la classe User.

Nel file __init__.py è possibile definire la variabile db. È inoltre possibile includere la dichiarazione from user import User in modo che sia possibile accedere all'oggetto User direttamente all'esterno del pacchetto. Ad esempio, è possibile importare il pacchetto model da un'altra parte nel programma utilizzando import model e quindi utilizzare model.User per utilizzare direttamente la classe User.

Per utilizzare db variabile direttamente nel user.py uso from ..model import db che importa db variabile definita nel file __init__.py.

+0

Questo non significa che quindi ho bisogno di passare 'app' (da' db = SQLAlchemy (app) ') in giro invece di' db'? – NewGuy

+0

Bene, in tal caso puoi aggiungere sia 'app' che' db' in '__init __. Py' – aliasm2k

Problemi correlati