読者です 読者をやめる 読者になる 読者になる

present

読書、食べ歩き、時々プログラミング

Kay Framework でも Blobstore を使ってみる

Python AppEngine

先日、App Engine で提供されている Blobstore を、webapp フレームワークで使っていました。

でも、実際のアプリ開発では Kay Framework を使っているわけで。


その Kay Framework ですけど、ちゃんと Blobstore を使うためのハンドラを提供しています。試しに、先日のコードを Kay で書き変えてみました。

core/views.py

# -*- coding: utf-8 -*-

import logging
import urllib

from google.appengine.api import users
from google.appengine.api import memcache
from google.appengine.ext import blobstore

import werkzeug
from werkzeug import exceptions

from kay import utils
from kay.handlers import blobstore_handlers


def index(request):
    # アップロード用の URL を作成
    # アップロードに成功したら core/upload エンドポイントへ移動させる
    upload_url = blobstore.create_upload_url(utils.url_for('core/upload'))

    # Blobstore に保存されているファイルをすべて取得
    files = blobstore.BlobInfo.all()

    # テンプレートを使って表示
    data = dict(
            upload_url=upload_url,
            files=files)
    return utils.render_to_response('core/index.html', data)


class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        # アップロードされたファイルの情報を取得
        files = self.get_uploads('file')
        blob_info = files[0]

        # redirect メソッドが上手く動かないので、ステータスコードとヘッダを使って
        # ブラウザにリダイレクトを指示
        headers = dict(Location=utils.url_for('core/serve', blob_key=blob_info.key()))
        return werkzeug.Response(None, headers=headers, status=302)


class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, blob_key):
        blob_key = str(urllib.unquote(blob_key))
        blob_info = blobstore.BlobInfo.get(blob_key)
        return self.send_blob(blob_info)

core/urls.py

# -*- coding: utf-8 -*-
# core.urls
# 

from kay.routing import (
    ViewGroup, Rule
)

view_groups = [
    ViewGroup(
        Rule('/', endpoint='index', view='core.views.index'),
        Rule('/upload', endpoint='upload', view=('core.views.UploadHandler', (), {})),
        Rule('/serve/<blob_key>', endpoint='serve', view=('core.views.ServeHandler', (), {})),
    )
]

core/templates/index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Top Page - core</title>
    </head>
    <body>
        <form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
            Upload File:<input type="file" name="file"><br>
            <input type="submit" name="submit" value="Submit">
        </form>

        <h2>Uploaded Files</h2>
        <ul>
            {% for file in files %}
            <li><a href="{{ url_for('core/serve', blob_key=file.key) }}">{{ file.filename }}</a></li>
            {% endfor %}
        </ul>
    </body>
</html>


Kay が提供している BlobstoreUploadHandler と BlobstoreDownloadHandler は、App Engine SDK が提供している同名のクラスを移植したものなので、使い方はほとんど同じです。


注意点を挙げるなら、redirect メソッドをを使わず、ステータスコードを指定したレスポンスを返すことで、リダイレクトしているところ。redirect メソッドはボディが書き込まれたレスポンスを返しますが、App Engine のアップロード用ハンドラでリダイレクトするときは、ボディが空じゃなきゃダメみたいです。