I store thumbnail images in Google App engine entities as BlobStoreProperties. Over time thumbnails need to be updated, which I do by updating the content of these entities with fresh image data. However I found out that any subsequent retrieval of these images still returns the same old copy that was saved first time in the entity. It’s surprisingly inconsistent behavior. I wrote a simple standalone code to verify this.
Here are two simple handlers and a model definition. SaveImageHandler saves the image to datastore and LoadImageHandler retrieves it.
from google.appengine.ext import db
import logging
class Image(db.Expando):
data = db.BlobProperty(required=True)
uid = db.StringProperty(required=True)
class SaveImageHandler(webapp.RequestHandler):
def post(self, uid):
imgdata = self.request.POST.get('imgdata').file.read()
logging.error('Saving %d bytes'%(len(imgdata)))
image = model.Image(data=imgdata, uid=uid)
image.put()
class LoadImageHandler(webapp.RequestHandler):
def post(self, uid):
image = model.Image.gql('WHERE uid = :1', uid).get()
self.response.headers['Content-type'] = 'image/png'
logging.error('Loading %d bytes'%(len(image.data)))
self.response.out.write(image.data)
def application():
return webapp.WSGIApplication([
('/_thumbsave/(.*)', SaveImageHandler),
('/_thumbload/(.*)', LoadImageHandler),
],debug=False)
def main():
util.run_wsgi_app(application())
if __name__ == '__main__':
main()
I upload an image like this
curl -F "imgdata=@/tmp/img1.png" http://ubuntu.local:8000/_thumbsave/X
I retrieve the image
curl -d dummy=0 http://ubuntu.local:8000/_thumbload/X > Downloads/imgout.png
imgout.png and img1.png are same
Then I upload another image img2.png
curl -F "imgdata=@/tmp/img2.png" http://ubuntu.local:8000/_thumbsave/X
Then retrieve it in same way above. I expect now imgout.png to be same as img2.png. But instead I find that it’s still the same old img1.png. Thus the Image query, returned stale object. The log statements that print the length of image, also verify that the image returned second time is not the updated one.
What’s going wrong here?
In your
SaveImageHandleryou are creating a newImageentity each time you POST your image data, then you are just fetching the first image with that uid in yourLoadImageHandlerChange it to ‘find or create’ the image like:
Rather than using a
uidproperty, think about usingkey_namesfor that purpose, and take a look at the get_or_insert method