2012-08-08 8 views
5

das ist mein database.pyFlask Wie verwenden Sie sqlalchemy deklarativ mit 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) 

und das ist mein 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) 

Ich bin ein paar seltsame Dinge zu bemerken:

  1. Als ich python backend.py ich bin Sehen Sie die erstellten Tabellen zweimal. Die gleichen create-Tabellenanweisungen werden ausgeführt.
  2. Wenn ich '/' besuche, erhalte ich den folgenden Fehler, selbst wenn ich 100% sicher bin, dass die Tabellen erstellt wurden. Warum?

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

+0

Können Sie Ihren Modellcode auch posten? Ich bin mir nicht sicher, was genau Sie hier vorhaben. Im Allgemeinen sollten Sie die Datenbankerstellung (init_db) nur einmal aufrufen. Ich schlage zumindest vor, es aus backend.py herauszunehmen und database.py nur einmal aufzurufen. – codegeek

Antwort

8

Wenn Sie eine SQLite-Datenbank im Speicher schaffen es nur zugänglich für die speziellen Thread ist, die sie geschaffen - Änderung create_engine('sqlite:///:memory:')-create_engine('sqlite:////some/file/path/db.sqlite' und Ihre Tabellen existieren.

Warum die Tabellen doppelt erstellt werden - Flask im Debug-Modus wird standardmäßig mit einem Server ausgeführt, der jedes Mal neu geladen wird, wenn Sie Ihren Code ändern. Um dies zu tun, erzeugt es einen neuen Prozess, der den Server tatsächlich ausführt - also wird Ihre init_db-Funktion aufgerufen, bevor Sie den Server starten, dann wird sie erneut aufgerufen, wenn der Server einen untergeordneten Prozess für die Ausführung von Anforderungen erstellt.

+1

Sie haben Recht, dass die In-Memory-Datenbank Thread-lokal ist. Eine wichtige Erkenntnis ist hier: In Flasks Entwicklungsserver laufen die Routen-Handler in einem anderen Thread als der Haupt-Thread. Deshalb stellt das gleiche 'db' Objekt tatsächlich unterschiedliche Datenbanken dar, abhängig davon, welchen Thread es verwendet. Ich habe versucht, dies hier zu notieren: http://gehrcke.de/2015/05/in-memory-sqlite-database-and-flask-a-threading-trap/ –

Verwandte Themen