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

Kay Framework でも Blobstore を使ってみる

先日、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 のアップロード用ハンドラでリダイレクトするときは、ボディが空じゃなきゃダメみたいです。