Once 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
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 gatekeeps 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.