[Django] #36824: FileField storage parameter should support string references to STORAGES dict keys

1 view
Skip to first unread message

Django

unread,
Dec 23, 2025, 9:46:19 AM (3 days ago) Dec 23
to django-...@googlegroups.com
#36824: FileField storage parameter should support string references to STORAGES
dict keys
-----------------------------+-----------------------------------------
Reporter: Petr Dlouhý | Type: New feature
Status: new | Component: Uncategorized
Version: 6.0 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-----------------------------+-----------------------------------------
= Summary =

FileField's `storage` parameter doesn't support string references to
`STORAGES` dict keys, despite Django 4.2+ establishing STORAGES as the
standard configuration method. This creates confusion and forces
workarounds.

= Description =

Django 4.2 introduced the `STORAGES` setting as a centralized dictionary
for configuring storage backends, deprecating `DEFAULT_FILE_STORAGE`.
However, `FileField` and `ImageField` don't support string references to
these storage keys.

== Current Behavior ==

{{{
#!python
# settings.py
STORAGES = {
"default": {...},
"private_assets": {...},
}

# models.py
from django.core.files.storage import storages

# This works - but verbose and requires callable wrapper
def get_private_storage():
return storages["private_assets"]

class MyModel(models.Model):
file = models.FileField(storage=get_private_storage)
}}}

== Expected Behavior ==

{{{
#!python
# This should work - consistent with STORAGES design
class MyModel(models.Model):
file = models.FileField(storage="private_assets")
}}}

== Problem ==

When developers try the intuitive approach (`storage="private_assets"`),
Django stores it as a string. This fails silently until runtime when code
accesses `field.storage`, causing:

{{{
AttributeError: 'str' object has no attribute 'path'
}}}

This is particularly problematic for third-party libraries (like `easy-
thumbnails`) that access `field.storage` directly and expect a storage
object, not a string.

= Inconsistency =

The `STORAGES` dict uses string keys everywhere:
* ✅ `settings.STORAGES["default"]` - configuration
* ✅ `storages["private_assets"]` - runtime access
* ✅ `THUMBNAIL_DEFAULT_STORAGE = "thumbnails"` - library settings
* ❌ `FileField(storage="name")` - '''doesn't work'''

This breaks the principle of least surprise. If Django establishes a
pattern (string keys for storage), it should work consistently across the
framework.

= Real-World Impact =

I encountered this while implementing Django STORAGES support for `easy-
thumbnails`. Users naturally try `storage="name"` based on the STORAGES
pattern, and it fails with a cryptic error. This forced me to add
defensive string resolution in the library.

= Proposed Solutions =

'''Option A: Support string storage in FileField (Recommended)'''

Add string resolution in `FileField.__init__()`:

{{{
#!python
def __init__(self, ..., storage=None, **kwargs):
self.storage = storage or default_storage

# Resolve string references to STORAGES dict
if isinstance(self.storage, str):
from django.core.files.storage import storages
self.storage = storages[self.storage]

if callable(self.storage):
self._storage_callable = self.storage
self.storage = self.storage()
...
}}}

'''Benefits:'''
* Consistent with STORAGES design
* Intuitive for developers
* Backwards compatible (no breaking changes)
* ~5 lines of code

'''Option B: Document that string storage is not supported'''

If supporting string storage is not desired, clearly document in
`FileField` docs:

{{{
Note: The storage parameter does not support string references to STORAGES
dict keys.
Use a callable function to reference configured storages:

def get_my_storage():
from django.core.files.storage import storages
return storages["my_storage"]

file = models.FileField(storage=get_my_storage)
}}}

This at least prevents confusion and provides a clear workaround.

= Migration Behavior =

String storage resolution wouldn't create migration issues because:
* Strings would be resolved at model load time (like callables)
* Migrations would store the string reference, not the resolved object
* This mirrors how callable storage already works

= Backwards Compatibility =

Fully backwards compatible - existing code using storage objects or
callables continues working unchanged.

= Related Tickets =

* #31941 - FileField with callable storage deconstruction
* #34192 - Callable storage returning default_storage

= Questions =

1. Was excluding string storage from FileField intentional, or an
oversight during STORAGES implementation?
2. If intentional, what's the reasoning? (I'd like to understand the
design decision)
3. If not desired as a feature, can we at least improve documentation to
prevent this confusion?
--
Ticket URL: <https://code.djangoproject.com/ticket/36824>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Dec 23, 2025, 11:00:45 AM (3 days ago) Dec 23
to django-...@googlegroups.com
#36824: FileField storage parameter should support string references to STORAGES
dict keys
-------------------------------------+-------------------------------------
Reporter: Petr Dlouhý | Owner: (none)
Type: New feature | Status: closed
Component: File | Version: 6.0
uploads/storage |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* component: Uncategorized => File uploads/storage
* resolution: => wontfix
* status: new => closed

Comment:

Replying to [ticket:36824 Petr Dlouhý]:

Hello Petr! The `storage` option works exactly as described in the
[https://docs.djangoproject.com/en/6.0/ref/models/fields/#django.db.models.FileField.storage
docs]:

> A storage object, or a callable which returns a storage object.

When suggesting a new feature for Django, the feature should first be
proposed and discussed with the community. To do that, please raise this
on the [https://github.com/orgs/django/projects/24 new feature tracker]
where you'll receive feedback from the community.

I'll close the ticket for now, but if the community agrees with the
proposal, please return to this ticket and reference the feature
discussion so we can re-open it. For more information, please refer to
[https://docs.djangoproject.com/en/stable/internals/contributing/bugs-and-
features/#requesting-features the documented guidelines for requesting
features].


Lastly, please avoid using LLM to generate overly verbose reports.
--
Ticket URL: <https://code.djangoproject.com/ticket/36824#comment:1>
Reply all
Reply to author
Forward
0 new messages