Skip to content

RFC: Extensibility Improvements For Multi-App #456

@channelcat

Description

@channelcat

I really like this project and recently tried implementing Django-style migrations. However, I ran into a few issues needing to be dealt with and monkey-patched to make work.

Goal: Per-application migrations

app1/models.py
app1/migrations/1_date_initial.py
app1/migrations/2_date_update.py
app2/models.py
app2/migrations/1_date_initial.py
app2/migrations/2_date_update.py

Here are some difficulties I ran into and how I think they might be smoothed over:

Migration path needs further configurability

Currently the path is always BASE_PATH/APP/NUMBER_DATE_COMMENTS.py where BASE_PATH is configurable.
It would be great to be able to pass a template string or lambda (that gets kwargs for path variables like app, date, etc.) to determine the full path of a migrations file. To make things truly dynamic, a template-string would allow you to create a regex to parse the file names back when reading them.

Migrate class being static makes multi-migrations tough

The aerich.migrate.Migrate class that performs all the magic is a static class that only handles 1 app and does not perform cleanup. To support creating migrations, you need to do this between each app check:

Migrate.upgrade_operators = []
Migrate.downgrade_operators = []

While an easy fix is to have a cleanup function, making the class instantiated instead of static would prevent any leaks in the first place, and also allow commands to run in parallel.

init_db creates ALL tables

init_db always seemed to create all tables for all apps, even when applied to just 1 app. I think the intention is to just create the initial migrations table. I'd make this function only consider the aerich migrations table.

Aerich creates a migration file for itself

In a multi-app setup, considering where to put this is strange. It does make sense that one day you might need to update the aerich models and can use this mechanism, but storing updates as migrations files in a project's source code is a bit leaky since it's library implementation details and not application code.

Needed inspection functionality

Providing common checks would be helpful, such as "is the migrations table initialized?", and "Are there migrations that need to run?" since running the migrate command with pending migrations will overwrite them. These checks help develop interfaces that inform users why the migration behavior isn't working as expected.

Pending migrations are overwritten

As mentioned, pending migrations are overwritten instead of considered for diffing. This behavior goes against user expectations, and at a minimum should notify or error. Ideally diffs of pending migrations would be considered, and running migrate before upgrading would use the application state to decide what the latest model changes are, not the database state.

Documentation does not cover multi-app

This was mostly only an issue when I was trying to understand whether I needed an aerich model in every app or just 1 single one.

--

Hopefully my use case is something that the maintainers want to support. Combine these with the other RFC that is suggesting DB-agnostic migrations files and I think this will easily be one of the best database tools for python developers.

If you find these suggestions agreeable, I'd be happy to contribute. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions