2012-08-08 17 views
5

este es mi database.pyFrasco ¿cómo se usa sqlalchemy declarativamente 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) 

y este es mi 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) 

estoy notando un par de cosas extrañas:

  1. Cuando hago python backend.py soy viendo las tablas creadas dos veces. Se ejecutan las mismas sentencias create table
  2. Cuando visito '/', recibo el siguiente error incluso cuando estoy 100% seguro de que las tablas se han creado. ¿Por qué?

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

+0

¿Puedes publicar el código de tu modelo también? No estoy seguro de qué es exactamente lo que estás tratando de hacer aquí. En general, debe llamar a la creación de la base de datos (init_db) solo una vez. Sugiero al menos sacarlo de backend.py y simplemente llamar a database.py una vez antes. – codegeek

Respuesta

8

Cuando se crea una base de datos SQLite en la memoria sólo es accesible para el hilo en particular que lo creó - el cambio create_engine('sqlite:///:memory:') a create_engine('sqlite:////some/file/path/db.sqlite' y existirá sus tablas.

En cuanto a por qué está viendo las tablas creadas dos veces: Flask en modo de depuración se ejecuta de forma predeterminada con un servidor que se recarga cada vez que cambia el código. Para hacerlo cuando se inicia, genera un nuevo proceso que realmente ejecuta el servidor, por lo que se llama a su función init_db antes de iniciar el servidor, luego se vuelve a llamar cuando el servidor crea un proceso secundario para atender solicitudes.

+1

Tiene razón en que la base de datos en memoria es local de subprocesos. Una idea importante aquí es: en el servidor de desarrollo de Flask, los manejadores de ruta se ejecutan en un hilo diferente al hilo principal. Es por eso que el mismo objeto 'db' en realidad representa diferentes bases de datos, dependiendo de qué hilo se utiliza. He tratado de tomar nota de esto aquí: http://gehrcke.de/2015/05/in-memory-sqlite-database-and-flask-a-threading-trap/ –