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. Thistechnique is used by the Peewee test suite to bind test model classes tovarious database instances when running the tests.
There are two sets of complementary methods:
Database.bind()
andModel.bind()
- bind one or more modelsto a database.Database.bind_ctx()
andModel.bind_ctx()
- which are thesame as theirbind()
counterparts, but return a context-manager and areuseful 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 samefor 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 ofusing the bind()
methods.