2012-08-08 4 views
5

questo è il mio database.pyFlask come si usa sqlalchemy in modo dichiarativo con init_db()?

engine = create_engine('sqlite:///:memory:', echo=True) 
session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) 
Base = declarative_base() 
Base.query = session.query_property() 

def init_db(): 
    # import all modules here that might define models so that 
    # they will be registered properly on the metadata. Otherwise 
    # you will have to import them first before calling init_db() 
    import models 
    Base.metadata.create_all(engine) 

e questo è il mio backend.py

from flask import Flask, session, g, request, render_template 
from database import init_db, session 
from models import * 

app = Flask(__name__) 
app.debug = True 
app.config.from_object(__name__) 

# Serve static file during debug 
if app.config['DEBUG']: 
    from werkzeug import SharedDataMiddleware 
    import os 
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, { 
    '/': os.path.join(os.path.dirname(__file__), 'static') 
    }) 

@app.route('/') 
def foo(): 
    session.add(User()) 
    session.commit() 
    return "NOTHING HERE." 

if __name__ == "__main__": 
    init_db() 
    app.run(port=8888) 

Sto notando un paio di cose strane:

  1. Quando faccio python backend.py Sono vedere i tavoli creati due volte. Le stesse istruzioni create della tabella vengono eseguite
  2. Quando visito "/", ricevo il seguente errore anche quando sono sicuro al 100% che le tabelle siano state create. Perché?

cursor.execute(statement, parameters) OperationalError: (OperationalError) no such table: users u'INSERT INTO users DEFAULT VALUES'()

+0

Puoi pubblicare anche il codice del tuo modello? Non sei sicuro di cosa stai provando a fare esattamente qui. In generale, si dovrebbe chiamare la creazione del database (init_db) solo una volta. Suggerisco almeno di estrarlo da backend.py e chiamare database.py una volta prima. – codegeek

risposta

8

Quando si crea un database SQLite in memoria è accessibile solo al particolare filo che lo ha creato - il cambiamento create_engine('sqlite:///:memory:')-create_engine('sqlite:////some/file/path/db.sqlite' ed esisterà le tabelle.

Sul motivo per cui si stanno visualizzando le tabelle due volte: Flask in modalità di debug per impostazione predefinita viene eseguito con un server che si ricarica ogni volta che si modifica il codice. Per fare quando inizia, genera un nuovo processo che esegue effettivamente il server - quindi la tua funzione init_db viene chiamata prima di avviare il server, quindi viene richiamata quando il server crea un processo figlio per servire le richieste.

+1

Hai ragione che il database in memoria è thread-local. Un'informazione importante qui è: nel server di sviluppo di Flask, i gestori di percorso vengono eseguiti in un thread diverso rispetto al thread principale. Questo è il motivo per cui lo stesso oggetto 'db' rappresenta effettivamente diversi database, a seconda del thread utilizzato. Ho cercato di annotarlo qui: http://gehrcke.de/2015/05/in-memory-sqlite-database-and-flask-a-threading-trap/ –