Setting the database at run-time
We have seen three ways that databases can be configured with Peewee:
# The usual way:
db = SqliteDatabase('my_app.db', pragmas={'journal_mode': 'wal'})
# Specify the details at run-time:
db = SqliteDatabase(None)
...
db.init(db_filename, pragmas={'journal_mode': 'wal'})
# Or use a placeholder:
db = DatabaseProxy()
...
db.initialize(SqliteDatabase('my_app.db', pragmas={'journal_mode': 'wal'}))
Peewee can also set or change the database for your model classes. This technique is used by the Peewee test suite to bind test model classes to various database instances when running the tests.
There are two sets of complementary methods:
Database.bind()
andModel.bind()
- bind one or more models to a database.Database.bind_ctx()
andModel.bind_ctx()
- which are the same as theirbind()
counterparts, but return a context-manager and are useful when the database should only be changed temporarily.
As an example, we’ll declare two models without specifying any database:
class User(Model):
username = TextField()
class Tweet(Model):
user = ForeignKeyField(User, backref='tweets')
content = TextField()
timestamp = TimestampField()
Bind the models to a database at run-time:
postgres_db = PostgresqlDatabase('my_app', user='postgres')
sqlite_db = SqliteDatabase('my_app.db')
# At this point, the User and Tweet models are NOT bound to any database.
# Let's bind them to the Postgres database:
postgres_db.bind([User, Tweet])
# Now we will temporarily bind them to the sqlite database:
with sqlite_db.bind_ctx([User, Tweet]):
# User and Tweet are now bound to the sqlite database.
assert User._meta.database is sqlite_db
# User and Tweet are once again bound to the Postgres database.
assert User._meta.database is postgres_db
The Model.bind()
and Model.bind_ctx()
methods work the same for binding a given model class:
# Bind the user model to the sqlite db. By default, Peewee will also
# bind any models that are related to User via foreign-key as well.
User.bind(sqlite_db)
assert User._meta.database is sqlite_db
assert Tweet._meta.database is sqlite_db # Related models bound too.
# Here we will temporarily bind *just* the User model to the postgres db.
with User.bind_ctx(postgres_db, bind_backrefs=False):
assert User._meta.database is postgres_db
assert Tweet._meta.database is sqlite_db # Has not changed.
# And now User is back to being bound to the sqlite_db.
assert User._meta.database is sqlite_db
The Testing Peewee Applications section of this document also contains some examples of using the bind()
methods.