Setting the database at run-time

We have seen three ways that databases can be configured with Peewee:

  1. # The usual way:
  2. db = SqliteDatabase('my_app.db', pragmas={'journal_mode': 'wal'})
  3. # Specify the details at run-time:
  4. db = SqliteDatabase(None)
  5. ...
  6. db.init(db_filename, pragmas={'journal_mode': 'wal'})
  7. # Or use a placeholder:
  8. db = DatabaseProxy()
  9. ...
  10. 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:

As an example, we’ll declare two models without specifying any database:

  1. class User(Model):
  2. username = TextField()
  3. class Tweet(Model):
  4. user = ForeignKeyField(User, backref='tweets')
  5. content = TextField()
  6. timestamp = TimestampField()

Bind the models to a database at run-time:

  1. postgres_db = PostgresqlDatabase('my_app', user='postgres')
  2. sqlite_db = SqliteDatabase('my_app.db')
  3. # At this point, the User and Tweet models are NOT bound to any database.
  4. # Let's bind them to the Postgres database:
  5. postgres_db.bind([User, Tweet])
  6. # Now we will temporarily bind them to the sqlite database:
  7. with sqlite_db.bind_ctx([User, Tweet]):
  8. # User and Tweet are now bound to the sqlite database.
  9. assert User._meta.database is sqlite_db
  10. # User and Tweet are once again bound to the Postgres database.
  11. assert User._meta.database is postgres_db

The Model.bind() and Model.bind_ctx() methods work the same for binding a given model class:

  1. # Bind the user model to the sqlite db. By default, Peewee will also
  2. # bind any models that are related to User via foreign-key as well.
  3. User.bind(sqlite_db)
  4. assert User._meta.database is sqlite_db
  5. assert Tweet._meta.database is sqlite_db # Related models bound too.
  6. # Here we will temporarily bind *just* the User model to the postgres db.
  7. with User.bind_ctx(postgres_db, bind_backrefs=False):
  8. assert User._meta.database is postgres_db
  9. assert Tweet._meta.database is sqlite_db # Has not changed.
  10. # And now User is back to being bound to the sqlite_db.
  11. assert User._meta.database is sqlite_db

The Testing Peewee Applications section of this document also contains some examples of using the bind() methods.