11π
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?
8π
Upgrading to Django 3.1+ fixes this: https://docs.djangoproject.com/en/3.2/releases/3.1/#file-storage
Just pass a callable into the storage argument.
from django.db import models
from django.conf import settings
from django.core.files.storage import get_storage_class
def _get_storage():
storage_class = get_storage_class(settings.MY_STORAGE_CLASS) # ie. 'django.core.files.storage.FileSystemStorage'
return storage_class()
class MyModel(models.Model):
myfile = models.FileField(max_length=255, blank=True, storage=_get_storage)
- [Django]-Heroku β Handling static files in Django app
- [Django]-Updated at field in django model
- [Django]-Celery task that runs more tasks
2π
The solution is to never run makemigrations
on production. Run migrate
all you want on production servers, but ignore warnings about running makemigrations
if they pertain to this issue.
Think about it: makemigrations
generates Python code, so running it on production would be the same as developing on that server. Depending on your server setup, your production site will likely serve those files correctly regardless of the makemigrations
warning.
- [Django]-Django logging custom attributes in formatter
- [Django]-How can I get a decimal field to show more decimal places in a template?
- [Django]-Django β TypeError β save() got an unexpected keyword argument 'force_insert'
2π
My problem was related, but slightly different. The storage class used by the field can change based on settings: the default locally, remote storage in production. I implemented a subclass of FileField
that ignores the storage kwarg when deconstructing the field for migration generation.
from django.db.models import FileField
class VariableStorageFileField(FileField):
"""
Disregard the storage kwarg when creating migrations for this field
"""
def deconstruct(self):
name, path, args, kwargs = super(VariableStorageFileField, self).deconstruct()
kwargs.pop('storage', None)
return name, path, args, kwargs
It can be used like this:
class MyModel(models.Model):
storage = get_storage_class(getattr(settings, 'LARGE_FILE_STORAGE', None))()
file = VariableStorageFileField(blank=True, null=True, storage=storage)
- [Django]-How to re-use a reusable app in Django
- [Django]-Django py.test does not find settings module
- [Django]-How to create GIN index in Django migration