Blobstore API untuk Python 3

Halaman ini menjelaskan cara menggunakan Blobstore API, salah satu layanan paket versi lama, dengan runtime Python 3 untuk lingkungan standar. Aplikasi Anda dapat mengakses layanan yang dipaketkan melalui SDK layanan App Engine untuk Python 3.

Ringkasan

Karena webapp tidak didukung di Python 3, Anda perlu melakukan beberapa perubahan kecil saat memigrasikan kode pengendali Blobstore dari Python 2 ke Python 3. Untuk menggunakan Blobstore API untuk Python 3, perhatikan hal-hal berikut:

  • Class pengendali Blobstore adalah class utilitas. Ini berarti bahwa class pengendali tidak lagi berbasis aplikasi web, dan Anda tidak dapat menggunakan modul blobstore_handlers yang disediakan oleh paket webapp (google.appengine.ext.webapp) atau parameter webapp2.RequestHandler di subclass dari pengendali ini.

  • Semua metode dalam class pengendali Blobstore memerlukan kamus environ WSGI sebagai parameter input.

Bagian berikut menunjukkan cara menggunakan class BlobstoreUploadHandler dan BlobstoreDownloadHandler untuk Python 3 di aplikasi Flask dan aplikasi WSGI yang tidak menggunakan framework Python. Anda dapat membandingkan contoh Python 3 dengan kode contoh Python 2 untuk mempelajari perbedaan perubahan kode lebih lanjut.

Contoh: Aplikasi Flask

Di Python 3, class pengendali Blobstore adalah bagian dari modul google.appengine.ext.blobstore. Untuk aplikasi Flask, semua panggilan yang dilakukan ke metode di class BlobstoreUploadHandler dan BlobstoreDownloadHandler memerlukan kamus request.environ (request diimpor dari modul flask).

Bandingkan perubahan kode yang dilakukan dari Python 2 (webapp2) dengan Python 3 (Flask). Perhatikan cara aplikasi Flask menggunakan parameter request.environ dalam metode get_uploads() dan send_blob():

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()

Jika ingin melihat contoh kode lengkap untuk Python 3 (Flask), lihat GitHub.

Contoh: Aplikasi WSGI tanpa framework web

Kode Python 3 (aplikasi WSGI) berikut menunjukkan cara menambahkan parameter environ saat menggunakan class pengendali Blobstore untuk aplikasi WSGI tanpa framework web. Perhatikan cara parameter environ digunakan dalam metode get_uploads() dan send_blob(), lalu bandingkan dengan versi 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),
]

Jika ingin melihat contoh kode lengkap untuk Python 3, lihat GitHub.