Python 2.7은 지원이 종료되었으며 2026년 1월 31일에 지원 중단됩니다. 지원 중단 후에는 조직에서 이전에 조직 정책을 사용하여 레거시 런타임의 배포를 다시 사용 설정한 경우에도 Python 2.7 애플리케이션을 배포할 수 없습니다. 기존 Python 2.7 애플리케이션은 지원 중단 날짜 이후에도 계속 실행되고 트래픽을 수신합니다. 지원되는 최신 Python 버전으로 마이그레이션하는 것이 좋습니다.
REGION_ID는 앱을 만들 때 선택한 리전을 기준으로 Google에서 할당하는 축약된 코드입니다. 일부 리전 ID는 일반적으로 사용되는 국가 및 주/도 코드와 비슷하게 표시될 수 있지만 코드는 국가 또는 주/도와 일치하지 않습니다. 2020년 2월 이후에 생성된 앱의 경우 REGION_ID.r이 App Engine URL에 포함됩니다. 이 날짜 이전에 만든 기존 앱의 경우 URL에서 리전 ID는 선택사항입니다.
Images API를 사용하여 이미지를 동적으로 업로드, 변환, 저장, 제공하는 방법을 알아봅니다. 이 예시에서는 공개 게시판에 글을 올리고 아바타와 함께 인사말을 업로드하는 방법을 설명합니다.
Datastore에서 이미지 모델 만들기
업로드된 이미지를 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)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-04(UTC)"],[[["\u003cp\u003eRegion IDs are codes assigned by Google based on the selected region when creating an app, and they do not necessarily correspond to country or province codes.\u003c/p\u003e\n"],["\u003cp\u003eThe Images API allows for the dynamic uploading, transforming, storing, and serving of images, as demonstrated by the example of posting messages and uploading avatars to a public message board.\u003c/p\u003e\n"],["\u003cp\u003eTo store uploaded images, the Guestbook model in Datastore needs to be updated to include a blob property, enabling users to select files for upload through an HTML form with specific attributes.\u003c/p\u003e\n"],["\u003cp\u003eImage transformation involves importing the \u003ccode\u003egoogle.appengine.api.images\u003c/code\u003e module and using the \u003ccode\u003eresize\u003c/code\u003e function to adjust image dimensions, such as creating 32x32 avatars.\u003c/p\u003e\n"],["\u003cp\u003eDeploying the guestbook application to App Engine involves using the \u003ccode\u003egcloud app deploy app.yaml index.yaml\u003c/code\u003e command, and accessing the deployed application can be done via \u003ccode\u003egcloud app browse\u003c/code\u003e, noting that Datastore indexes might take time to generate.\u003c/p\u003e\n"]]],[],null,["# Images API examples\n\n### Region ID\n\nThe \u003cvar translate=\"no\"\u003eREGION_ID\u003c/var\u003e is an abbreviated code that Google assigns\nbased on the region you select when you create your app. The code does not\ncorrespond to a country or province, even though some region IDs may appear\nsimilar to commonly used country and province codes. For apps created after\nFebruary 2020, \u003cvar translate=\"no\"\u003eREGION_ID\u003c/var\u003e`.r` is included in\nApp Engine URLs. For existing apps created before this date, the\nregion ID is optional in the URL.\n\nLearn more\n[about region IDs](/appengine/docs/legacy/standard/python/how-requests-are-routed#region-id). \nOK\n\nLearn how to upload, transform, store, and serve images dynamically using the [Images API](/appengine/docs/legacy/standard/python/refdocs/google.appengine.api.images). This\nexample describes how to post messages to a public message board and upload an\navatar with your greeting.\n| 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 the [migration guide](/appengine/migration-center/standard/migrate-to-second-gen/python-differences) to learn about your migration options for legacy bundled services.\n\nCreating an Image model in Datastore\n------------------------------------\n\nYou need to update the model from the guestbook sample to store the uploaded image as a blob. \n\n class Greeting(ndb.Model):\n \"\"\"Models a Guestbook entry with an author, content, avatar, and date.\"\"\"\n author = ndb.StringProperty()\n content = ndb.TextProperty()\n avatar = ndb.BlobProperty()\n date = ndb.DateTimeProperty(auto_now_add=True)\n\nUploading user images\n---------------------\n\nYou will need to modify the HTML form to enable the user to upload an image:\n\n1. Add a field that enables the user to select a file from their computer to upload.\n\n2. Add the `enctype` attribute to the form tag and specify this is a multi-part form post.\n\n self.response.out.write(\"\"\"\n \u003cform action=\"/sign?%s\"\n enctype=\"multipart/form-data\"\n method=\"post\"\u003e\n \u003cdiv\u003e\n \u003ctextarea name=\"content\" rows=\"3\" cols=\"60\"\u003e\u003c/textarea\u003e\n \u003c/div\u003e\n \u003cdiv\u003e\u003clabel\u003eAvatar:\u003c/label\u003e\u003c/div\u003e\n \u003cdiv\u003e\u003cinput type=\"file\" name=\"img\"/\u003e\u003c/div\u003e\n \u003cdiv\u003e\u003cinput type=\"submit\" value=\"Sign Guestbook\"\u003e\u003c/div\u003e\n \u003c/form\u003e\n \u003chr\u003e\n \u003cform\u003eGuestbook name: \u003cinput value=\"%s\" name=\"guestbook_name\"\u003e\n \u003cinput type=\"submit\" value=\"switch\"\u003e\u003c/form\u003e\n \u003c/body\u003e\n \u003c/html\u003e\"\"\" % (urllib.urlencode({'guestbook_name': guestbook_name}),\n cgi.escape(guestbook_name)))\n\n3. Update the Guestbook handler to get the image data from the form post and store it as a blob in\n the datastore.\n\n class Guestbook(webapp2.RequestHandler):\n def post(self):\n guestbook_name = self.request.get('guestbook_name')\n greeting = Greeting(parent=guestbook_key(guestbook_name))\n\n if users.get_current_user():\n greeting.author = users.get_current_user().nickname()\n\n greeting.content = self.request.get('content')\n\n avatar = self.request.get('img')\n avatar = images.resize(avatar, 32, 32)\n greeting.avatar = avatar\n greeting.put()\n\n self.redirect('/?' + urllib.urlencode(\n {'guestbook_name': guestbook_name}))\n\nTransforming images\n-------------------\n\nTo create 32x32 avatars you will need to:\n\n1. Import the [`google.appengine.api.images`](/appengine/docs/legacy/standard/python/refdocs/google.appengine.api.images) module.\n\n from google.appengine.api import images\n\n2. Call the `resize` function and pass in the image data.\n\n avatar = images.resize(avatar, 32, 32)\n\nDynamically serving images\n--------------------------\n\nTo serve images, you will need to:\n\n1. Create an image handler that dynamically serves images off the `/img` path.\n\n class Image(webapp2.RequestHandler):\n def get(self):\n greeting_key = ndb.Key(urlsafe=self.request.get('img_id'))\n greeting = greeting_key.get()\n if greeting.avatar:\n self.response.headers['Content-Type'] = 'image/png'\n self.response.out.write(greeting.avatar)\n else:\n self.response.out.write('No image')\n\n2. Update the HTML to display these dynamically served images.\n\n self.response.out.write('\u003cdiv\u003e\u003cimg src=\"/img?img_id=%s\"\u003e\u003c/img\u003e' %\n greeting.key.urlsafe())\n self.response.out.write('\u003cblockquote\u003e%s\u003c/blockquote\u003e\u003c/div\u003e' %\n cgi.escape(greeting.content))\n\nYou will need to update the Guestbook's HTML to pass the key of the greeting to the image handler as\nit gets the `img_id` from the request.\n\nDeploying the app to App Engine\n-------------------------------\n\nTo upload the guestbook app, run the following command from within the\n`guestbook` directory of your application where the `app.yaml` and\n`index.yaml` files are located: \n\n```bash\ngcloud app deploy app.yaml index.yaml\n```\n\nThe [Datastore indexes](/appengine/docs/standard/python3/building-app/storing-and-retrieving-data) might take some time to\ngenerate before your application is available. If the indexes are still in the\nprocess of being generated, you will receive a `NeedIndexError`\nmessage when accessing your app. This error is transient, so try a little later\nif at first you receive this error.\n\nTo learn more about deploying your app from the command line, see\n[Deploying A Python App](/appengine/docs/legacy/standard/python/tools/uploadinganapp).\n\nViewing your deployed application\n---------------------------------\n\nTo launch your browser and view the app at\n\n`https://`\u003cvar translate=\"no\"\u003ePROJECT_ID\u003c/var\u003e`.`\u003cvar translate=\"no\"\u003e\u003ca href=\"#appengine-urls\" style=\"border-bottom: 1px dotted #999\" class=\"devsite-dialog-button\" data-modal-dialog-id=\"regional_url\" track-type=\"progressiveHelp\" track-name=\"modalHelp\" track-metadata-goal=\"regionalURL\"\u003eREGION_ID\u003c/a\u003e\u003c/var\u003e`.r.appspot.com`, run the following command: \n\n```bash\ngcloud app browse\n```"]]