In my Django app I use a FileSystemStorage
for generated files. I initialize it like this:
import os from urlparse import urljoin from django.conf import settings from django.core.files.storage import FileSystemStorage gen_files_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'generated/'), base_url=urljoin(settings.MEDIA_URL, 'generated/'))
When I want to create a new file I use:
from django.core.files.base import ContentFile from django.db import models def next_number(): # num = ... return num gen_file = models.FileField(storage=gen_files_storage) gen_file.save('file%s.txt' % next_number(), ContentFile(''))
That works fine. The only problem is that the FileSystemStorage
's path is "hardcoded" in the Django migration. Because I use different settings for development (which changes) and production, often the manage.py makemigrations
command generates a migration only because the path changed, although everything stays the same in the database.
I know there is a solution using a subclass of FileSystemStorage
(see my answer below), but is there a better solution?
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 ...
you can either: temporarily remove your migration, execute python manage.py migrate, add again your migration and re-execute python manage.py migrate. Use this case if the migrations refer to different models and you want different migration files for each one of them.
Django writes a record into the table django_migrations consisting of some information like the app the migration belongs to, the name of the migration, and the date it was applied.
There is a solution involving a custom @deconstructible
subclass of FileSystemStorage
:
import os from urlparse import urljoin from django.conf import settings from django.core.files.storage import FileSystemStorage from django.utils.deconstruct import deconstructible @deconstructible class MyFileSystemStorage(FileSystemStorage): def __init__(self, subdir): self.subdir = subdir super(MyFileSystemStorage, self).__init__(location=os.path.join(settings.MEDIA_ROOT, self.subdir), base_url=urljoin(settings.MEDIA_URL, self.subdir)) def __eq__(self, other): return self.subdir == other.subdir
Then I can initialize the storage like this:
import os from urlparse import urljoin from django.conf import settings from django.core.files.storage import FileSystemStorage gen_files_storage = MyFileSystemStorage('generated/')
This way Django migrations won't notice changes in my settings. Is there a better way though?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With