6

My Django 1.8 app uses a third-party app (django-avatar) whose model contains an ImageField. I'm also using a custom DEFAULT_FILE_STORAGE (S3BotoStorage from django-storages-redux) in my project's settings.py. As a result, every time I run manage.py migrate, I get this warning about the avatar app:

Your models have changes that are not yet reflected in a migration, and so won't be applied. Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

... because avatar's initial migration references Django's default FileSystemStorage. Running makemigrations creates a new 0002 migration in the avatar app, to make its ImageField's storage match my project setting:

...
migrations.AlterField(
    model_name='avatar',
    name='avatar',
    field=models.ImageField(storage=storages.backends.s3boto.S3BotoStorage(), max_length=1024, upload_to=avatar.models.avatar_file_path, blank=True),
),

The problem is, this new migration is created in avatar installed in python's site-packages, outside my project (so outside git control, unavailable for deployment, etc.).

What's the right way to handle migrations for a third-party app that uses an ImageField (or FileField) in a project with custom DEFAULT_FILE_STORAGE? I've considered:

  • Just ignore the warning. The migration to change storage doesn't actually affect the DB schema, and since my project's DEFAULT_FILE_STORAGE has been S3BotoStorage since the start, no data migration is needed.

  • Use settings.MIGRATION_MODULES to move avatar's migrations into my project. (And then carefully port over every future avatar migration to my copy--which seems error-prone.) [EDIT: this comment on the django-users mailing list suggests this is the wrong approach.]

  • Ask the django-avatar (or django-storages-redux) maintainers to change... what? (BTW, S3BotoStorage is already deconstructible -- that's not the problem.)

  • Or...?

medmunds
  • 5,950
  • 3
  • 28
  • 51
  • Hey medmunds, I'm the current maintainer of django-avatar and I would also like to know the answer to this. Do you think creating a another migration that changes the `ImageField.storage` attribute to reference `settings.AVATAR_STORAGE` would prevent this? – grantmcconnaughey Feb 14 '16 at 23:46
  • Hey Grant, thanks for the package! So, you'd add a schema migration to django-avatar and manually edit it to have something like `storage=get_storage_class(settings.AVATAR_STORAGE)()`? I think that might solve my problem, but you'd have to remember to edit every future django-avatar schemamigration the same way. Also, it *might* cause problems for people truly trying to migrate from one storage to another, because it wouldn't be freezing the state at the time of the migration (maybe -- not sure about this). – medmunds Feb 15 '16 at 18:36
  • There's some discussion of migrations and storages in the Django tracker ([22373](https://code.djangoproject.com/ticket/22373) and [22337](https://code.djangoproject.com/ticket/22337)), but none of it in the context of third-party apps. I wonder if it would help to raise the issue over there? – medmunds Feb 15 '16 at 18:42
  • Yes, that is what I'm talking about. I think you're right about the issue of it not freezing the state of the migration. Even if I change it to use `AVATAR_STORAGE` that still won't fix the issue of changing `AVATAR_STORAGE` during a project's life. I'm really not sure how to go about this. I'll look into raising an issue. – grantmcconnaughey Feb 15 '16 at 22:09

1 Answers1

1

The answer is... Ask the django-avatar maintainers to fix it.

If you want to simply use the default storage you should pass None or django.core.files.storage.default_storage to ImageField. In this case storage kwarg will not be passed to the field in the migration.

I created PR to fix this.

Sergey Fedoseev
  • 2,800
  • 2
  • 18
  • 16
  • Nice: `default_storage` -- didn't know about that. Won't django-avatar now also need a new migration to override the explicit reference to `django.core.files.storage.FileSystemStorage()` in its [initial migration](https://github.com/grantmcconnaughey/django-avatar/blob/2.1.1/avatar/migrations/0001_initial.py#L23)? – medmunds May 26 '16 at 00:44
  • @medmunds I just modified existing migration in PR, however I'm not sure if this is correct approach/ – Sergey Fedoseev May 26 '16 at 06:27