Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django migrations and FileSystemStorage depending on settings

Tags:

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?

like image 921
geckon Avatar asked Sep 02 '15 09:09

geckon


People also ask

In what circumstances would you use the migrate command in Django?

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

How do I fix migration issues in Django?

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.

How does Django know which migrations have run?

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.


1 Answers

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?

like image 168
geckon Avatar answered Oct 05 '22 05:10

geckon