Images API examples

Region ID

The REGION_ID is an abbreviated code that Google assigns based on the region you select when you create your app. The code does not correspond to a country or province, even though some region IDs may appear similar to commonly used country and province codes. For apps created after February 2020, REGION_ID.r is included in App Engine URLs. For existing apps created before this date, the region ID is optional in the URL.

Learn more about region IDs.

Learn how to upload, transform, store, and serve images dynamically using the Images API. This example describes how to post messages to a public message board and upload an avatar with your greeting.

Creating an Image model in Datastore

You need to update the model from the guestbook sample to store the uploaded image as a blob.

class Greeting(ndb.Model):
    """Models a Guestbook entry with an author, content, avatar, and date."""
    author = ndb.StringProperty()
    content = ndb.TextProperty()
    avatar = ndb.BlobProperty()
    date = ndb.DateTimeProperty(auto_now_add=True)

Uploading user images

You will need to modify the HTML form to enable the user to upload an image:

  1. Add a field that enables the user to select a file from their computer to upload.

  2. Add the enctype attribute to the form tag and specify this is a multi-part form post.

    self.response.out.write("""
          <form action="/sign?%s"
                enctype="multipart/form-data"
                method="post">
            <div>
              <textarea name="content" rows="3" cols="60"></textarea>
            </div>
            <div><label>Avatar:</label></div>
            <div><input type="file" name="img"/></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)))
  3. Update the Guestbook handler to get the image data from the form post and store it as a blob in the datastore.

    class Guestbook(webapp2.RequestHandler):
        def post(self):
            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')
    
            avatar = self.request.get('img')
            avatar = images.resize(avatar, 32, 32)
            greeting.avatar = avatar
            greeting.put()
    
            self.redirect('/?' + urllib.urlencode(
                {'guestbook_name': guestbook_name}))

Transforming images

To create 32x32 avatars you will need to:

  1. Import the google.appengine.api.images module.

    from google.appengine.api import images
  2. Call the resize function and pass in the image data.

    avatar = images.resize(avatar, 32, 32)

Dynamically serving images

To serve images, you will need to:

  1. Create an image handler that dynamically serves images off the /img path.

    class Image(webapp2.RequestHandler):
        def get(self):
            greeting_key = ndb.Key(urlsafe=self.request.get('img_id'))
            greeting = greeting_key.get()
            if greeting.avatar:
                self.response.headers['Content-Type'] = 'image/png'
                self.response.out.write(greeting.avatar)
            else:
                self.response.out.write('No image')
  2. Update the HTML to display these dynamically served images.

    self.response.out.write('<div><img src="/img?img_id=%s"></img>' %
                            greeting.key.urlsafe())
    self.response.out.write('<blockquote>%s</blockquote></div>' %
                            cgi.escape(greeting.content))

You will need to update the Guestbook's HTML to pass the key of the greeting to the image handler as it gets the img_id from the request.

Deploying the app to App Engine

To upload the guestbook app, run the following command from within the guestbook directory of your application where the app.yaml and index.yaml files are located:

gcloud app deploy app.yaml index.yaml

The Datastore indexes might take some time to generate before your application is available. If the indexes are still in the process of being generated, you will receive a NeedIndexError message when accessing your app. This error is transient, so try a little later if at first you receive this error.

To learn more about deploying your app from the command line, see Deploying A Python App.

Viewing your deployed application

To launch your browser and view the app at https://PROJECT_ID.REGION_ID.r.appspot.com, run the following command:

gcloud app browse