[Django] #36622: FileField.__init__ is triggering storage LazyObject resolution at boot time

8 views
Skip to first unread message

Django

unread,
Sep 26, 2025, 9:55:51 AM9/26/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Type:
| Uncategorized
Status: new | Component: Database
| layer (models, ORM)
Version: 5.2 | 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
-------------------------------------+-------------------------------------
There is this code in `FileField.__init__` :

{{{
self.storage = storage or default_storage
}}}

The problem is that if we want to have a LazyObject as storage for the
field, it is still resolved at boot time, and it seems unecessary to
trigger resolution at this moment. This seems not expected as the
documentation itself suggest to use LazyObject in case we require a
callable to be overridable during tests :
https://docs.djangoproject.com/en/5.2/topics/files/#using-a-callable

Using `storage or default_storage` is calling `storage.__bool__` which
trigger resolution on default LazyObject.

A solution would be to change this line by :

{{{
self.storage = storage if storage is not None else default_storage
}}}



A workaround for the case specified in the documentation is to override
__bool__ on LazyObject so it always returns True.



{{{
class OtherStorage(LazyObject):
def _setup(self):
self._wrapped = storages["mystorage"]

def __bool__(self):
return True
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36622>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 26, 2025, 9:56:32 AM9/26/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
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 Fabien MICHEL):

* type: Uncategorized => Bug

--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:1>

Django

unread,
Sep 26, 2025, 9:58:58 AM9/26/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Fabien MICHEL:

Old description:

> There is this code in `FileField.__init__` :
>
> {{{
> self.storage = storage or default_storage
> }}}
>
> The problem is that if we want to have a LazyObject as storage for the
> field, it is still resolved at boot time, and it seems unecessary to
> trigger resolution at this moment. This seems not expected as the
> documentation itself suggest to use LazyObject in case we require a
> callable to be overridable during tests :
> https://docs.djangoproject.com/en/5.2/topics/files/#using-a-callable
>
> Using `storage or default_storage` is calling `storage.__bool__` which
> trigger resolution on default LazyObject.
>
> A solution would be to change this line by :
>
> {{{
> self.storage = storage if storage is not None else default_storage
> }}}
>

>
> A workaround for the case specified in the documentation is to override
> __bool__ on LazyObject so it always returns True.
>

>
> {{{
> class OtherStorage(LazyObject):
> def _setup(self):
> self._wrapped = storages["mystorage"]
>
> def __bool__(self):
> return True
> }}}

New description:

There is this code in `FileField.__init__` :

{{{
self.storage = storage or default_storage
}}}

The problem is that if we want to have a LazyObject as storage for the
field, it is still resolved at boot time, and it seems unecessary to
trigger resolution at this moment. This seems not expected as the
documentation itself suggest to use LazyObject in case we require a
callable to be overridable during tests :
https://docs.djangoproject.com/en/5.2/topics/files/#using-a-callable

Using `storage or default_storage` is calling `storage.__bool__` which
trigger resolution on default LazyObject.

A solution would be to change this line by :

{{{
self.storage = storage if storage is not None else default_storage
}}}



A workaround for the case specified in the documentation is to override
`__bool__` on `LazyObject` so it always returns True.



{{{
class OtherStorage(LazyObject):
def _setup(self):
self._wrapped = storages["mystorage"]

def __bool__(self):
return True
}}}

--
--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:2>

Django

unread,
Sep 26, 2025, 10:04:22 AM9/26/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Sarah Boyce):

Related #36504
--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:3>

Django

unread,
Sep 29, 2025, 5:42:15 AM9/29/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: closed
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution: duplicate
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 Sarah Boyce):

* resolution: => duplicate
* status: new => closed

Comment:

Thank you for the ticket! I have tested and I agree with this approach.
Given there were some efforts started in #36504, I have added a comment
there and marking this as a duplicate to try and prevent
contradictory/overlapping effort
--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:4>

Django

unread,
Oct 9, 2025, 3:45:04 PM10/9/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
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 Clifford Gama):

* resolution: duplicate =>
* status: closed => new

Comment:

Reopening because this issue can be fixed independently of #36504--it
neither contradicts nor, strictly speaking, overlap. The reason being that
for `override_settings` to work on custom storages, we still need to write
a custom signal receiver. It only seems to work now because we're
resolving for the first time after calling `override_settings`. However,
whatever value is accessed will persist and cannot be overridden again.

The following modification to the docs example should demonstrate:

{{{#!python
def test_storage(self):
model = MyModel()
self.assertIsInstance(model.upload.storage, FileSystemStorage) #
Assuming this is in settings
with override_settings(
STORAGES={
"mystorage": {
"BACKEND": "django.core.files.storage.InMemoryStorage",
}
}
):
self.assertIsInstance(model.upload.storage, InMemoryStorage)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:5>

Django

unread,
Oct 9, 2025, 3:54:11 PM10/9/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Clifford Gama):

* has_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:6>

Django

unread,
Oct 15, 2025, 10:09:03 AM10/15/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* stage: Unreviewed => Accepted

Comment:

Thank you Clifford for your detailed explanation.
--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:7>

Django

unread,
Oct 15, 2025, 5:23:34 PM10/15/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* stage: Accepted => Ready for checkin

--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:8>

Django

unread,
Oct 15, 2025, 9:07:49 PM10/15/25
to django-...@googlegroups.com
#36622: FileField.__init__ is triggering storage LazyObject resolution at boot time
-------------------------------------+-------------------------------------
Reporter: Fabien MICHEL | Owner: (none)
Type: Bug | Status: closed
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* resolution: => fixed
* status: new => closed

Comment:

Fixed in `main` in 6862d46dd96d71d80d6d2fa9873a93d811b39562.
Fixed in `[6.0.x]` in 5c114ce2d8479549ee9dd486bc28df5b2e3d54ad.
--
Ticket URL: <https://code.djangoproject.com/ticket/36622#comment:9>
Reply all
Reply to author
Forward
0 new messages