7

I don't want to create a migration file whenever I change the storage of the FileField. I am getting the storage class from settings.py and it is configurable.

settings.py

Storage =  S3BotoStorage(bucket='example')

models.py

 from django.conf import settings

 class myModel(models.Model):
        file = models.FileField(upload_to='', blank=True, storage=settings.Storage)
3
  • If storage is not specified in settings then default storage is used and migrations are created. If I change the storage after an initial migration then a new migration file is created, which I don't want to happen. Commented Dec 14, 2016 at 8:24
  • Did you find an answer for this ? I have a similar issue. Commented Jul 22, 2019 at 14:22
  • I'm having this same issue as well. Did you ever find a solution? Commented Jul 22 at 16:47

4 Answers 4

9

TLDR: It's an empty migration, it's harmless let it be reading any further or trying different things is probably just a waste of time

When ever you make a change to a model django has to make a migration because it needs to keep track of what changes have been made to a model over time. However that does not always mean that a modification will be made in the database. The migration produced here is an empty one. Your migration probably looks something like this and you will say, hay that's not empty!!

class Migration(migrations.Migration):

    dependencies = [
        ('stackoverflow', '0010_jsonmodel'),
    ]

    operations = [
        migrations.AlterField(
            model_name='jsonmodel',
            name='jfield',
            field=stackoverflow.models.MyJsonField(),
        ),
        migrations.AlterField(
            model_name='parent',
            name='picture',
            field=models.ImageField(storage=b'Bada', upload_to=b'/home/'),
        ),
    ]

But it is!! just do

./manage.py sqlmigrate <myapp> <migration_number>

And you will find that it does not produce any SQL! Quote from the manual as suggested by @sayse

Django will make migrations for any change to your models or fields - even options that don’t affect the database - as the only way it can reconstruct a field correctly is to have all the changes in the history, and you might need those options in some data migrations later on (for example, if you’ve set custom validators).

Sign up to request clarification or add additional context in comments.

6 Comments

@e4c5 sqlmigrate show the sql statement but i dont want the migration file to be created. Is that possible in anyway?
no it's not possible. refer to the updated answer. And why should having an empty migration be a problem at all?
Migrations in my use case will cause migration history conflicts.
how can that be so?
I have published a package with say 5 migrations on pyPi and now if someone installs that package and runs nake migration after changing the storage class then it will create a migration file number 6. And if i make any changes to the package and publish it again on pyPi with a new migration 6.There would be migration conflicts.
|
2

Yet a simpler solution is to use a callable to select the storage:

def select_storage():
    return storages[settings.STORAGE_CLASS]

file = models.FileField(upload_to='videos/%Y/%m/%d/', storage=select_storage, blank=True, null=True, verbose_name=_('file'))

This way you'll not get a new migration if you change the STORAGE_CLASS.

1 Comment

I had a similar problem as well, and using a callable solved the problem. For some reason I was'nt able to find this question and SO did'nt suggest it on my original question on stackoverflow.com/q/79709513/8297745
0

Here is a simple solution I implemented for my video uploads that could be uploaded using different storage.

  1. Implement a storage class that acts as a wrapper to the actual storage implementation:
@deconstructible(path="travel.apps.vod.models.VideoStorage")
class VideoStorage:

    def __init__(self):
        self.storage = storages[settings.VOD_STORAGE]

    def __getattr__(self, item):
        return getattr(self.storage, item)

If you want you can inherit from Storage class, and implement all of its methods, by calling the method self.storage, but I prefer this short implementation.

  1. Use an instance of this storage on your file field:
class SomeClass(models.Model):

    file = models.File(storage=ViedeoStorage(), ....)

Note: Since the class in my implementation is not a subclass of Storage you need to use an instance as in storage=ViedeoStorage(), instead of a callable, otherwise Django will raise an error.

  1. Define different storage classes in your settings (it's up to you how to handle this part)
 STORAGES = {
            'default': {
                'BACKEND': self.DEFAULT_STORAGE_CLASS,
            },
            'staticfiles': {
                'BACKEND': 'travel.core.storage.CompressedManifestStaticFilesStorage',
            },
            'local': {
                'BACKEND': 'django.core.files.storage.FileSystemStorage',
            },
            's3': {
                'BACKEND': 'storages.backends.s3.S3Storage',
            },
        }

VOD_STORAGE = 's3'

Now whenever you change the VOD_STORAGE to select a different storage for your files, no migration will be generated.

P.S. you'll have one migration after you changed to this new storage, but this it.

Comments

-1

Here is my interpretation to your question - You want to use the storage class (which can be changed in future) specified in your settings.py to store the files.

Suppose you specify xyz storage class in your settings.py and run makemigrations. Django will create a migration file with storage attribute as the one you had specified in the settings.py.

Now if you change the storage class in the settings.py and do not run makemigrations and upload your file, your file will get uploaded to the new storage you specified in the settings file even if you do not run makemigrations.

Hope it helps.

2 Comments

Yes this would help but what if i run makemigrations in my build script? Then migrations will be created.
Did you find a solution? I got the same problem. My local settings are different than other devs so each time someone does a migration the path changes in the migration file because of different paths

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.