Python 2.7 has reached end of supportand will bedeprecatedon January 31, 2026. After deprecation, you won't be able to deploy Python 2.7applications, even if your organization previously used an organization policy tore-enable deployments of legacy runtimes. Your existing Python2.7 applications will continue to run and receive traffic after theirdeprecation date. We recommend thatyoumigrate to the latest supported version of Python.

Images API examples

Region ID

TheREGION_ID is an abbreviated code that Google assignsbased on the region you select when you create your app. The code does notcorrespond to a country or province, even though some region IDs may appearsimilar 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 moreabout region IDs.

Learn how to upload, transform, store, and serve images dynamically using theImages API. Thisexample describes how to post messages to a public message board and upload anavatar with your greeting.

This page describes how to use the legacy bundled services and APIs. This API can only run in first-generation runtimes in the App Engine standard environment. If you are updating to the App Engine Python 3 runtime, refer to themigration guide to learn about your migration options for legacy bundled services.

Creating an Image model in Datastore

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

classGreeting(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 theenctype 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 inthe datastore.

    classGuestbook(webapp2.RequestHandler):defpost(self):guestbook_name=self.request.get('guestbook_name')greeting=Greeting(parent=guestbook_key(guestbook_name))ifusers.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=avatargreeting.put()self.redirect('/?'+urllib.urlencode({'guestbook_name':guestbook_name}))

Transforming images

To create 32x32 avatars you will need to:

  1. Import thegoogle.appengine.api.images module.

    fromgoogle.appengine.apiimportimages
  2. Call theresize 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.

    classImage(webapp2.RequestHandler):defget(self):greeting_key=ndb.Key(urlsafe=self.request.get('img_id'))greeting=greeting_key.get()ifgreeting.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 asit gets theimg_id from the request.

Deploying the app to App Engine

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

gcloudappdeployapp.yamlindex.yaml

TheDatastore indexes might take some time togenerate before your application is available. If the indexes are still in theprocess of being generated, you will receive aNeedIndexErrormessage when accessing your app. This error is transient, so try a little laterif at first you receive this error.

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

Viewing your deployed application

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

gcloudappbrowse

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.