Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing Images on App Engine using Django

I'm trying to upload and save a resized image in a db.BlobProperty field on Google App Engine using Django.

the relevant part of my view that process the request looks like this:

image = images.resize(request.POST.get('image'), 100, 100)
recipe.large_image = db.Blob(image)
recipe.put()

Which seems like it would be the logical django equivalent of the example in the docs:

from google.appengine.api import images

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")
    avatar = images.resize(self.request.get("img"), 32, 32)
    greeting.avatar = db.Blob(avatar)
    greeting.put()
    self.redirect('/')

(source: http://code.google.com/appengine/docs/python/images/usingimages.html#Transform)

But, I keep getting an error that says: NotImageError / Empty image data.

and refers to this line:

image = images.resize(request.POST.get('image'), 100, 100)

I'm having trouble getting to the image data. Seems like it's not being uploaded but I can't figure out why. My form has the enctype="multipart/form-data" and all that. I think something's wrong with how I'm referring to the image data. "request.POST.get('image')" but I can't figure out how else to reference it. Any ideas?

Thanks in advance.

like image 960
Henrik Joreteg Avatar asked Oct 24 '09 03:10

Henrik Joreteg


1 Answers

After some guidance from "hcalves" I figured out the problem. First of all, the default version of Django that comes bundled with App Engine is version 0.96 and how the framework handles uploaded files has changed since then. However in order to maintain compatibility with older apps you have to explicitly tell App Engine to use Django 1.1 like this:

from google.appengine.dist import use_library
use_library('django', '1.1')

You can read more about that in the app engine docs.

Ok, so here's the solution:

from google.appengine.api import images

image = request.FILES['large_image'].read()
recipe.large_image = db.Blob(images.resize(image, 480))
recipe.put()

Then, to serve the dynamic images back again from the datastore, build a handler for images like this:

from django.http import HttpResponse, HttpResponseRedirect

def recipe_image(request,key_name):
    recipe = Recipe.get_by_key_name(key_name)

    if recipe.large_image:
        image = recipe.large_image
    else:
        return HttpResponseRedirect("/static/image_not_found.png")

    #build your response
    response = HttpResponse(image)
    # set the content type to png because that's what the Google images api 
    # stores modified images as by default
    response['Content-Type'] = 'image/png'
    # set some reasonable cache headers unless you want the image pulled on every request
    response['Cache-Control'] = 'max-age=7200'
    return response
like image 119
Henrik Joreteg Avatar answered Nov 13 '22 11:11

Henrik Joreteg