Proposal: add a flag to `showmigrations` that lists only unapplied migrations

Hey folks!

Awhile back a coworker of mine wrote a newmigrations command that just shows migrations that haven’t been run yet vs listing out all migrations with the checkboxes.

This feels like a nice thing that could be a flag added to showmigrations. I discussed this with several people at DjangoCon this year who also agreed this would be a nice thing to add.

Expected output:

./manage showmigrations --unapplied
app_a
 [ ] 0001_initial
 [ ] 0002_add_cool_stuff
app_b
 [ ] 0002_auto_20190129_2304

Lets say the above is a case where we have three apps, app_b already has it’s first migration run.

To be fair, this is somewhat similar to migrate --plan. But there a couple reasons why this could still be useful:

  • The output of migrate --plan is structured differently
  • For many folks, showmigrations is useful to debugging and checking the state on a given enviornment. Switching to use a different command just to avoid scrolling through long lists of already applied migrations is not ideal.
  • In some cases many folks don’t think to run migrate unless they actually want an operation to take place. Personally I’d avoid it lest a typo lead me to trying to run migrations when I don’t mean to.

I have an in progress example of what this could look like:

Open to any thoughts, feedback. Please comment if you would use this or think it’s a good idea, and also if you have any concerns!

5 Likes

I very much support this. I develop on Windows and, while I certainly have options to run ./manage.py showmigrations | grep '\[ \]' via git bash, wsl, or out on our central and cloud nodes, I don’t think it’s fair to presume that everyone else has the same access to tool, knowledge, and resources as I do. I have assisted people in standing up Django development purely on windows (including once while helped coach a Django Girls meetup) with no knowledge of git bash. It’s difficult enough for a newcomer to learn to use python, http, Django, etc. For us to also force upon them that they must develop knowledge of LSB utilities in order to gather a list of pending migrations is a heavy ask.

I very much support this proposal as I think it makes the library all the more user friendly.

2 Likes

+1 from me. Although --plan exists, it shows many lower-level details which can often be ignored.

@felixxm wrote on your initial PR that adding options is controversial. I see this one as less so since the showmigrations command has few options at current.

For symmetry, I suggest we also add --applied to show the list of applied migrations. I can imagine it would be useful for storing a “snapshot” when comparing environments.

1 Like

+1 from me, for all the reasons supplied by the previous two responses. (I also especially get tired of adding | grep '\[ \]' to the end of the showmigrations command.)

I’m a bit surprised. Migration-related commands already have a way to display unapplied migrations. Is it reasonable to add it to another command only because it’s not there yet?

  • showmigrations --plan displays flat list on migrations:
$ python manage.py showmigrations --plan
[X]  contenttypes.0001_initial
[ ]  auth.0001_initial
[ ]  admin.0001_initial
[ ]  admin.0002_logentry_remove_auto_add
[ ]  admin.0003_logentry_add_action_flag_choices

We can add grep and there is a flat list of unapplied migrations: python manage.py showmigrations --plan | grep -v "[X]".

  • migrate --plan displays list of unapplied migrations with operations. I don’t think operation lists are an issue here. How many unapplied migrations might you have and want to inspect at once?
$ python manage.py migrate --plan
Planned operations:
contenttypes.0001_initial
    Create model ContentType
    Alter unique_together for contenttype (1 constraint(s))
auth.0001_initial
    Create model Permission
    Create model Group
    Create model User
admin.0001_initial
    Create model LogEntry
admin.0002_logentry_remove_auto_add
    Alter field action_time on logentry
admin.0003_logentry_add_action_flag_choices
    Alter field action_flag on logentry
  • python manage.py showmigrations --list displays nested list of all migrations:
$ python manage.py showmigrations --list
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
auth
 [ ] 0001_initial
 [ ] 0002_alter_permission_name_max_length
 [ ] 0003_alter_user_email_max_length
 [ ] 0004_alter_user_username_opts
 [ ] 0005_alter_user_last_login_null
 [ ] 0006_require_contenttypes_0002
 [ ] 0007_alter_validators_add_error_messages
 [ ] 0008_alter_user_username_max_length
 [ ] 0009_alter_user_last_name_max_length
 [ ] 0010_alter_group_name_max_length
 [ ] 0011_update_proxy_permissions
 [ ] 0012_alter_user_first_name_max_length

We can add grep and we will get what the reported proposed: python manage.py showmigrations --list | grep -v "[X]". We normally don’t add new features for something that is already possible :person_shrugging:

I’m with felix on this one :man_shrugging::stuck_out_tongue:

One of the arguments for adding it was because the default window shell doesn’t have grep. We can use findstr instead:

(env) C:\Users\David\django\test_project>python ./manage.py showmigrations|findstr /v "[X]"
admin
auth
 [ ] 0010_alter_group_name_max_length
 [ ] 0011_update_proxy_permissions
 [ ] 0012_alter_user_first_name_max_length
contenttypes
sessions
 [ ] 0001_initial

I am sorry, I didn’t review what the output looks like. I got mixed up in the docs and thought that showmigratinos --plan acted like migrate --plan and showed operations not migrations. Therefore text filtering with grep (or find-str) would be too hard.

Thank you for gathering examples @felixxm. I agree that since one can achieve the result with a simple filter using grep or similar, there’s no need to expand the commands.

Not surprisingly, I still think it’s a simple enough add that would be more user/beginner friendly and not rely on usage of grep as an added step. :smile:

But so far it looks like in terms of comments on the proposal we are about evenly split (though I’ll note at DjangoCon I mentioned it to some other folks verbally who also thought it was a good idea), so for now I’ll avoid creating a ticket for it if it isn’t an idea likely to be accepted.

Perhaps it could be added to django-extensions until there are more are in favor of it being added to core?

1 Like