Alter field migration with Peewee
from peewee import CharField, MySQLDatabase
We can do migrations for
PostgreSQL and supported operations are:
drop_not_null, so basically you can accomplish most of the common tasks on your database migration.
So what’s the issue? Recently I faced problem to migrate one column in my table. In case you don’t worry about losing a data you can simply
add_column with a new definition or
add_column, apply custom script which will copy all the data to new field and finally
But there is another approach allowing us to use a shortcut and migrate our database the same way as we would do that using raw SQL (smth like
ALTER TABLE <table_name> MODIFY <col_name> VARCHAR(<new_value>);)
As we can see
migrate command accepts list of operation from our migrator, so all we need is to implement another
change_column_type operation in our migration. Let’s create our own migrator which will support modifying columns!
First we subclass
MySQLMigrator and add an
operation method to it.
from playhouse.migrate import MySQLMigrator, operation
Every operation should return
Context instance which is basically an object containing all the data needed to generate resulting SQL. We already have an idea about how the final sql code should look like, so all we need is to provide required data to generate that statement.
def change_column_type(self, table, column_name, new_field):
literal methods which will evaluate straight to the code provided as parameter and
Entity which tells peewee to escape names to be valid sql. At the end we insert definition for our field also as sql. We can use our migrator with newly implemented method right after this:
migrator = ExtendedMySQLMigrator(db)
There is another small improvement to this code: we actually need to modify a column that is already present on our model (bound to it), so there is no need to provide
column_name parameter as it is already known by peewee. So we remove that parameter and not provide column_name entity manually.
When applying migration we can know provide update field directly from that model class itself like the following
Don’t forget to create a database backup before applying any migrations (especially your own, especially not well-tested)!
Happy database migration :)