Ad

Overwrite In Datastore Using Python For GAE - Guestbook Example

I want to do something very similar to the Guestbook example GAE provides in Python.

But instead allowing one user to sign multiple times, I want each submission to overwrite any preexisting one by the current user.

I'm having trouble figuring out how to edit this example to make that work.

import cgi
import datetime
import urllib
import wsgiref.handlers

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


class Greeting(db.Model):
"""Models an individual Guestbook entry with an author, content, and date."""
author = db.StringProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)


def guestbook_key(guestbook_name=None):
"""Constructs a Datastore key for a Guestbook entity with guestbook_name."""
return db.Key.from_path('Guestbook', guestbook_name or 'default_guestbook')


class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
guestbook_name=self.request.get('guestbook_name')

# Ancestor Queries, as shown here, are strongly consistent with the High
# Replication Datastore. Queries that span entity groups are eventually
# consistent. If we omitted the ancestor from this query there would be a
# slight chance that Greeting that had just been written would not show up
# in a query.
greetings = db.GqlQuery("SELECT * "
                        "FROM Greeting "
                        "WHERE ANCESTOR IS :1 "
                        "ORDER BY date DESC LIMIT 10",
                        guestbook_key(guestbook_name))

for greeting in greetings:
  if greeting.author:
    self.response.out.write(
        '<b>%s</b> wrote:' % greeting.author)
  else:
    self.response.out.write('An anonymous person wrote:')
  self.response.out.write('<blockquote>%s</blockquote>' %
                          cgi.escape(greeting.content))

self.response.out.write("""
      <form action="/sign?%s" method="post">
        <div><textarea name="content" rows="3" cols="60"></textarea></div>
        <div><input type="submit" value="Sign Guestbook"></div>
      </form>
      <hr>
      <form>Guestbook name: <input value="%s" name="guestbook_name">
      <input type="submit" value="switch"></form>
    </body>
  </html>""" % (urllib.urlencode({'guestbook_name': guestbook_name}),
                      cgi.escape(guestbook_name)))


class Guestbook(webapp.RequestHandler):
def post(self):
# We set the same parent key on the 'Greeting' to ensure each greeting is in
# the same entity group. Queries across the single entity group will be
# consistent. However, the write rate to a single entity group should
# be limited to ~1/second.
guestbook_name = self.request.get('guestbook_name')
greeting = Greeting(parent=guestbook_key(guestbook_name))

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

greeting.content = self.request.get('content')
greeting.put()
self.redirect('/?' + urllib.urlencode({'guestbook_name': guestbook_name}))


application = webapp.WSGIApplication([
('/', MainPage),
('/sign', Guestbook)
], debug=True)


def main():
run_wsgi_app(application)


if __name__ == '__main__':
main()
Ad

Answer

The easiest way to do this is to modify the post method of the Guestbook class, so that it checks for an existing post from the current user and updates it, if it exists.

class Guestbook(webapp.RequestHandler):
  def post(self):
    guestbook_name = self.request.get('guestbook_name')
    user = users.get_current_user()
    nickname = None
    if user:
      nickname = user.nickname()
      greeting = Greeting.gql('WHERE author = :1 AND ANCESTOR IS :2',
          nickname, guestbook_key(guestbook_name)).get()
    if not greeting:
      greeting = Greeting(parent=guestbook_key(guestbook_name))
      greeting.author = nickname

    greeting.content = self.request.get('content')
    greeting.put()
    self.redirect('/?' + urllib.urlencode({'guestbook_name': guestbook_name}))
Ad
source: stackoverflow.com
Ad