Python 3용 Blobstore API

이 페이지에서는 표준 환경에 Python 3 런타임과 함께 기존 번들 서비스 중 하나인 Blobstore API를 사용하는 방법을 설명합니다. 앱은 Your app can access the bundled services through the Python 3용 App Engine 서비스 SDK를 통해 번들 서비스에 액세스할 수 있습니다.

개요

웹 앱은 Python 3에서 지원되지 않으므로 Blobstore 핸들러 코드를 Python 2에서 Python 3으로 마이그레이션할 때 최소한 몇 가지 사항을 변경해야 합니다. Python 3용 Blobstore API를 사용하려면 다음 사항에 유의하세요.

  • Blobstore 핸들러 클래스는 유틸리티 클래스입니다. 즉, 핸들러 클래스는 더 이상 웹 기반이 아니며 웹 앱 패키지(google.appengine.ext.webapp) 또는 이러한 핸들러 서브클래스의 webapp2.RequestHandler 매개변수에서 제공하는 blobstore_handlers 모듈을 사용할 수 없습니다.

  • Blobstore 핸들러 클래스의 모든 메서드를 사용하려면 WSGI environ 사전이 입력 매개변수로 필요합니다.

다음 섹션에서는 Flask 앱과 Python 프레임워크를 사용하지 않는 WSGI 앱에서 Python 3용 BlobstoreUploadHandler 및 BlobstoreDownloadHandler 클래스를 사용하는 방법을 보여줍니다. 코드 변경 차이를 자세히 알아보려면 Python 3 예시를 Python 2 예시 코드와 비교하면 됩니다.

예: Flask 앱

Python 3에서 Blobstore 핸들러 클래스는 google.appengine.ext.blobstore 모듈의 일부입니다. Flask 앱의 경우 BlobstoreUploadHandler 및 BlobstoreDownloadHandler 클래스의 메서드에 대한 모든 호출을 사용하려면 request.environ 사전(flask 모듈에서 가져오는 request)이 필요합니다.

Python 2(webapp2)와 Python 3(Flask)의 코드 변경사항을 비교합니다. Flask 앱에서 get_uploads() 및 send_blob() 메서드에서 request.environ 매개변수를 사용하는 방법을 확인합니다.

Python 2(webapp2)

class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload = self.get_uploads()[0]
        user_photo = UserPhoto(
            user=users.get_current_user().user_id(),
            blob_key=upload.key())
        user_photo.put()

        self.redirect('/view_photo/%s' % upload.key())

class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, photo_key):
        if not blobstore.get(photo_key):
            self.error(404)
        else:
            self.send_blob(photo_key)

app = webapp2.WSGIApplication([
    ('/', PhotoUploadFormHandler),
    ('/upload_photo', PhotoUploadHandler),
    ('/view_photo/([^/]+)?', ViewPhotoHandler),
], debug=True)

Python 3(Flask)

class PhotoUploadHandler(blobstore.BlobstoreUploadHandler):
    def post(self):
        upload = self.get_uploads(request.environ)[0]
        photo = PhotoUpload(blob_key=upload.key())
        photo.put()

        return redirect("/view_photo/%s" % upload.key())


class ViewPhotoHandler(blobstore.BlobstoreDownloadHandler):
    def get(self, photo_key):
        if not blobstore.get(photo_key):
            return "Photo key not found", 404
        else:
            headers = self.send_blob(request.environ, photo_key)

            # Prevent Flask from setting a default content-type.
            # GAE sets it to a guessed type if the header is not set.
            headers["Content-Type"] = None
            return "", headers


@app.route("/view_photo/<photo_key>")
def view_photo(photo_key):
    """View photo given a key."""
    return ViewPhotoHandler().get(photo_key)


@app.route("/upload_photo", methods=["POST"])
def upload_photo():
    """Upload handler called by blobstore when a blob is uploaded in the test."""
    return PhotoUploadHandler().post()

Python 3(Flask)의 전체 코드 샘플을 보려면 GitHub를 참조하세요.

예: 웹 프레임워크가 없는 WSGI 앱

다음 Python 3(WSGI 앱) 코드에서는 웹 프레임워크가 없는 WSGI 앱에 Blobstore 핸들러 클래스를 사용할 때 environ 파라미터를 추가하는 방법을 보여줍니다. environ 파라미터가 get_uploads() 및 send_blob() 메서드에서 사용되는 방식을 확인하고 Python 2 버전과 비교합니다.

Python 2

class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload = self.get_uploads()[0]
        user_photo = UserPhoto(
            user=users.get_current_user().user_id(),
            blob_key=upload.key())
        user_photo.put()

        self.redirect('/view_photo/%s' % upload.key())

class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, photo_key):
        if not blobstore.get(photo_key):
            self.error(404)
        else:
            self.send_blob(photo_key)

app = webapp2.WSGIApplication([
    ('/', PhotoUploadFormHandler),
    ('/upload_photo', PhotoUploadHandler),
    ('/view_photo/([^/]+)?', ViewPhotoHandler),
], debug=True)

Python 3

class UploadPhotoHandler(blobstore.BlobstoreUploadHandler):
    """Upload handler called by blobstore when a blob is uploaded in the test."""

    def post(self, environ):
        upload = self.get_uploads(environ)[0]
        user_photo = UserPhoto(blob_key=upload.key())
        user_photo.put()

        # Redirect to the '/view_photo/<Photo Key>' URL
        return (
            "",
            http.HTTPStatus.FOUND,
            [("Location", "/view_photo/%s" % upload.key())],
        )


class ViewPhotoHandler(blobstore.BlobstoreDownloadHandler):
    def get_photo(self, environ, photo_key):
        if not blobstore.get(photo_key):
            return "Photo key not found", http.HTTPStatus.NOT_FOUND, []
        else:
            return (
                "",
                http.HTTPStatus.OK,
                list(self.send_blob(environ, photo_key).items()),
            )

    def get(self, environ):
        photo_key = (environ["app.url_args"])[0]
        return self.get_photo(environ, photo_key)


# map urls to functions
urls = [
    (r"^$", UploadFormHandler),
    (r"upload_photo/?$", UploadPhotoHandler),
    (r"view_photo/(.+)$", ViewPhotoHandler),
]

Python 3(Flask)의 전체 코드 샘플을 보려면 GitHub를 참조하세요.