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, flushand 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.