Re: An idea for improving @validate
On 29 Jan 2008, at 11:06, Dmitry Lipovoi wrote: also in routes it's possible to config one url to diffetent actions on GET and POST requests. something like this: m.connect('myform', controller='form', action='handle_form', conditions=dict(method=['POST'])) m.connect('myform', controller='form', action='show_form')) Sure, it's possible, but what's really bugging me is that this has to be worked around in the first place ;) In my opinion, it should be *default* do the right thing, which is to have one exposed url for a form. Or at least, the documentation should be altered or extended so that the one-url way of doing things is prominent. Basically, what I'm saying is I think @validate is broken and should be fixed, irrespective of any work-arounds that exist. Cheers, Steven --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
also in routes it's possible to config one url to diffetent actions on GET and POST requests. something like this: m.connect('myform', controller='form', action='handle_form', conditions=dict(method=['POST'])) m.connect('myform', controller='form', action='show_form')) On Jan 29, 3:44 pm, Steven Holmes [EMAIL PROTECTED] wrote: On 29 Jan 2008, at 08:36, Alberto Valverde wrote: Steven Holmes wrote: Hi, @validate supports separating form rendering and form post processing into distinct methods. This is convenient, but has a nasty flaw: It requires two separate URLs, a form display URL and a URL to handle the post. When a form post fails to validate, the form is re-displayed, but at the post URL instead of the original form display URL. I find this inconsistent and broken. Here is a little example: class AccountController(BaseController): def create_form(self): return render('create_account') @validate(schema=CreateAccountSchema(), form='create_form') def create(self): return 'Account Created!' To view the form we go to /account/create_form, then when we submit we are taken to /account/create, where the form is re-displayed if there were errors. Two different URLs for the same form. This is unnecessarily exposing a (confusing) implementation detail to the user. Changing @validate so that it will always internally redirect to create_form if there is no form post would make things more consistent. The form could then be viewed at /account/create and also re-displayed with errors are /account/create, while the nice separation between form display and form processing is maintained. I don't know what effect this change would have on backwards compatibility, but it can be made with a trivial (two lines or so) change to @validate. (I can do a quick patch if anybody's interested). With a little help of pylons.controllers.dispatch_on you can achieve what you want: @dispatch_on(POST=do_create) def create(self): render(my form) @validate(schema=something, form=create) def do_create(self): process(self.form_seult) the form shown at create() can submit to itself so the external API only sees the /create url while you avoid branching inside the method to do two different jobs which is cleaner, IMHO. Alberto Thanks, I didn't know about dispatch_on. However, this isn't so much of a case of what I want as what I think should happen by default. The pylons form tutorial teaches the two-URL way and I think that having two different URLs for displaying the same form is fundamentally broken (and unnecessary). Are there any advantages to doing it this way that I've missed? (My preferred method would actually involve saving the Invalid exception somewhere and redirecting the user to referrer, but that's a more fundamental change). Cheers, Steven --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 3:28 AM, Steven Holmes [EMAIL PROTECTED] wrote: In my opinion, it should be *default* do the right thing, which is to have one exposed url for a form. Or at least, the documentation should be altered or extended so that the one-url way of doing things is prominent. Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On 29 Jan 2008, at 16:21, Mike Orr wrote: On Jan 29, 2008 3:28 AM, Steven Holmes [EMAIL PROTECTED] wrote: In my opinion, it should be *default* do the right thing, which is to have one exposed url for a form. Or at least, the documentation should be altered or extended so that the one-url way of doing things is prominent. Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. -- Mike Orr [EMAIL PROTECTED] I will use all my powers of persuasion ;) Besides, I'M RIGHT :P --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 11:21 AM, Mike Orr [EMAIL PROTECTED] wrote: Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. I don't have this particular religion, but what would a REST zealot say? Seems like two different URI's for the same thing is bad. I've hacked up my base controller class to make it work the way that Steven wants. I suppose to me, clean URIs are better than clean controllers. And in my case, the mess isn't in my controllers, it's in my base controller class. Plus, I'm not sure that decorators make things cleaner; it just puts some mysterious magic in my code. @validate is pretty easy to understand magic, but it's still one little line that completely changes the expected dispatch behavior of pylons (one url = one request = one route = one action = one method = one response). I don't like 'em. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
Matt Feifarek wrote: Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. I don't have this particular religion, but what would a REST zealot say? Seems like two different URI's for the same thing is bad. REST zealots say that you should have: GET /resource - rendered thing GET /resource/edit - form POST /resource - make the change So there is generally another URL involved. But REST zealots don't deal with HTML forms. Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On 29 Jan 2008, at 16:53, Matt Feifarek wrote: On Jan 29, 2008 11:21 AM, Mike Orr [EMAIL PROTECTED] wrote: Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. I don't have this particular religion, but what would a REST zealot say? Seems like two different URI's for the same thing is bad. I've hacked up my base controller class to make it work the way that Steven wants. I suppose to me, clean URIs are better than clean controllers. And in my case, the mess isn't in my controllers, it's in my base controller class. Plus, I'm not sure that decorators make things cleaner; it just puts some mysterious magic in my code. @validate is pretty easy to understand magic, but it's still one little line that completely changes the expected dispatch behavior of pylons (one url = one request = one route = one action = one method = one response). I don't like 'em. I'm not a fan of @validate either, as a general rule. I like being able to select schemas at request time (for things like a CRUDController it lets me have subclasses with things like create_schema = foo). However, I can see that @validate would be very useful for a significant number of common cases. The ideal way to handle forms, in my opinion, is to always redirect after a POST. If there are errors, save the Invalid exception and redirect to the referrer. This allows form actions to be targeted by multiple forms in different places. (The usual example I give of this is adding products to a shopping cart--I want to be able to have the add form both on the product summary and on the full product page. Redirecting to referer automatically does the right thing). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 11:15 AM, Ian Bicking [EMAIL PROTECTED] wrote: I think using POST is okay; if you are using _action=PUT it isn't a PUT anyway, and it feels like it's not much more than HTTP verb push-ups. POST over a resource updates the resource in some fashion; updating a resource in-place via POST is okay (PUT might be better, but not-really-a-PUT *isn't* better). I generally agree with you, and I keep going back and forth whether to use map.resource in my own applications. Because what does it really matter if you use POST or PUT? Users can't effectively predict URLs across applications anyway, and there's no practical reason to; e.g., no Google GWebsite that's a common front end for interacting with a variety of sites. /resource/ vs /resource/1 is a good idea, but I'm not sure the rest of it matters. Are there any other practical arguments for a REST-like add/edit/delete, or is it all just academic ideology? But still, something needs to be done for Pylons, and map.resource exists, so I guess a fair number of people are using it. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
Mike Orr wrote: On Jan 29, 2008 9:40 AM, Ian Bicking [EMAIL PROTECTED] wrote: Matt Feifarek wrote: Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. I don't have this particular religion, but what would a REST zealot say? Seems like two different URI's for the same thing is bad. REST zealots say that you should have: GET /resource - rendered thing GET /resource/edit - form POST /resource - make the change So there is generally another URL involved. But REST zealots don't deal with HTML forms. This gets into how Pylons should support REST, and what this implies for the changes I'm making in Routes 2. Ben and I discussed map.resource a week ago, and he said it follows the Atom Publishing Protocol, a widely-respected REST spec. I haven't studied it yet but here are some links on it. http://tools.ietf.org/html/rfc5023 http://www.ibm.com/developerworks/library/x-atompp1/ As a recap, map.resource believes that: GET/messages = display index page POST /messages = create new message GET/messages/new= display add form (action = POST /messages) GET/messages/1 = display message 1 GET/messages/1/edit = display edit form (action = PUT /messages/1) PUT/messages/1 = modify message 1 DELETE /messages/ 1= delete message 1 (Routes 1 has ;edit instead of /edit, but Ben said that's an invalid URL syntax borrowed from Rails, which Rails has since corrected.) PUT and DELETE are implemented by an _action query param to a POST form, which Routes notices and changes the request method. Again, Ben says this is widely done in other programming languages. It's kind of wonky, though, because web applications don't expose resources. When you get /messages you get an HTML page. You don't get a well-formed container of resources like in atompub. When you get /messages/1 you get HTML again. When you edit you send application/x-form-www-urlencoded (or whatever it is). That's not the same content type as what you were given (HTML). It's not even that close to the same content type. (Though the intention of a FormEncode Schema is actually to take a resource and turn it into something isomorphic to an HTML form, and then convert it back again... but expressing form submissions as a transformation of data is tricky.) As long as you are doing this, you might want to consider some kind of validation submission as well, that can be used by Javascript to submit and get errors. Also a preview submission. I think using POST is okay; if you are using _action=PUT it isn't a PUT anyway, and it feels like it's not much more than HTTP verb push-ups. POST over a resource updates the resource in some fashion; updating a resource in-place via POST is okay (PUT might be better, but not-really-a-PUT *isn't* better). Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 1:05 PM, Ian Bicking wrote: I didn't realize it was in the body, not a query string. In that case it's just absurd. You can't add stuff to the body of a PUT. The body *is* the PUT. You could add it to a header. But you can only do that in an XHR request. Huh? I'm saying, that the way the form_tag handler in WebHelpers works, is if you do: h.form_tag('/some/url/to/send', method='put') It makes a form tag with the normal POST method, but adds in a hidden field called _method='PUT', that when Routes sees it in the Routes Middleware, modifies the REQUEST_METHOD so that it appears as if it was a PUT, and everything you had that assumed it would be a PUT works just fine even though browers can't PUT. If you're doing a real PUT, there's no need to add _method='PUT'... its already a PUT. What are you talking about? Cheers, Ben smime.p7s Description: S/MIME cryptographic signature
Re: An idea for improving @validate
On Jan 29, 2008 3:58 PM, Ben Bangert [EMAIL PROTECTED] wrote: On Jan 29, 2008, at 11:35 AM, Matt Feifarek wrote: /accounts -- list current accounts /account/8733 == /account/8733/view /account/8733/edit /account/new -- empty form /account/8733/view/attachments/2 (etc.) That's pretty much exactly how Rotues map.resource sets things up as well. I didn't know that there was such a thing. The default routing.py doesn't mention it, so I guess I never found it. make_map() stock certainly doesn't work that way. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 11:15 AM, Ian Bicking wrote: It's kind of wonky, though, because web applications don't expose resources. When you get /messages you get an HTML page. You don't get a well-formed container of resources like in atompub. When you get /messages/1 you get HTML again. When you edit you send application/x-form-www-urlencoded (or whatever it is). That's not the same content type as what you were given (HTML). It's not even that close to the same content type. (Though the intention of a FormEncode Schema is actually to take a resource and turn it into something isomorphic to an HTML form, and then convert it back again... but expressing form submissions as a transformation of data is tricky.) This is where content type switching comes in, which should be in Pylons 0.9.7. If you want the resource represented as HTML, you either specify it in the HTTP headers with the Accept header, or you explicity ask by extension: GET /messages/1.html Or if you want an XML representation of that object, and the site provides it: GET /messages/1.xml OR, you ask for GET /messages/1 with the HTTP Accept header set *only* to application/xml. When you send the POST, you specify the content-type desired in the response with the Accept header, again, this requires some more elegant content type switching, which is going into Pylons 0.9.7. This means that in your view action on a controller, you might have something like: if mimetype('html'): return render('some/html/template') elif mimetype('xml'): # prepare subset of data for XML viewing return render('genshi', 'some/xml/template') etc. Since browsers generally flaunt rather obscene HTTP Accept parameters, you attempt to return HTML first if the browser can handle it, and only after that you fall-back to the other format desired. The mimetype function above will also first return content as html if its explicit in the URL (/messages/1.html), this way clients that can't customize HTTP Accept headers can also still properly ask for the format desired (maybe some JS library doing a GET on /messages/1.json). As long as you are doing this, you might want to consider some kind of validation submission as well, that can be used by Javascript to submit and get errors. Also a preview submission. I think using POST is okay; if you are using _action=PUT it isn't a PUT anyway, and it feels like it's not much more than HTTP verb push-ups. POST over a resource updates the resource in some fashion; updating a resource in-place via POST is okay (PUT might be better, but not-really-a-PUT *isn't* better). It's really just to have a consistent API for parts of a webapp that you'd like to either be all REST on, or easily expose as a web service. Cheers, Ben smime.p7s Description: S/MIME cryptographic signature
Re: An idea for improving @validate
Ben Bangert wrote: On Jan 29, 2008, at 11:45 AM, Ian Bicking wrote: POST or PUT over a resource automatically invalidates all caches (at Ok... so POST and PUT invalidate the cache... POST /resource/1?_action=PUT doesn't invalidate any caches, and so it's not just rather useless, it's actually counterproductive. Err, wait, didn't you just say that POST invalidates the cache? I should note that the _method=PUT is in the body, not the URL, as its a POST. I didn't realize it was in the body, not a query string. In that case it's just absurd. You can't add stuff to the body of a PUT. The body *is* the PUT. You could add it to a header. But you can only do that in an XHR request. Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 11:35 AM, Matt Feifarek wrote: /accounts -- list current accounts /account/8733 == /account/8733/view /account/8733/edit /account/new -- empty form /account/8733/view/attachments/2 (etc.) That's pretty much exactly how Rotues map.resource sets things up as well. Cheers, Ben smime.p7s Description: S/MIME cryptographic signature
Re: An idea for improving @validate
Ben Bangert wrote: On Jan 29, 2008, at 1:05 PM, Ian Bicking wrote: I didn't realize it was in the body, not a query string. In that case it's just absurd. You can't add stuff to the body of a PUT. The body *is* the PUT. You could add it to a header. But you can only do that in an XHR request. Huh? I'm saying, that the way the form_tag handler in WebHelpers works, is if you do: h.form_tag('/some/url/to/send', method='put') It makes a form tag with the normal POST method, but adds in a hidden field called _method='PUT', that when Routes sees it in the Routes Middleware, modifies the REQUEST_METHOD so that it appears as if it was a PUT, and everything you had that assumed it would be a PUT works just fine even though browers can't PUT. If you're doing a real PUT, there's no need to add _method='PUT'... its already a PUT. What are you talking about? I still don't get what you are doing. I'm talking about HTTP. Here's what a sensible RESTful interaction looks like: GET /some/resource - response: 200 OK Content-Type: application/xml xmlsome doc/xml Given that, to update with PUT you do: PUT /some/resource Content-Type: application/xml xmlupdated version of doc/xml What kinds of HTTP requests are you talking about? Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 11:45 AM, Ian Bicking wrote: POST or PUT over a resource automatically invalidates all caches (at Ok... so POST and PUT invalidate the cache... POST /resource/1?_action=PUT doesn't invalidate any caches, and so it's not just rather useless, it's actually counterproductive. Err, wait, didn't you just say that POST invalidates the cache? I should note that the _method=PUT is in the body, not the URL, as its a POST. Cheers, Ben smime.p7s Description: S/MIME cryptographic signature
Re: An idea for improving @validate
Mike Orr wrote: I googled around to see how other people are combining Atom and HTML. It looks like Atom is an advantage only if you want to syndicate the resource. And even with that, if you only want to syndicate it read-only but require all changes to be done at the original website, it looks like only the index and show URLs need to be conformat (/article/ and /article/1), and the modify URLs can be anything. And the index URL would have to provide a bona fide XML atom feed, not an HTML page with hyperlinks. Remembering atompub again, it's really pretty loose on URLs. There is a service document which is kind of the frontend. That points to a collection, which is what everyone thinks of. The collection and service document point to each other, they don't have to have any particular URL layout. The collection should produce the entries as a feed. That feed can be paged (and probably should be) so while the collection has a head, to get the complete collection there's multiple URLs, and those URLs are again pointers. Each entry has a pointer to its URL, which can again be anywhere. The collection's main URL must accept POST. The entry URLs must accept DELETE and PUT. You can lay out those URLs however you want. It could be: /atom.xml - head /atom-pg2.xml - for paging /entries/2008/01/29/asdlkfjkj.xml - for the entry /entries?id=3493 - another entry option Really atompub doesn't care at all, and though the examples tend to suggest a certain logical structure, it just a very loose suggestion. You can cross domains or use query strings or whatever. Clients can suggest URL slugs, but it's just a suggestion, and there's no indication about where in the URL the slug may appear. So, I think this means map.resource is good at what it does -- Atom serialization -- but it's not a complete answer for how to organize a set of index/show/add/modify/delete operations in a website. I've thought about keeping map.resource as-is and adding another more flexible method for HTML resources that want to be standardized and somewhat REST-like but not necessarily completely REST, and using GET for forms and POST for execution. I haven't yet gotten into the design, though one-method foo/add, foo/1/edit and foo/1/delete are a possibility, optionally expandable to the two-method style (ask_delete, confirm_delete, something like that). Are there any good standards or precendants to guide this? Note there's a possible namespace collision between /collection/add and /collection/item-id... what if the item-id is add? I'd be more inclined to use a query string, like /collection?form=add. Maybe form is a better indication than the common action, as the point is that these forms (in proper REST style) aren't actually doing anything. Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 9:40 AM, Ian Bicking [EMAIL PROTECTED] wrote: Matt Feifarek wrote: Yes, we're disagreeing on what the default should be. Well, you'll have to convince Ben. I think he likes it the other way. I don't have this particular religion, but what would a REST zealot say? Seems like two different URI's for the same thing is bad. REST zealots say that you should have: GET /resource - rendered thing GET /resource/edit - form POST /resource - make the change So there is generally another URL involved. But REST zealots don't deal with HTML forms. This gets into how Pylons should support REST, and what this implies for the changes I'm making in Routes 2. Ben and I discussed map.resource a week ago, and he said it follows the Atom Publishing Protocol, a widely-respected REST spec. I haven't studied it yet but here are some links on it. http://tools.ietf.org/html/rfc5023 http://www.ibm.com/developerworks/library/x-atompp1/ As a recap, map.resource believes that: GET/messages = display index page POST /messages = create new message GET/messages/new= display add form (action = POST /messages) GET/messages/1 = display message 1 GET/messages/1/edit = display edit form (action = PUT /messages/1) PUT/messages/1 = modify message 1 DELETE /messages/ 1= delete message 1 (Routes 1 has ;edit instead of /edit, but Ben said that's an invalid URL syntax borrowed from Rails, which Rails has since corrected.) PUT and DELETE are implemented by an _action query param to a POST form, which Routes notices and changes the request method. Again, Ben says this is widely done in other programming languages. Atom specifies the URLs, not the controller methods. So we could rename the actions or merge the form-submission ones. But I'm wary of making such a big change for such a small benefit. One problem I've come across is the lack of a delete confirmation form. Ben says you can do it in Javascript before the DELETE executed, but I need something that degrades if users don't have Javascript. It looks like GET /messages/1/delete would nicely fit into that scheme. @validate is another issue. It's a nice convenience but it does limit what you can do in your code. Going to a one-method scheme would require it to be bypassed or rewritten in the application. I've also found another problem in that the forms I'm porting to Pylons have a Cancel button, which is supposed to bypass the validators and do a redirect. I'd either have to have a big OR validator around all the others, or wrap or rewrite @validate to process cancel before executing the validators. So, I think the Pylons docs need to mention @rewrite's limitions and show how to work around them (calling the validators manually in the action), and perhaps also show the one-method technique. However, I'm not sure the one-method technique will be supported by map.resource, though you can use arguments to get something approaching that. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 2:26 PM, Mike Orr [EMAIL PROTECTED] wrote: Are there any other practical arguments for a REST-like add/edit/delete, or is it all just academic ideology? IANARZ (I am not a REST Zealot) but... I noticed when I moved to Pylons (from Webware, fwiw) that one of the first things I did before writing any code was work out the URI-space. Then went to routes. I somehow stumbled through my own preferences on the same pattern that Ian mentions: /accounts -- list current accounts /account/8733 == /account/8733/view /account/8733/edit /account/new -- empty form /account/8733/view/attachments/2 (etc.) This is different from stock Pylons, which recommends: /account/view/8733 To me, viewing is a property of 8733, not vice versa. So, I switched 'em. That was easy in routes. It felt to me like this step made me write a better application; things landed in better places. I don't expect to ever have any kind of robot use these applications, and I bet never once will a user look at the location bar and think gee, those are nice urls but it helped me write better software, I think. That's worth something. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
Mike Orr wrote: On Jan 29, 2008 11:15 AM, Ian Bicking [EMAIL PROTECTED] wrote: I think using POST is okay; if you are using _action=PUT it isn't a PUT anyway, and it feels like it's not much more than HTTP verb push-ups. POST over a resource updates the resource in some fashion; updating a resource in-place via POST is okay (PUT might be better, but not-really-a-PUT *isn't* better). I generally agree with you, and I keep going back and forth whether to use map.resource in my own applications. Because what does it really matter if you use POST or PUT? Users can't effectively predict URLs across applications anyway, and there's no practical reason to; e.g., no Google GWebsite that's a common front end for interacting with a variety of sites. /resource/ vs /resource/1 is a good idea, but I'm not sure the rest of it matters. Are there any other practical arguments for a REST-like add/edit/delete, or is it all just academic ideology? POST or PUT over a resource automatically invalidates all caches (at least all that see the request), so that is of some benefit. I like PUT insofar as it is clearly symmetric with GET. If there is not a strong symmetry then I don't see any purpose to it. POST /resource/1?_action=PUT doesn't invalidate any caches, and so it's not just rather useless, it's actually counterproductive. Technically you could use Accept headers to handle a resource with multiple representations. But the Accept header totally blows; browsers lie about it (they claim they'd prefer XML over HTML?!?) and it totally messes up caching and the fixes are hard to handle. But still, something needs to be done for Pylons, and map.resource exists, so I guess a fair number of people are using it. Well, for services I think the atompub layout is nice. For rendered HTML and HTML forms it doesn't work that well IMHO. Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 11:45 AM, Ian Bicking [EMAIL PROTECTED] wrote: Mike Orr wrote: On Jan 29, 2008 11:15 AM, Ian Bicking [EMAIL PROTECTED] wrote: I think using POST is okay; if you are using _action=PUT it isn't a PUT anyway, and it feels like it's not much more than HTTP verb push-ups. POST over a resource updates the resource in some fashion; updating a resource in-place via POST is okay (PUT might be better, but not-really-a-PUT *isn't* better). I generally agree with you, and I keep going back and forth whether to use map.resource in my own applications. Because what does it really matter if you use POST or PUT? Users can't effectively predict URLs across applications anyway, and there's no practical reason to; e.g., no Google GWebsite that's a common front end for interacting with a variety of sites. /resource/ vs /resource/1 is a good idea, but I'm not sure the rest of it matters. Are there any other practical arguments for a REST-like add/edit/delete, or is it all just academic ideology? POST or PUT over a resource automatically invalidates all caches (at least all that see the request), so that is of some benefit. I like PUT insofar as it is clearly symmetric with GET. If there is not a strong symmetry then I don't see any purpose to it. POST /resource/1?_action=PUT doesn't invalidate any caches, and so it's not just rather useless, it's actually counterproductive. Technically you could use Accept headers to handle a resource with multiple representations. But the Accept header totally blows; browsers lie about it (they claim they'd prefer XML over HTML?!?) and it totally messes up caching and the fixes are hard to handle. But still, something needs to be done for Pylons, and map.resource exists, so I guess a fair number of people are using it. Well, for services I think the atompub layout is nice. For rendered HTML and HTML forms it doesn't work that well IMHO. I googled around to see how other people are combining Atom and HTML. It looks like Atom is an advantage only if you want to syndicate the resource. And even with that, if you only want to syndicate it read-only but require all changes to be done at the original website, it looks like only the index and show URLs need to be conformat (/article/ and /article/1), and the modify URLs can be anything. And the index URL would have to provide a bona fide XML atom feed, not an HTML page with hyperlinks. So, I think this means map.resource is good at what it does -- Atom serialization -- but it's not a complete answer for how to organize a set of index/show/add/modify/delete operations in a website. I've thought about keeping map.resource as-is and adding another more flexible method for HTML resources that want to be standardized and somewhat REST-like but not necessarily completely REST, and using GET for forms and POST for execution. I haven't yet gotten into the design, though one-method foo/add, foo/1/edit and foo/1/delete are a possibility, optionally expandable to the two-method style (ask_delete, confirm_delete, something like that). Are there any good standards or precendants to guide this? -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 1:26 PM, Ian Bicking wrote: I still don't get what you are doing. I'm talking about HTTP. Here's what a sensible RESTful interaction looks like: Browsers can't do sensible RESTful interactions, as they have no PUT or DELETE. What I'm referring to is how that's 'faked' for browsers by including a _method='PUT' or _method='DELETE' in a POST body (for use *only* with browsers). GET /some/resource - response: 200 OK Content-Type: application/xml xmlsome doc/xml Given that, to update with PUT you do: PUT /some/resource Content-Type: application/xml xmlupdated version of doc/xml What kinds of HTTP requests are you talking about? Yup, and the map.resource, with the mimetype stuff in Pylons 0.9.7 will do exactly what you illustrate there. Again, the talk of the _method stuff included in the POST is purely to deal with web browsers since they can't PUT/DELETE. Clients using a XML RESTful API to the resource will not include such stuff of course, and merely do the PUT/ DELETE exactly as you indicated. This is how map.resource works, and is intended to work with both browsers, and service consumers. - Ben smime.p7s Description: S/MIME cryptographic signature
Re: An idea for improving @validate
On Jan 29, 2008, at 11:45 AM, Ian Bicking wrote: POST or PUT over a resource automatically invalidates all caches (at least all that see the request), so that is of some benefit. I like PUT insofar as it is clearly symmetric with GET. If there is not a strong symmetry then I don't see any purpose to it. POST /resource/1?_action=PUT doesn't invalidate any caches, and so it's not just rather useless, it's actually counterproductive. That POST would invalidate caches for /resource/1, I thought you just pointed that out in the last paragraph? =] -- Philip Jenvey --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 10:51 AM, Mike Orr wrote: One problem I've come across is the lack of a delete confirmation form. Ben says you can do it in Javascript before the DELETE executed, but I need something that degrades if users don't have Javascript. It looks like GET /messages/1/delete would nicely fit into that scheme. GETs should not have any side effects. So modifying/deleting a resource should be done via a POST. -- Philip Jenvey --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 1:11 PM, Philip Jenvey [EMAIL PROTECTED] wrote: On Jan 29, 2008, at 10:51 AM, Mike Orr wrote: One problem I've come across is the lack of a delete confirmation form. Ben says you can do it in Javascript before the DELETE executed, but I need something that degrades if users don't have Javascript. It looks like GET /messages/1/delete would nicely fit into that scheme. GETs should not have any side effects. So modifying/deleting a resource should be done via a POST. What I meant was, GET /messages/1/delete displays the confirmation form (Do you really want to delete 'My Favorite Pony'?). Then either DELETE /messages/1 or POST /messages/1/delete could be implemented to delete it. The latter is what I've used in the past. Though I like Ian's idea of using a query param to choose a form... maybe. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On 29 Jan 2008, at 18:51, Mike Orr wrote: @validate is another issue. It's a nice convenience but it does limit what you can do in your code. Going to a one-method scheme would require it to be bypassed or rewritten in the application. I've also found another problem in that the forms I'm porting to Pylons have a Cancel button, which is supposed to bypass the validators and do a redirect. I'd either have to have a big OR validator around all the others, or wrap or rewrite @validate to process cancel before executing the validators. So, I think the Pylons docs need to mention @rewrite's limitions and show how to work around them (calling the validators manually in the action), and perhaps also show the one-method technique. However, I'm not sure the one-method technique will be supported by map.resource, though you can use arguments to get something approaching that. I'm not sure what you mean by one-method scheme. What I was suggesting for @validate would still have two methods on the controller, one for form processing and one for displaying the form. It's just these would be accessed at the *same* URL, being differentiated by whether it was POST or a GET. This is exactly what happens now when re-submitting a form that didn't validate... the form is redisplayed at, say, /account/create and also POSTed to /account/create. The difference is that there is an extra / account/create_form URL through which the form is accessed initially. What good does this extra URL do? As far as I can tell, none. So what I'm proposing isn't fundamentally different from what happens already with @validate, and it's not using any techniques that are not already used in the current @validate. Regarding URLs, I only have the very vaguest idea of what REST is. Much like Matt, I structure my URLs like this: /account/create -- Create an account (GET displays the form, POST creates the account and redirects to /account/id) /account/id -- Displays the account details /account/id/edit -- Edit account details (similar to /account/create) /account/delete -- Deletes the account (GET gives a form asking confirmation, POST does the deletion). This has worked very well for me so far. Cheers, Steven --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 1:12 PM, Matt Feifarek [EMAIL PROTECTED] wrote: make_map() stock certainly doesn't work that way. :controller/:action/:id does go the other way, if your actions are things like view, add, delete. I use them differently, with the controller being a section of the site and the action being a subsection, as in /faq vs /faq/privacy_policy. Until recently all my pages have been read-only so this has worked well. But for modifiable things I'll need something else. Routes 2 will replace :controller/:action/:id with a single default route, which is non-minimizable. So if it's :controller/:action, you'd have to specify both or use another route. If it's :controller, you could only specify the controller (useful for TG2 and WSGI controllers; not useful for Pylons controllers). That might make it a good time to transition away from /articles/edit/12 type URLs. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
Ben Bangert wrote: On Jan 29, 2008, at 1:26 PM, Ian Bicking wrote: I still don't get what you are doing. I'm talking about HTTP. Here's what a sensible RESTful interaction looks like: Browsers can't do sensible RESTful interactions, as they have no PUT or DELETE. What I'm referring to is how that's 'faked' for browsers by including a _method='PUT' or _method='DELETE' in a POST body (for use *only* with browsers). While _method=DELETE mostly makes sense to me (you aren't effecting the natural body, since DELETE doesn't have a body), I still don't get how this works with PUT. It's not a PUT. Why pretend it's a PUT? It feels like an abuse of the term. Ian --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008 2:55 PM, Steven Holmes [EMAIL PROTECTED] wrote: On 29 Jan 2008, at 18:51, Mike Orr wrote: @validate is another issue. It's a nice convenience but it does limit what you can do in your code. Going to a one-method scheme would require it to be bypassed or rewritten in the application. I've also found another problem in that the forms I'm porting to Pylons have a Cancel button, which is supposed to bypass the validators and do a redirect. I'd either have to have a big OR validator around all the others, or wrap or rewrite @validate to process cancel before executing the validators. So, I think the Pylons docs need to mention @rewrite's limitions and show how to work around them (calling the validators manually in the action), and perhaps also show the one-method technique. However, I'm not sure the one-method technique will be supported by map.resource, though you can use arguments to get something approaching that. I'm not sure what you mean by one-method scheme. I meant having the same controller method both display the form and process it. This is how some other frameworks do it, and what I thought you wanted. The method would need an if to distinguish whether there's form input, and another to distinguish whether there were errors. I forgot that @validate without the form= argument would call the original method, so it should work in a one-method scenario after all. What I was suggesting for @validate would still have two methods on the controller, one for form processing and one for displaying the form. It's just these would be accessed at the *same* URL, being differentiated by whether it was POST or a GET. This is exactly what happens now when re-submitting a form that didn't validate... the form is redisplayed at, say, /account/create and also POSTed to /account/create. The difference is that there is an extra / account/create_form URL through which the form is accessed initially. What good does this extra URL do? As far as I can tell, none. So what I'm proposing isn't fundamentally different from what happens already with @validate, and it's not using any techniques that are not already used in the current @validate. I don't see why it matters that an error form is displayed at a different URL than the original form, especially since it's a temporary transition step (not something to bookmark). But point taken that the same URL could route to two different methods depending on the HTTP action. Regarding URLs, I only have the very vaguest idea of what REST is. Much like Matt, I structure my URLs like this: /account/create -- Create an account (GET displays the form, POST creates the account and redirects to /account/id) /account/id -- Displays the account details /account/id/edit -- Edit account details (similar to /account/create) /account/delete -- Deletes the account (GET gives a form asking confirmation, POST does the deletion). I assume you mean /account/id/delete. That's what I've been doing too. I've been trying to port my pages to map.resource to be REST-ly correct, but I'm starting to think this is not necessary for things like accounts that will never be syndicated. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
Ben Bangert wrote: On Jan 29, 2008, at 3:27 PM, Ian Bicking wrote: While _method=DELETE mostly makes sense to me (you aren't effecting the natural body, since DELETE doesn't have a body), I still don't get how this works with PUT. It's not a PUT. Why pretend it's a PUT? It feels like an abuse of the term. So that you have a API that works with browsers and real service consumers (that do know PUT). Again, its purely for browsers since they can't do PUT/DELETE. In the case of faking a DELETE from a web browser, you will not actually be sending a DELETE (browser's can't), so you do a POST and in the body you have the _method=DELETE. Same thing for a PUT. Why don't you just match method=('PUT', 'POST') so the same route accepts both verbs? Calling a POST a PUT is just silly. You pretend its a PUT so that you can code up a single controller that is compatible with both browsers *and* service oriented clients. Yes, but service based clients and browsers send totally different request bodies. Making them look like they were submitted with same verb doesnt change that. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
It sounds like we want a new map method that does what Steven is describing, for sites that want to add/modify/delete something but don't need the limitations/opportunities of map.resources. Anybody have an idea for a method name? map.resource2, map.nonresource, map.entity, map.object, ...? -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 29, 2008, at 3:27 PM, Ian Bicking wrote: While _method=DELETE mostly makes sense to me (you aren't effecting the natural body, since DELETE doesn't have a body), I still don't get how this works with PUT. It's not a PUT. Why pretend it's a PUT? It feels like an abuse of the term. So that you have a API that works with browsers and real service consumers (that do know PUT). Again, its purely for browsers since they can't do PUT/DELETE. In the case of faking a DELETE from a web browser, you will not actually be sending a DELETE (browser's can't), so you do a POST and in the body you have the _method=DELETE. Same thing for a PUT. You pretend its a PUT so that you can code up a single controller that is compatible with both browsers *and* service oriented clients. - Ben smime.p7s Description: S/MIME cryptographic signature
Re: An idea for improving @validate
Just realised I accidentally sent this to Mike directly instead of the list. On 29 Jan 2008, at 23:17, Mike Orr wrote: On Jan 29, 2008 2:55 PM, Steven Holmes [EMAIL PROTECTED] wrote: What I was suggesting for @validate would still have two methods on the controller, one for form processing and one for displaying the form. It's just these would be accessed at the *same* URL, being differentiated by whether it was POST or a GET. This is exactly what happens now when re-submitting a form that didn't validate... the form is redisplayed at, say, /account/create and also POSTed to /account/create. The difference is that there is an extra / account/create_form URL through which the form is accessed initially. What good does this extra URL do? As far as I can tell, none. So what I'm proposing isn't fundamentally different from what happens already with @validate, and it's not using any techniques that are not already used in the current @validate. I don't see why it matters that an error form is displayed at a different URL than the original form, especially since it's a temporary transition step (not something to bookmark). But point taken that the same URL could route to two different methods depending on the HTTP action. It matters for two reasons: It's exposing an implementation detail to the user (they don't give a damn that internally the form is using two methods). It's also inconsistent. Why *shouldn't* a user bookmark a URL to edit their account? And why would the user expect two pages that display the same form to act so differently--one being bookmarkable, one not being bookmarkable. It's just unnecessarily confusing. They don't care if the step is a transition step or not, and they certainly shouldn't have to care. And what will happen if the user clicks return in the address bar and reloads the page with a GET? It breaks. It's just a Bad Way Of Doing Things. There are no advantages to it that I can see. Regarding URLs, I only have the very vaguest idea of what REST is. Much like Matt, I structure my URLs like this: /account/create -- Create an account (GET displays the form, POST creates the account and redirects to /account/id) /account/id -- Displays the account details /account/id/edit -- Edit account details (similar to /account/ create) /account/delete -- Deletes the account (GET gives a form asking confirmation, POST does the deletion). I assume you mean /account/id/delete. That's what I've been doing too. I've been trying to port my pages to map.resource to be REST-ly correct, but I'm starting to think this is not necessary for things like accounts that will never be syndicated. Yeah, I meant /account/id/delete Cheers, Steven --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---
Re: An idea for improving @validate
On Jan 28, 2008 5:33 PM, Steven Holmes [EMAIL PROTECTED] wrote: @validate supports separating form rendering and form post processing into distinct methods. This is convenient, but has a nasty flaw: It requires two separate URLs, a form display URL and a URL to handle the post. When a form post fails to validate, the form is re-displayed, but at the post URL instead of the original form display URL. I find this inconsistent and broken. There seem to be two philosophies about that. I agree with you, that it's cleaner to have everything in one method with: if form_submitted: if not form_has_errors: do action display form Quixote's form handling is like this. But Pylons and TurboGears users generally seem to prefer it the other way, so that each method just does one thing. -- Mike Orr [EMAIL PROTECTED] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups pylons-discuss group. To post to this group, send email to pylons-discuss@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en -~--~~~~--~~--~--~---