Schema Migrations

Peewee now supports schema migrations, with well-tested support for Postgresql,SQLite and MySQL. Unlike other schema migration tools, peewee’s migrations donot handle introspection and database “versioning”. Rather, peewee provides anumber of helper functions for generating and running schema-alteringstatements. This engine provides the basis on which a more sophisticated toolcould some day be built.

Migrations can be written as simple python scripts and executed from thecommand-line. Since the migrations only depend on your applicationsDatabase object, it should be easy to manage changing your modeldefinitions and maintaining a set of migration scripts without introducingdependencies.

Example usage

Begin by importing the helpers from the migrate module:

  1. from playhouse.migrate import *

Instantiate a migrator. The SchemaMigrator class is responsiblefor generating schema altering operations, which can then be run sequentiallyby the migrate() helper.

  1. # Postgres example:
  2. my_db = PostgresqlDatabase(...)
  3. migrator = PostgresqlMigrator(my_db)
  4.  
  5. # SQLite example:
  6. my_db = SqliteDatabase('my_database.db')
  7. migrator = SqliteMigrator(my_db)

Use migrate() to execute one or more operations:

  1. title_field = CharField(default='')
  2. status_field = IntegerField(null=True)
  3.  
  4. migrate(
  5. migrator.add_column('some_table', 'title', title_field),
  6. migrator.add_column('some_table', 'status', status_field),
  7. migrator.drop_column('some_table', 'old_column'),
  8. )

Warning

Migrations are not run inside a transaction. If you wish the migration torun in a transaction you will need to wrap the call to migrate in aatomic() context-manager, e.g.

  1. with my_db.atomic():
  2. migrate(...)

Supported Operations

Add new field(s) to an existing model:

  1. # Create your field instances. For non-null fields you must specify a
  2. # default value.
  3. pubdate_field = DateTimeField(null=True)
  4. comment_field = TextField(default='')
  5.  
  6. # Run the migration, specifying the database table, field name and field.
  7. migrate(
  8. migrator.add_column('comment_tbl', 'pub_date', pubdate_field),
  9. migrator.add_column('comment_tbl', 'comment', comment_field),
  10. )

Renaming a field:

  1. # Specify the table, original name of the column, and its new name.
  2. migrate(
  3. migrator.rename_column('story', 'pub_date', 'publish_date'),
  4. migrator.rename_column('story', 'mod_date', 'modified_date'),
  5. )

Dropping a field:

  1. migrate(
  2. migrator.drop_column('story', 'some_old_field'),
  3. )

Making a field nullable or not nullable:

  1. # Note that when making a field not null that field must not have any
  2. # NULL values present.
  3. migrate(
  4. # Make `pub_date` allow NULL values.
  5. migrator.drop_not_null('story', 'pub_date'),
  6.  
  7. # Prevent `modified_date` from containing NULL values.
  8. migrator.add_not_null('story', 'modified_date'),
  9. )

Altering a field’s data-type:

  1. # Change a VARCHAR(50) field to a TEXT field.
  2. migrate(
  3. migrator.alter_column_type('person', 'email', TextField())
  4. )

Renaming a table:

  1. migrate(
  2. migrator.rename_table('story', 'stories_tbl'),
  3. )

Adding an index:

  1. # Specify the table, column names, and whether the index should be
  2. # UNIQUE or not.
  3. migrate(
  4. # Create an index on the `pub_date` column.
  5. migrator.add_index('story', ('pub_date',), False),
  6.  
  7. # Create a multi-column index on the `pub_date` and `status` fields.
  8. migrator.add_index('story', ('pub_date', 'status'), False),
  9.  
  10. # Create a unique index on the category and title fields.
  11. migrator.add_index('story', ('category_id', 'title'), True),
  12. )

Dropping an index:

  1. # Specify the index name.
  2. migrate(migrator.drop_index('story', 'story_pub_date_status'))

Adding or dropping table constraints:

  1. # Add a CHECK() constraint to enforce the price cannot be negative.
  2. migrate(migrator.add_constraint(
  3. 'products',
  4. 'price_check',
  5. Check('price >= 0')))
  6.  
  7. # Remove the price check constraint.
  8. migrate(migrator.drop_constraint('products', 'price_check'))
  9.  
  10. # Add a UNIQUE constraint on the first and last names.
  11. migrate(migrator.add_unique('person', 'first_name', 'last_name'))

Migrations API

  • migrate(*operations)
  • Execute one or more schema altering operations.

Usage:

  1. migrate(
  2. migrator.add_column('some_table', 'new_column', CharField(default='')),
  3. migrator.create_index('some_table', ('new_column',)),
  4. )
  • class SchemaMigrator(database)

Parameters:database – a Database instance.

The SchemaMigrator is responsible for generating schema-alteringstatements.

  • addcolumn(_table, column_name, field)

Parameters:

  1. - **table** (_str_) Name of the table to add column to.
  2. - **column_name** (_str_) Name of the new column.
  3. - **field** ([_Field_]($91d5d4e449d7d4b4.md#Field)) – A [<code>Field</code>]($91d5d4e449d7d4b4.md#Field) instance.

Add a new column to the provided table. The field provided will be usedto generate the appropriate column definition.

Note

If the field is not nullable it must specify a default value.

Note

For non-null fields, the field will initially be added as a null field,then an UPDATE statement will be executed to populate the columnwith the default value. Finally, the column will be marked as not null.

  • dropcolumn(_table, column_name[, cascade=True])

Parameters:

  1. - **table** (_str_) Name of the table to drop column from.
  2. - **column_name** (_str_) Name of the column to drop.
  3. - **cascade** (_bool_) Whether the column should be dropped with _CASCADE_.
  • renamecolumn(_table, old_name, new_name)

Parameters:

  1. - **table** (_str_) Name of the table containing column to rename.
  2. - **old_name** (_str_) Current name of the column.
  3. - **new_name** (_str_) New name for the column.
  • addnot_null(_table, column)

Parameters:

  1. - **table** (_str_) Name of table containing column.
  2. - **column** (_str_) Name of the column to make not nullable.
  • dropnot_null(_table, column)

Parameters:

  1. - **table** (_str_) Name of table containing column.
  2. - **column** (_str_) Name of the column to make nullable.
  • altercolumn_type(_table, column, field[, cast=None])

Parameters:

  1. - **table** (_str_) Name of the table.
  2. - **column_name** (_str_) Name of the column to modify.
  3. - **field** ([_Field_]($91d5d4e449d7d4b4.md#Field)) – [<code>Field</code>]($91d5d4e449d7d4b4.md#Field) instance representing newdata type.
  4. - **cast** (postgres-only) specify a cast expression if thedata-types are incompatible, e.g. <code>column_name::int</code>. Can beprovided as either a string or a [<code>Cast</code>]($91d5d4e449d7d4b4.md#Cast) instance.

Alter the data-type of a column. This method should be used with care,as using incompatible types may not be well-supported by your database.

  • renametable(_old_name, new_name)

Parameters:

  1. - **old_name** (_str_) Current name of the table.
  2. - **new_name** (_str_) New name for the table.
  • addindex(_table, columns[, unique=False[, using=None]])

Parameters:

  1. - **table** (_str_) Name of table on which to create the index.
  2. - **columns** (_list_) List of columns which should be indexed.
  3. - **unique** (_bool_) Whether the new index should specify a unique constraint.
  4. - **using** (_str_) Index type (where supported), e.g. GiST or GIN.
  • dropindex(_table, index_name)

Parameters:

  1. - **table** (_str_) Name of the table containing the index to be dropped.
  2. - **index_name** (_str_) Name of the index to be dropped.
  • addconstraint(_table, name, constraint)

Parameters:

  1. - **table** (_str_) Table to add constraint to.
  2. - **name** (_str_) Name used to identify the constraint.
  3. - **constraint** either a [<code>Check()</code>]($91d5d4e449d7d4b4.md#Check) constraint or foradding an arbitrary constraint use [<code>SQL</code>]($91d5d4e449d7d4b4.md#SQL).
  • dropconstraint(_table, name)

Parameters:

  1. - **table** (_str_) Table to drop constraint from.
  2. - **name** (_str_) Name of constraint to drop.
  • addunique(_table, *column_names)

Parameters:

  1. - **table** (_str_) Table to add constraint to.
  2. - **column_names** (_str_) One or more columns for UNIQUE constraint.
  • class PostgresqlMigrator(database)
  • Generate migrations for Postgresql databases.

    • setsearch_path(_schema_name)

Parameters:schema_name (str) – Schema to use.

Set the search path (schema) for the subsequent operations.

  • class SqliteMigrator(database)
  • Generate migrations for SQLite databases.

SQLite has limited support for ALTER TABLE queries, so the followingoperations are currently not supported for SQLite:

  • add_constraint
  • drop_constraint
  • add_unique
  • class MySQLMigrator(database)
  • Generate migrations for MySQL databases.