Reputation: 942
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)
Upvotes: 6
Views: 2075
Reputation: 357
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
.
Upvotes: 0
Reputation: 357
Here is a simple solution I implemented for my video uploads that could be uploaded using different storage.
@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.
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.
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.
Upvotes: 0
Reputation: 53774
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).
Upvotes: 9
Reputation: 2603
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.
Upvotes: -1