diff options
| author | François Freitag <mail@franek.fr> | 2023-06-17 18:00:43 +0200 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-06-19 05:24:42 +0200 |
| commit | bcacc6321ae819965f478bfee2072a796801f298 (patch) | |
| tree | a032506dd7acc495623293c0cd0e7cdfecfa71eb | |
| parent | 0c5146523b614783b60ba9f9222769dff83c776c (diff) | |
Refs #34517 -- Restored skipping ImageFileField.update_dimension_fields without width/height fields.
This avoids reading the image size when the dimensions fields
(image_width, image_height) do not exist, as that operation may be
expensive.
Partially reverts ea53e7c09f1b8864c20c65976bbeaeab77abdaec, that dropped
the check for the dimension fields in update_dimension_fields(), because
the post_init signal was no longer registered without dimension fields.
However, another code path to that function exists: when the
ImageFileField is save()d, the name from the storage is setattr()ed on
the field, and ImageFileDescriptor calls update_dimension_fields()
because the image size might have changed. Keep bailing out early when
dimensions are unused.
Besides, computing the image dimensions causes to close() the file,
resulting in a backward-incompatible change. The test protects against
that change.
| -rw-r--r-- | django/db/models/fields/files.py | 6 | ||||
| -rw-r--r-- | tests/model_fields/test_imagefield.py | 7 |
2 files changed, 11 insertions, 2 deletions
diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index e10c8cd69a..95985684ee 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -458,8 +458,10 @@ class ImageField(FileField): Dimensions can be forced to update with force=True, which is how ImageFileDescriptor.__set__ calls this method. """ - # Nothing to update if the field is deferred. - if self.attname not in instance.__dict__: + # Nothing to update if the field doesn't have dimension fields or if + # the field is deferred. + has_dimension_fields = self.width_field or self.height_field + if not has_dimension_fields or self.attname not in instance.__dict__: return # getattr will call the ImageFileDescriptor's __get__ method, which diff --git a/tests/model_fields/test_imagefield.py b/tests/model_fields/test_imagefield.py index 81ac9dad61..8bbfee30f2 100644 --- a/tests/model_fields/test_imagefield.py +++ b/tests/model_fields/test_imagefield.py @@ -336,6 +336,13 @@ class ImageFieldNoDimensionsTests(ImageFieldTwoDimensionsTests): [sender_id for (_, sender_id), *_ in signals.post_init.receivers], ) + def test_save_does_not_close_file(self): + p = self.PersonModel(name="Joe") + p.mugshot.save("mug", self.file1) + with p.mugshot as f: + # Underlying file object wasn’t closed. + self.assertEqual(f.tell(), 0) + @skipIf(Image is None, "Pillow is required to test ImageField") class ImageFieldOneDimensionTests(ImageFieldTwoDimensionsTests): |
