• 
      

    Make MoveToDjangoMigrations work when the app isn't yet in the database.

    Review Request #14530 — Created July 30, 2025 and submitted — Latest diff uploaded

    Information

    Django Evolution
    release-2.x

    Reviewers

    MoveToDjangoMigrations had a dependency on the migrations being
    applied. The idea was that:

    1. If this was a new app in the database, we'd want migrations to handle
      any initial work first.

    2. If the app was already installed, but the evolution was new, those
      migrations would have already been applied.

    The problem was that the first case didn't necessarily work right.

    We could reach a state where the migrations weren't in the graph, and
    the dependency would break. This could happen if installing an app that
    has both migrations and evolutions defined as custom for the app.
    There's no signature for the app yet, and we have evolutions, so we
    prioritize those and skip the migrations (so we can deal with any
    potentially-broken state in the migratinos).

    In this case, there was no way of really communicating that the
    migrations should have been in the graph but also should not have been
    applied since the evolution replaces them.

    This change adds that capability. Along with the before/after
    migrations/evolutions dependencies, there's now a new
    replace_migrations dependency type that works like after_migrations
    but makes the dependencies optional. This allows them to depend on a
    recorded migration if it's in the graph as before, but to proceed
    without failure if that migration wasn't found in the graph.

    With that, we can keep a consistent graph in the case where the
    migration would have been processed or picked up, but without requiring
    it to be applied or recorded first in this case.

    The new test app (move_to_migrations_app) simulates a module that
    (in cooperation with the test setup) builds upon a faulty base (a
    0001_initial that contains a superset of the fields actually in the
    base model), adds missing fields in the evolution, hands it off to
    Django, and then adds a field via a migration. This simulates the kind
    of problems we've seen in some third-party apps that squash history back
    down into a 0001_initial over time.

    There are also fixes for the upgrade tests, which had previously been a
    no-op due to a leftover return, masking some bad test harness setup.

    Tested on all versions of Django, on all supported databases.

    Commits

    Files