Project

General

Profile

Story #1372

Handle PUT like POST in Django

Added by Roger Dahl over 13 years ago. Updated over 12 years ago.

Status:
Closed
Priority:
Low
Assignee:
Category:
d1_mn_GMN
Target version:
-
Start date:
2011-02-16
Due date:
% Done:

100%

Story Points:
Sprint:

Description

Django currently has only minimal support for PUT. It is recognized in the Django community that PUT should be handled pretty much like POST, but as of version 1.2.5 final, this has not been implemented.

Django ticket and discussion:

http://code.djangoproject.com/ticket/12635
http://groups.google.com/group/django-users/browse_thread/thread/5e04a8ffeaa36c7?hl=en&pli=1


Subtasks

Task #1373: Fix support for PUT in DjangoClosedRoger Dahl

Task #1374: Push Django patch into trunkClosedRoger Dahl

History

#1 Updated by Dave Vieglais over 13 years ago

  • Position set to 16
  • Target version changed from Sprint-2011.10-Block.2 to Sprint-2011.11-Block.2

#2 Updated by Dave Vieglais over 13 years ago

  • Target version changed from Sprint-2011.11-Block.2 to Sprint-2011.12-Block.2
  • Position set to 1
  • Position deleted (22)

#3 Updated by Dave Vieglais over 13 years ago

  • Target version deleted (Sprint-2011.12-Block.2)
  • Position deleted (22)
  • Position set to 1
  • Position changed from 1 to 175

#4 Updated by Roger Dahl about 13 years ago

Django has good support for form data and file uploads through the standard
method, using POST with MIME multipart. When Django receives a POST, it
branches out to a separate code path that buffers up the request and makes
it available as a stream to view methods. However, this special handling
of MMP documents is triggered by the method, POST, and not by the document
type. The result is that it's not possible to take advantage of the
functionality when PUT is used as part of a REST interface.

Workarounds that have been tried:

  • Working around the limitation by changing the REST interface so that two
    operations against the same resource use two different URLs instead of two
    different methods (POST and PUT). That way, a POST can be used for both
    operations. This works, but requires changing the REST interface spec.

  • Create a layer that sits between wsgi and the main part of Django, which
    directs PUT into the same code path as POST. We had this working but it broke
    after a Django update. It should be possible to get this working, but we will
    have to keep updating it when it breaks after Django updates.

  • In the Django 1.3 docs, describing the new class based views
    (http://docs.djangoproject.com/en/1.3/ref/class-based-views/), I found the
    following:

get_form_kwargs()
Build the keyword arguments requried to instanciate an the form. The initial
argument is set to get_initial(). If the request is a POST or PUT, the
request data (request.POST and request.FILES) will also be provided.

This indicated to me that the PUT issue had been fixed in 1.3, so I set up a
VM with 1.3 and wrote a test project. I first issued a POST and verified that
the information appeared in request.POST and request.FILES. Then I changed the
POST to a PUT, but could not get the data to appear in request.POST,
request.FILES or anywhere else in the request object. I was also not able to
find anything about PUT support in the 1.3 release notes.

  • When Django receives a PUT request, the data in the request body is captured in request.raw_post_data. It is possible for a view to parse out this information to support PUT of form data or files. The problem with this approach is that the entire object is buffered in memory, preventing the system from handling big files and from scaling up to handling multiple clients, each submitting small files.

Resources related to this issue:

Ticket #5682 (closed: wontfix)
Support data sent via HTTP PUT in HttpRequest
http://code.djangoproject.com/ticket/5682

~~

Add head, options, put, delete to test Client
Ticket #5888 (closed: fixed)
http://code.djangoproject.com/ticket/5888

~~

Django REST extensions

Django Piston
A mini-framework for Django for creating RESTful APIs.
https://bitbucket.org/jespern/django-piston/wiki/Home
django-piston-resource-error-handler / piston / utils.py
https://bitbucket.org/mcordes/django-piston-resource-error-handler/src/fde50de72c4b/piston/utils.py

django-rest-interface: A generic REST interface for Django
http://code.google.com/p/django-rest-interface/

Django REST framework
http://django-rest-framework.org

"Another contrib package for easy REST based interfaces in Django"
http://code.google.com/p/django-restapi/
django-restapi

~~

http://markmail.org/message/ni7hfdhj5ssxfwkr
A little change to wsgi.py for PUT method.

I found that in django development server , the data posted with PUT method
can't be accessed using request.POST . While it's ok with apache !

So I made a little change to django/core/handlers/wsgi.py , I've changed line
110 to : if self.method in ['POST', 'PUT']:

Maybe we should change the whole _load_post_and_files method in wsgi.py to be
like the one in modpython.py:

def _load_post_and_files(self):
"Populates self._post and self._files"
if self._req.headers_in.has_key('content-type') and self._req.headers_in['content-type'].startswith('multipart'):
self._post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)
else:
self._post, self._files = http.QueryDict(self.raw_post_data), datastructures.MultiValueDict()

~~

wsgicollection
http://bitworking.org/news/wsgicollection

~~

Look into the request.META['wsgi.input'] object.

~~

Changes to request_response have broken django-rest-interface:

http://django-rest-interface.googlecode.com/svn/trunk/django_restapi/res
ource.py tries to set "request.method = 'POST'" in order to run PUTs
through request._load_post_and_files() as POSTs as
_load_post_and_files() does not currently seem to support PUT. This used
to work, however current django SVN seems to have broken it. This
breakage seems to be by design as the HttpRequest doc says "All
attributes except session should be considered read-only." I am not the
author of django-rest-interface but I am using it in production.

Can request._load_post_and_files() be updated to support PUT also in
order to fix this issue??

The current django-rest-interface approach was a bit of a hack that
turned out to pretty well so that we didn't need to change core at the
time. We should get around to adding PUT support to HttpRequest, though,
you're right.

I've created ticket #5682 for this. It's a really trivial change (you've
seen how simple it is in django-rest-interface), so shouldn't take too
long to fix.

I have been reading through ModPythonRequest, HttpRequest and
http://www.b-list.org/weblog/2006/jun/13/how-django-processes-request/ and
think I have almost got a handle on it. Do you think you will have a chance
to look at this soon or should I try to patch it myself?

I would encourage you to try it yourself.

It shouldn't be too hard.. let me point you at the right place. Have a
look in django/core/handlers/*.py for where we set up the GET and POST
properties (wsgi.py and modpython.py). It should be as simple as
creating an analogous thing for PUT and then altering the call to
_load_post_and_files so that it only populates POST or PUT when the
method is appropriate.

~~

How to PUT a file in Django
http://kunxi.org/archives/2009/01/how-to-put-a-file-in-django/

How Django processes a request (old)
http://www.b-list.org/weblog/2006/jun/13/how-django-processes-request/

Changes to request_response have broken django-rest-interface
http://www.mail-archive.com/django-developers@googlegroups.com/msg13404.html

#5 Updated by Dave Vieglais almost 13 years ago

  • Position deleted (225)
  • Position set to 36

#6 Updated by Dave Vieglais over 12 years ago

  • Position deleted (126)
  • Position set to 14

#7 Updated by Dave Vieglais over 12 years ago

  • Position set to 18
  • Position deleted (25)

#8 Updated by Roger Dahl over 12 years ago

  • Milestone set to None
  • Status changed from New to Closed

Also available in: Atom PDF

Add picture from clipboard (Maximum size: 14.8 MB)