Reputation: 513
I have a project where I want to isolate DB initialization (SQLAlchemy) from the other module so I've create a module
db_initializer.py
:
engine = create_engine('sqlite:///db') # TODO from config file
Session = sessionmaker(bind=engine)
Base = declarative_base(bind=engine)
def create_tables():
Base.metadata.create_all(engine)
First of all I need to put create_all in a function because my model is in another package.
model/foo.py
:
from core.db_initializer import Base
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
def __init__(self, name: str = None):
self.name = name
def __repr__(self):
return "<User(id=%d, name=%s)>" % (int(self.id), str(self.name))
And my main call create_tables.
Is there any other to do that? And now I need to create the engine with custom config (IP,User, ...) and only the main script know the config it's possible?
Something like
main.py
:
import db_initializer as db
import model.foo
db.init(config) # which create the engine and create table
When I do something like that I got problem with the Base object which have not bind to the engine which is not created yet. Any solutions?
Upvotes: 1
Views: 3118
Reputation: 3257
You don't need to create engine or session before declaring your models. You can declare models in model/foo.py:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
Let's assume you have some application in myapp.py. Declare it so it can be initialized with engine:
from sqlalchemy.orm import Session
import model.foo
class MyApp:
def __init__(self, engine):
self.engine = engine
def get_users(self):
session = Session(self.engine)
users = session.query(model.foo.User).all()
session.close()
return users
Create engine in main.py and use it to initialize models.foo.Base.metadata
and other applications where you need it:
from sqlalchemy import create_engine
import model.foo
import myapp
engine = create_engine('sqlite:///db')
model.foo.Base.metadata.bind = engine
model.foo.Base.metadata.create_all()
app = myapp.MyApp(engine)
UPD: For scoped_session
approach myapp.py can be look like this:
import model.foo
class MyApp:
def __init__(self, session):
self.session = session
def get_users(self):
return self.session.query(model.foo.User).all()
And main.py:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
import model.foo
import myapp
engine = create_engine('sqlite:///db')
session = scoped_session(sessionmaker(engine))
model.foo.Base.metadata.bind = engine
model.foo.Base.metadata.create_all()
app = myapp.MyApp(session)
Upvotes: 1