How to PUT a file in Django
django pythonOnce we decide to go for PUT instead of POST, we step out the comfort zone of
Django, there is no mapped form filed, no validation, we have to deal with the
raw WSGI interface by ourselves. Anyway, we can still use the
django.core.file.File
class.
If we dig into the source code, the django.core.file.File
defines: open
,
close
, read
, tell
, seek
, flush
and some other django-specific
operations, like chunks
, readlines
, xreadlines
etc.
Ticket #8501 glues File
and file
object when chunks
method is missing.
It is interesting that the interface File
exposed explicitly requires that the
underlying file object supports random access, which is most likely overkill for
regular usage. Sometimes, less is more. And it implicitly expects read
will return EOF, which is also not true for WSGI.input
. So we end up to brew
our own:
class SocketFile(File):
# Only forward access is allowed
def __init__(self, socket, size):
super(SocketFile, self).__init__(socket)
self._size = int(size)
self._pos = 0
def read(self, num_bytes=None):
if num_bytes is None:
num_bytes = self._size - self._pos
else:
num_bytes = min(num_bytes, self._size - self._pos)
self._pos += num_bytes
return self.file.read(num_bytes)
def tell(self):
return self._pos
def seek(self, position):
pass
The SocketFile
object is initialized with the length of the socket file
object, aka CONTENT*LENGTH, the read
method guards the operation to return
EOF. seek
is inherited from File
, so just bypass it. Just wrap the raw
WSGI.input
with SocketFile
, and use it as File
. Please check
views.py
for the usage.