Opened 13 years ago
Last modified 9 years ago
#18283 assigned Bug
FileField should not reuse FieldFiles
Reported by: | Sayane | Owned by: | Andrzej Pragacz |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
A simple example:
old_image = mymodel.image old_image.open() try: mymodel.image = do_something_with_image(old_image) finally: old_image.close() mymodel.save() # transaction manager is in auto commit mode old_image.delete()
Expected behavior:
New file is commited to disk and database, old file is removed.
Actual behavior:
New file is commited to disk and database, then this new file is removed from disk.
That's because FileField (or to be more precise: FileDescriptor class) is re-using FieldFile objects instead of creating new FieldFile for every new instance of a file. This leads to unexpected results and data loss (like in example).
Change History (4)
comment:1 by , 13 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 9 years ago
Owner: | changed from | to
---|
comment:4 by , 9 years ago
Note:
See TracTickets
for help on using tickets.
I have a real trouble with reproducing this bug. The description of it is very enigmatic - the submitter didn't mention what
do_something_with_image()
actually does (for instance, what type of object it returns).This bug seems to happen only when one takes the
FieldFile
object from specified model field and modifies it in place. This is illustrated bytest_unchanged_fieldfile
in the diff below:https://github.com/django/django/compare/master...szopu:ticket_18283?expand=1
The only way I see this problem can be fixed, is defensive shallow copying of the
FieldFile
object in__get__
and__set__
(I think that doing it for__set__
only is not enough). But this solution has a downside, for instance, this would generate following semantics:So my question is: Is it the right way to go?