6
votes

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...?

1
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
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
There's some discussion of migrations and storages in the Django tracker (22373 and 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
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

1 Answers

1
votes

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.