Opened 9 years ago
Closed 9 years ago
#26469 closed Bug (duplicate)
FieldFile.open() does not properly set mode when opening file
Reported by: | Nathan Osman | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.9 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Consider the following model definition:
class Thing(models.Model): file = models.FileField(upload_to="things")
Let's suppose I have an existing model instance and I want to open the file for writing:
t = Thing.objects.get(pk=1) t.file.open('wb') t.file.write(data)
This raises an unexpected exception:
IOError: File not open for writing
Here's the source code for FieldFile.open()
:
def open(self, mode='rb'): self._require_file() self.file.open(mode)
The second line in the body accesses self.file
- a property which is defined as follows:
def _get_file(self): self._require_file() if not hasattr(self, '_file') or self._file is None: self._file = self.storage.open(self.name, 'rb') return self._file # ... file = property(_get_file, ...
If self._file
is None
(which is the case in my example above), the storage backend is then instructed to open the file with mode 'rb' instead of the mode that was originally passed to FieldFile.open()
. The newly opened File
instance is returned and control resumes in FieldFile.open()
which invokes the open()
method on the File
instance.
Here are the first few lines of File.open()
:
def open(self, mode=None): if not self.closed: self.seek(0) elif self.name and os.path.exists(self.name): self.file = open(self.name, mode or self.mode) # ...
Since the file is already open, not self.closed
evaluates to True
and the file remains open in read-only mode. It is not possible to write to the file.
Duplicate of #26398. This should be fixed in master.