http://django-rest-interface.googlecode.com/svn/trunk/django_restapi/resource.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??
--
Peter Nixon
http://peternixon.net/
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.
Regards,
Malcolm
If you create an account in Trac, it won't apply spam filtering to you.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
And how does one go about doing that? I don't see a signup link anywhere...
--
Tomas Kopecek
e-mail: permonik at mesias.brnonet.cz
ICQ: 114483784
Thanks. I have signed up now, but I still cannot for the life of me find a
link to that page from anywhere. Shouldn't it be a little more prominent?
Yeah, it should; I'll add a couple of links when I get a moment.
Jacob
Hi Malcolm
Aside from the BIGINT patch (which still hasn't been applied) I haven't done
much hacking on Django internals so it is not so trivial for me. :-)
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?
Cheers
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.
Regards,
Malcolm
Hi malcolm,
I use django-rest-interface too and I have this bug which need to be
quickly fixed so I submitted a patch which need review on #5682, let
me know if I need to do something else. I will add a patch for
modpython too when this one will be accepted.
Peter, you can test it too, it solves the bug with django-rest-interface.
Two questions:
* did I need to write tests for this new verb?
* did I have to do something in django.http.HttpRequest?
Regards,
David
I had a quick read of it. Looks like you're on the right track.
The main problem I see with it is that you're over-populating the data
structures a bit. If the request is a PUT, you're still populating
self.POST as a side-effect. We should neaten this up a bit.
When I started to think about this and how we would use it, it's not a
complete no-brainer and I'm beginning to think my original suggestion
(and what Andreas implemented in django-rest-interface) might not be the
easiest for end users (third-party programmers like yourselves). A
couple of possibilities spring to mind:
(1) We always populate self.POST and only self.POST. Since the
recommended way to check the method is to check request.method first, it
means the same code can potentially be used to handle PUT and POST data.
(2) We populate self.POST if request.method == 'POST' and self.PUT if
request.method == 'PUT' and leave the other one blank.
(3) We leave self.POST available for backwards compatibilty, but use a
more generic name like self.DATA for the data we extract. This is a
version of (1) with renaming involved.
Right at the moment, I'm probably slightly in favour of option (1)
because it's the smallest change and we can think of self.POST as "the
posted data" regardless of how the HTTP verb is spelt. Code will act
based on request.method, but there are more possibilities for factoring
out common pieces when working with the data.
So then the only change that is needed is to also populate that field
when the method is "PUT" (with accompanying changes in HttpRequest).
I'd be interested in hearing your thoughts, Peter and David, on this,
since you've already got experience using that piece of the framework.
Is there a lot of commonality between the way you're handling the PUT
and POST paths? I know it's a slight change to Andreas' code, but it's
not too intrusive from the looks of it. [Andreas: have I forgotten some
subtlety here?]
My mental example when I'm thinking about this is always how would
something like Atom Publishing work, but that doesn't make me lean one
way or the other here. So more examples might help.
> Peter, you can test it too, it solves the bug with django-rest-interface.
>
> Two questions:
> * did I need to write tests for this new verb?
Ideally, yes. It will probably require some changes to
django.test.client to allow the news type of request. Then some
additions to tests/modeltests/test_client would be appreciated.
> * did I have to do something in django.http.HttpRequest?
Yes. Search for wherever POST is referenced there and you'll need
something similar for PUT. __getitem__ and _set_encoding are the two
obvious places, although the latter one might be made moot if we put all
the data into request.POST regardless of the verb. In that case, though,
we'll need to make some of the errors and the __repr__ formats clearer,
since referring unambiguously to "POST" may be confusing.
I understand that you guys are eager to get something done here so you
can continue to track Django's trunk, so I'll try to respond quickly in
this thread. But right at the moment, the design is as good as I think
it can be, so let's take a moment to work on that. We're pretty close,
though.
Regards,
Malcolm
Thanks for your reactivity.
>
> The main problem I see with it is that you're over-populating the data
> structures a bit. If the request is a PUT, you're still populating
> self.POST as a side-effect. We should neaten this up a bit.
>
> When I started to think about this and how we would use it, it's not a
> complete no-brainer and I'm beginning to think my original suggestion
> (and what Andreas implemented in django-rest-interface) might not be the
> easiest for end users (third-party programmers like yourselves). A
> couple of possibilities spring to mind:
>
> (1) We always populate self.POST and only self.POST. Since the
> recommended way to check the method is to check request.method first, it
> means the same code can potentially be used to handle PUT and POST data.
>
> (2) We populate self.POST if request.method == 'POST' and self.PUT if
> request.method == 'PUT' and leave the other one blank.
>
> (3) We leave self.POST available for backwards compatibilty, but use a
> more generic name like self.DATA for the data we extract. This is a
> version of (1) with renaming involved.
>
> Right at the moment, I'm probably slightly in favour of option (1)
> because it's the smallest change and we can think of self.POST as "the
> posted data" regardless of how the HTTP verb is spelt. Code will act
> based on request.method, but there are more possibilities for factoring
> out common pieces when working with the data.
I'm not sure that "smallest change" should drive the decision, even if
I admit that a backward incompatible change could be a pain. The
option (3) seems more natural to me to make the difference between
what you post and the POST verb, it's more explicit. What about
self.PUT in this scenario?
>
> So then the only change that is needed is to also populate that field
> when the method is "PUT" (with accompanying changes in HttpRequest).
>
> I'd be interested in hearing your thoughts, Peter and David, on this,
> since you've already got experience using that piece of the framework.
> Is there a lot of commonality between the way you're handling the PUT
> and POST paths? I know it's a slight change to Andreas' code, but it's
> not too intrusive from the looks of it. [Andreas: have I forgotten some
> subtlety here?]
The current standard solution of restapi, which get data given the
receiver looks enough flexible to me. I never had to factorize PUT and
POST because restapi already handle this for me.
> > * did I need to write tests for this new verb?
>
> Ideally, yes. It will probably require some changes to
> django.test.client to allow the news type of request. Then some
> additions to tests/modeltests/test_client would be appreciated.
Yes, I need client.put() and client.delete() for my personal use so I
can provide a patch for this part. It'll require some documentation
too, not that trivial patch eventually :).
>
> > * did I have to do something in django.http.HttpRequest?
>
> Yes. Search for wherever POST is referenced there and you'll need
> something similar for PUT. __getitem__ and _set_encoding are the two
> obvious places, although the latter one might be made moot if we put all
> the data into request.POST regardless of the verb. In that case, though,
> we'll need to make some of the errors and the __repr__ formats clearer,
> since referring unambiguously to "POST" may be confusing.
I had attached a patch for http.HttpRequest, it probably evolves given
the final decision we'll take but let me know if it's what you
thought.
>
> I understand that you guys are eager to get something done here so you
> can continue to track Django's trunk, so I'll try to respond quickly in
> this thread. But right at the moment, the design is as good as I think
> it can be, so let's take a moment to work on that. We're pretty close,
> though.
I think too, given the success of the last one, what about some kind
of GSoC or REST sprint? At this point, it could be interesting to end
with something which can be merged to the trunk.
Regards,
David
>> On 10/4/07, Peter Nixon <list...@peternixon.net> wrote:
>>> I tried to open the following ticket but it thinks my IP is a
>>> spammer,
>>> so I am sending to the list:
>>
>> If you create an account in Trac, it won't apply spam filtering to
>> you.
>
> And how does one go about doing that? I don't see a signup link
> anywhere...
did you enter your name and email id in settings?
--
regards
kg
http://lawgon.livejournal.com
http://nrcfosshelpline.in/web/
It doesn't drive the decision, but it is absolutely a consideration.
> The
> option (3) seems more natural to me to make the difference between
> what you post and the POST verb, it's more explicit. What about
> self.PUT in this scenario?
That's called option (2). :-)
>
> >
> > So then the only change that is needed is to also populate that field
> > when the method is "PUT" (with accompanying changes in HttpRequest).
> >
> > I'd be interested in hearing your thoughts, Peter and David, on this,
> > since you've already got experience using that piece of the framework.
> > Is there a lot of commonality between the way you're handling the PUT
> > and POST paths? I know it's a slight change to Andreas' code, but it's
> > not too intrusive from the looks of it. [Andreas: have I forgotten some
> > subtlety here?]
>
> The current standard solution of restapi, which get data given the
> receiver looks enough flexible to me. I never had to factorize PUT and
> POST because restapi already handle this for me.
There are a lot of cases that Andreas' work doesn't cover, since REST is
a very broadly applicable theory. That was one of the challenges of the
project: working out what areas needed help and where we would just be
adding constraints or creating equivalent amounts of work. As soon as
you start to move to situations where your publically exposed resources
don't map more or less one-to-one onto models, things become a lot
trickier and we haven't quite solved that -- partly because I suspect
it's not really solvable.
My point here is not in any way to diminish the work Andreas has done or
the use you are getting from it. In certain scenarios, it is obviously a
great help and he's done some excellent design and implementation. I was
very happy with the work Andreas did. However, some perspective is
necesary. My point *is* to say that there are uses for PUT and POST
beyond django-rest-api and there are plenty of situations where I would
directly implement the handling, rather than using the django-rest-api
classes. So we are looking for a consistent Django solution here, rather
than just something that works smoothly with django-rest-api.
It's that former case where I'm thinking there might be a reasonable
overlap in the code between PUT and POST handling. I'm still not sure
about this -- it's going to take a little more mulling over.
[...]
> I think too, given the success of the last one, what about some kind
> of GSoC or REST sprint? At this point, it could be interesting to end
> with something which can be merged to the trunk.
I'm not against sprints, but we're talking about a very small change
here.
The reason we asked GSoC students to develop their apps as third-party
applications this year was to precisely avoid any rush to inclusion.
Django-rest-api is a perfect example: with the exception of needing PUT
support in HttpRequest, there's no changes required to core, so there's
no real need to include it in core. Maybe, one day, it might be a
candidate for django/contrib/, but it's not at that point yet and for
the time being, hosting at Google is great because it gives Andreas --
and anybody else who wants to contribute -- an issue tracker, subversion
hosting and the whole enchilada without any fuss. So let's stay focused
on adding PUT support to HttpRequest in this thread.
Regards,
Malcolm
I just know somebody's going to say "yes it is", so I'll clarify: all
REST problems are relatively simple to implement. But trying to force
all cases into a framework such as django-rest-api is the part that I
think isn't neatly solvable. The nice solutions to one problem might
look quite different to the nice architecture of another problem and the
common intersection -- which is the bit a framework tries to capture --
isn't always very large. Django-rest-api nicely encapsulates the common
intersection for a particular group of problems and does that quite
well, but that group isn't the whole problem space. That was all I was
ineptly trying to say there.
Regards,
Malcolm
Weren't custom descendants of the Resource class designed for this? I
even thought they would be the more common application
django-rest-interface since you can automatically map models to
resources only in simple cases.
Yes, that's the idea and it mostly works pretty well. I agree that
that's the more general case, too -- model mapping is a special case of
that. The main difficulty is automatically creating the correct URLS,
particularly reverse URL mapping.
The Resource class is quite as independent from everything as we would
have liked. I say "we" here because towards the end of the SoC period,
Andreas and I spent quite a long time trying to loosen a few of the
couplings between output classes and the representation classes --
Collection and Responder, in particular -- and we both felt it wasn't as
neat as it could be, but we couldn't see how to improve it. That's
probably still work in progress.
My own mental measuring stick during the whole project was to imagine a
case where I was implementing Atom Publishing and using many models to
represent what became a single article resource in the public interface
(I have images, text, metadata, possibly a model with links in it for
validation in the future, etc). You can fit this into Resource
subclasses, but the amount of work you end up doing never really
convinced me that the framework was helping me here. It felt like the
same amount of work as if I did it from scratch, so where was the clear
win in using the framework for this case and did it even feel wrong not
to use it? Again, this isn't a mark against Andreas work, but was more a
case of me trying to test the boundaries.
I should talk to Andreas about posting some of the discussions we had
and where we left of on the wiki and creating a project mailing list so
that other people can get in on the fun here.
Cheers,
Malcolm
+ self.DATA?
> There are a lot of cases that Andreas' work doesn't cover, since REST is
> a very broadly applicable theory. That was one of the challenges of the
> project: working out what areas needed help and where we would just be
> adding constraints or creating equivalent amounts of work. As soon as
> you start to move to situations where your publically exposed resources
> don't map more or less one-to-one onto models, things become a lot
> trickier and we haven't quite solved that -- partly because I suspect
> it's not really solvable.
>
> My point here is not in any way to diminish the work Andreas has done or
> the use you are getting from it. In certain scenarios, it is obviously a
> great help and he's done some excellent design and implementation. I was
> very happy with the work Andreas did. However, some perspective is
> necesary. My point *is* to say that there are uses for PUT and POST
> beyond django-rest-api and there are plenty of situations where I would
> directly implement the handling, rather than using the django-rest-api
> classes. So we are looking for a consistent Django solution here, rather
> than just something that works smoothly with django-rest-api.
>
> It's that former case where I'm thinking there might be a reasonable
> overlap in the code between PUT and POST handling. I'm still not sure
> about this -- it's going to take a little more mulling over.
Ok, I do agree and I understand. I will answer on the second thread
about resources which not fit a one-to-one model.
> > I think too, given the success of the last one, what about some kind
> > of GSoC or REST sprint? At this point, it could be interesting to end
> > with something which can be merged to the trunk.
>
> I'm not against sprints, but we're talking about a very small change
> here.
>
> The reason we asked GSoC students to develop their apps as third-party
> applications this year was to precisely avoid any rush to inclusion.
> Django-rest-api is a perfect example: with the exception of needing PUT
> support in HttpRequest, there's no changes required to core, so there's
> no real need to include it in core. Maybe, one day, it might be a
> candidate for django/contrib/, but it's not at that point yet and for
> the time being, hosting at Google is great because it gives Andreas --
> and anybody else who wants to contribute -- an issue tracker, subversion
> hosting and the whole enchilada without any fuss. So let's stay focused
> on adding PUT support to HttpRequest in this thread.
Ok, that's just that in the initial proposition, the last point is
"Prepare the code to be merged to trunk" so I thought that it was one
of the goals but I agree that it could be kept as a third party app
for the moment.
Regards,
David
Hi David
Thanks for doing this. I have written a patch for mod_python and added it to
the ticket. I have tested it and deployed it with a patched rest api in
production ;-)
Cheers
BTW, no more thought about the way of handling PUT? I've just added a
patch against test.client which add .put() and .delete(), I'm waiting
for (a) reaction(s) to add tests and documentation.
Cheers,
David
Sorry for insisting on that point but this is important to me, once
the decision is taken I can produce patches but I need your feedback
here to continue :).
Cheers,
David
<rant>Well, since I'm working on Django on a totally volunteer basis and
already have a fairly large prioritised list of things to do -- many of
which, quite honestly, have a larger impact on the broader Django
userbase than this one -- as well as day jobs that need attention in
order to pay the bills, it would be impolite of me not to entirely
reshuffle things to meet your needs then. :-(</rant>
Now that I've got that out of the way...
My personal preference is to use request.DATA and keep request.POST
around as a backwards compatibility feature for a release or two. That
way PUT, POST -- and if somebody wants to use it later, OPTIONS, etc --
can all use the same attribute, since you can only be doing one at a
time. That saves having to add a new attribute for every potential HTTP
verb (note that the set isn't restricted to just PUT, POST, GET and
DELETE) and helps write common code for processing the data --
request.method tells you the verb, request.DATA gives you the entity
body.
My second favourite preference is to add request.PUT, as
django-rest-interface does at the moment.
However, neither decision is binding until at least one other core
maintainer steps in with some agreement or sufficient time passes that
I'm convinced they really don't care which way we go.
Regards,
Malcolm
Here's my 2ยข: use ``request.DATA``, and keep ``request.POST`` around
forever. I quite like the way ``request.GET`` and ``request.POST``
echo PHP's superglobals: they're one of the (few) things PHP gets
right.
I also like the semantics of GET/POST being parsed for form encoding,
and DATA always having the raw, unparsed content. Seems nice to me.
I don't, though, feel very strongly either way, so I'll defer to
Malcolm's judgement here.
Jacob
<rant class="mitsuhiko">
I perfectly understand because I'm in the same situation. But
sometimes, when someone motivated ask me politely and when this item
just take me a couple of minutes, I decide to put this one in top of
my todolist because I know that my decision will have consequences and
maybe this guy is insisting because he's got time right now.
</rant>
> My personal preference is to use request.DATA and keep request.POST
> around as a backwards compatibility feature for a release or two. That
> way PUT, POST -- and if somebody wants to use it later, OPTIONS, etc --
> can all use the same attribute, since you can only be doing one at a
> time. That saves having to add a new attribute for every potential HTTP
> verb (note that the set isn't restricted to just PUT, POST, GET and
> DELETE) and helps write common code for processing the data --
> request.method tells you the verb, request.DATA gives you the entity
> body.
>
> My second favourite preference is to add request.PUT, as
> django-rest-interface does at the moment.
>
> However, neither decision is binding until at least one other core
> maintainer steps in with some agreement or sufficient time passes that
> I'm convinced they really don't care which way we go.
Thanks for your answer, I agree with you that request.DATA could be
interesting. I will update my patches with this proposition given the
fact that Jacob agree with you.
David
Um ... you're using request.method to differentiate that stuff already,
right?
Malcolm
The request.method attribute exists precisely for this purpose, so
that you can find out what the HTTP request method was ;)
This isn't completely sufficient because it's possible to submit a form
via POST with no data (e.g. a form with checkboxes and maybe some fields
that aren't filled in). That's why we introduced request.method.
Malcolm
What about sending a POST to a GET-encoded URI? You get both GET and
POST then with possibly overlapping values.
--
Patryk Zawadzki
PLD Linux Distribution