Blobstore API für Python 3

Auf dieser Seite wird beschrieben, wie Sie die Blobstore API, einen der gebündelten Legacy-Dienste, mit der Python 3-Laufzeit für die Standardumgebung verwenden. Ihre Anwendung kann über das App Engine Services SDK für Python 3 auf die gebündelten Dienste zugreifen.

Übersicht

Da "webapp" in Python 3 nicht unterstützt wird, müssen Sie bei der Migration des Blobstore-Handler-Codes von Python 2 zu Python 3 einige Änderungen vornehmen. Beachten Sie Folgendes, um die Blobstore API für Python 3 zu verwenden:

  • Blobstore-Handler-Klassen sind Dienstprogrammklassen. Dies bedeutet, dass die Handler-Klassen nicht mehr webapp-basiert sind und Sie das Modul blobstore_handlers, das vom webapp-Paket (google.appengine.ext.webapp) bereitgestellt wird, oder die Parameter webapp2.RequestHandler in Unterklassen dieser Handler nicht verwenden können.

  • Alle Methoden in Blobstore-Handler-Klassen erfordern das WSGI-Dictionary environ als Eingabeparameter.

In den folgenden Abschnitten wird gezeigt, wie Sie die Klassen BlobstoreUploadHandler und BlobstoreDownloadHandler für Python 3 in einer Flask-Anwendung und einer WSGI-Anwendung, die kein Python-Framework verwendet, verwenden. Sie können die Python 3-Beispiele mit dem Python 2-Beispielcode vergleichen, um mehr über Unterschiede bei Codeänderungen zu erfahren.

Beispiel: Flask-Anwendung

In Python 3 sind die Blobstore-Handler-Klassen Teil des Moduls google.appengine.ext.blobstore. Bei einer Flask-Anwendung erfordern alle Aufrufe von Methoden der Klassen BlobstoreUploadHandler und BlobstoreDownloadHandler das Dictionary request.environ (request wird aus dem Modul flask importiert).

Vergleichen Sie die Codeänderungen von Python 2 (webapp2) mit Python 3 (Flask). Beachten Sie, wie die Flask-Anwendung den Parameter request.environ in den Methoden get_uploads() und send_blob() verwendet:

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

Das vollständige Codebeispiel für Python 3 (Flask) finden Sie unter GitHub.

Beispiel: WSGI-Anwendung ohne Web-Framework

Der folgende Python 3-Code (WSGI-App-Code) zeigt, wie der Parameter environ bei Verwendung von Blobstore-Handler-Klassen für eine WSGI-Anwendung ohne Web-Framework hinzugefügt wird. Beachten Sie, wie der Parameter environ in den Methoden get_uploads() und send_blob() verwendet wird, und vergleichen Sie ihn mit der Version von 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),
]

Das vollständige Codebeispiel für Python 3 finden Sie auf GitHub.