#FileField Migration Using Custom FileSystemStorage Location

5 messages · Page 1 of 1 (latest)

mild cipher
#

Note: there's an existing SO post for this (https://stackoverflow.com/questions/75470649/how-to-use-a-relative-path-for-django-filestorage-location-in-migrations), but I didn't find either of the answers there helpful/complete.

Summary: When I create a migration to add a FileField that uses a FileSystemStorage with a custom location, the location in the migration is specified as an absolute path specific to my filesystem.

At a high level, I'm trying to add another storage option (not change the default storage option) to Django's defaults where I can store files that I never want to serve later. I used the STORAGES setting to accomplish this:

BASE_DIR = Path(__file__).resolve().parent.parent
PRIVATE_MEDIA_ROOT = BASE_DIR / 'unserved-media'
STORAGES = {
    ...
    'private': {
        'BACKEND': 'django.core.files.storage.FileSystemStorage',
        'OPTIONS': {
            'location': PRIVATE_MEDIA_ROOT,
            'base_url': '/do/not/use/this/',
        },
    },
}

I'm using it in my models like so:

from django.core.files.storage import storages
file = models.FileField(upload_to=..., storage=storages['private'])

When I make my migration, it turns out like this:

migrations.AlterField(
    ...
    name='file',
    field=models.FileField(
        storage=django.core.files.storage.FileSystemStorage(
            base_url='/do/not/use/this/',
            # This is the important part.
            location=pathlib.PurePosixPath(
                '/absolute/path/specific/to/my/system/unserved-media'
            ),
        ),
        upload_to=...,
    ),
),

First of all, does the location argument here in the migration even matter? If the deployed environment is configured correctly, will having this path in the migration actually affect anything? Second, how do I get the migration not to specify a static/absolute path here? Even if I try to remove it manually, the next migration picks it up and adds it.

open light
#

You could add the Path() manipulation to the migration file also, something like location=pathlib.Path(__file__).parent.parent.parent / "unserved-media") or something like that

#

I often edit migration files to contain the same code as settings.py or some other file to avoid this exact problem. It works fine.

#

You could maybe also do storage=storages["private"]. Of course the migration framework will not pick up possibly relevant changes then (if it even works at all)

mild cipher
#

Manually replacing with storages["private"] in the migration did work. Thanks for your help. I posted an answer on SO as well.