views:

612

answers:

1

Im checking the examples google gives on how to start using python; especifically the code posted here; http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html

The thing that i want to lean is that, here:

class Guestbook(webapp.RequestHandler):
  def post(self):
    greeting = Greeting()

    if users.get_current_user():
      greeting.author = users.get_current_user()

    greeting.content = self.request.get('content')
    greeting.put()
    self.redirect('/')

They are saving a comment, IF the user is logged in, we save the user; if not its empty and when we get it out of the db we actually check for that here:

  if greeting.author:
    self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
  else:
    self.response.out.write('An anonymous person wrote:')

So what i would like is to use the User object to get the information, like this:

class Guestbook(webapp.RequestHandler):
    def post(self):
        user = users.get_current_user()
        if user:
            greeting = Greeting()
        if users.get_current_user():
            greeting.author = users.get_current_user()
            greeting.content = self.request.get('content')
            greeting.put()
            self.redirect('/')
        else:
            self.redirect(users.create_login_url(self.request.uri))

So, what i would like to do with that code is to send the user to the login url(if he is not logged in); and then to come back with whatever he had in post and actually post it. But what happens is that it doesnt even get to that action coz is nothing in the post. I know i could put something in the session and check for it in the get action of the guestbook, but i wanted to check if someone could come up with a better solution!

Thanks

+3  A: 

The problem is, self.redirect cannot "carry along" the payload of a POST HTTP request, so (from a post method) the redirection to the login-url &c is going to misbehave (in fact I believe the login URL will use get to continue when it's done, and that there's no way to ask it to do a post instead).

If you don't want to stash that POST payload around somewhere (session or otherwise), you can make your code work by changing the def post in your snippet above to def get, and of course the action="post" in the HTML written in other parts of the example that you haven't snipped to action="get". There are other minor workarounds (you could accept post for "normal" messages from logged-in users and redirect them to the get that perhaps does something simpler if they weren't logged in yet), but I think this info is sufficient to help you continue from here, right?

Alex Martelli
There's several rather large caveats to this solution: GETs are a poor choice for long data, and they're intended to be idempotent. Submitting anything non-idempotent (such as a guestbook entry) introduces XSRF issues.
Nick Johnson
@Nick, good points -- that's why a "stash payload around somewhere" approach is also worth considering (e.g., whenever the data may be long, or if potential forgeries are an issue despite the "logged-in user" condition on the GET being accepted).
Alex Martelli