Storing Images on App Engine using Django

2020-05-21 12:04发布

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.

2条回答
Lonely孤独者°
2楼-- · 2020-05-21 12:53

You access uploaded data via request.FILES['field_name'].

http://docs.djangoproject.com/en/dev/topics/http/file-uploads/


Reading more about Google's Image API, seems to me you should be doing something like this:

from google.appengine.api import images

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

request.FILES['image'].read() should work because it's supposed to be a Django's UploadedFile instance.

查看更多
迷人小祖宗
3楼-- · 2020-05-21 13:06

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
查看更多
登录 后发表回答