Schema & Migrations

Migrations are used to build and modify your database tables. This is done through use of migration files and the Schema class. Migration files are really just wrappers around the Schema class as well as a way for Masonite to manage which migrations have run and which ones have not.

Creating Migrations

Creating migrations are easy with the migration commands. To create one simply run:

$ masonite-orm migration migration_for_users_table

This will create a migration file for you and put it in the databases/migrations directory.

If you want to create a starter migration, that is a migration with some boilerplate of what you are planning to do, you can use the --table and --create flag:

$ masonite-orm migration migration_for_users_table --create users

This will setup a migration for you with some boiler plate on creating a new table

$ masonite-orm migration migration_for_users_table --table users

This will setup a migration for you for boiler plate on modifying an existing table.

Building Migrations

To start building up your migration, simply modify the up method and start adding any of the available methods below to your migration.

A simple example would look like this for a new table:

class MigrationForUsersTable(Migration):
    def up(self):
        """
        Run the migrations.
        """
        with self.schema.create("users") as table:
            table.increments('id')
            table.string('username')
            table.string('email').unique()
            table.string('password')
            table.boolean('is_admin')
            table.integer('age')

            table.timestamps()

    def down(self):
        """
        Revert the migrations.
        """
        self.schema.drop("users")

Available Methods

Changes & Rolling Back Migrations

In addition to building up the migration, you should also build onto the down method which should reverse whatever was done in the up method. If you create a table in the up method, you should drop the table in the down method.

Getting Migration Status

At any time you can get the migrations that have run or need to be ran:

$ masonite-orm migrate:status

Seeing Migration SQL Dumps

If you would like to see just the SQL that would run instead of running the actual migrations, you can specify the -s flag (short for --show). This works on the migrate and migrate:rollback commands.

python craft migrate -s

Refreshing Migrations

Refreshing a database is simply rolling back all migrations and then migrating again. This "refreshes" your database.

You can refresh by running the command:

$ masonite-orm migrate:refresh

You can also seed your database after refreshing your migrations. Which will rebuild you database to some desire state.

You can run all seeders located in Database Seeder class by:

$ masonite-orm migrate:refresh --seed

Or simply run a specific seeder:

$ masonite-orm migrate:refresh --seed CustomTable

CustomTable is the name of the seeder without "Seeder" suffix. Internally we will run the desired CustomTableSeeder.

Modifiers

In addition to the available columns you can use, you can also specify some modifers which will change the behavior of the column:

Indexes

In addition to columns, you can also create indexes. Below are the available indexes you can create:

The default primary key is often set to an auto-incrementing integer, but you can use a UUID instead.

Foreign Keys

If you want to create a foreign key you can do so simply as well:

table.foreign('local_column').references('other_column').on('other_table')

And optionally specify an on_delete or on_update method:

table.foreign('local_column').references('other_column').on('other_table').on_update('set null')

You can use these options:

Available options for on_update and on_delete are:

  • cascade

  • set null

  • restrict

  • no action

  • default

You can also pass a name parameter to change the name of the constraint:

table.foreign('local_column', name="foreign_constraint").references('other_column').on('other_table')

You may also use a shorthand method:

table.add_foreign('local_column.other_column.other_table', name="foreign_constraint")

Changing Columns

If you would like to change a column you should simply specify the new column and then specify a .change() method on it.

Here is an example of changing an email field to a nullable field:

class MigrationForUsersTable(Migration):
    def up(self):
        """
        Run the migrations.
        """
        with self.schema.table("users") as table:
            table.string('email').nullable().change()

        with self.schema.table("users") as table:
            table.string('email').unique()


    def down(self):
        """
        Revert the migrations.
        """
        pass

Truncating

You can truncate a table:

schema.truncate("users")

You can also temporarily disable foreign key checks and truncate a table:

schema.truncate("users", foreign_keys=False)

Dropping a Table

You can drop a table:

schema.drop_table("users")

Dropping a Table If It Exists

You can drop a table if it exists:

schema.drop_table_if_exists("users")

Last updated