Google App Engine Version 1.3.6の新機能

Google App Engine Version 1.3.6の新機能を開発環境で試しました。

サンプルコードはKay-Frameworkを使用しています。

(1)Results of datastore count() queries and offsets for all datastore queries are no longer capped at 1000.

データストアのクエリーとカウントの1000件の制限を解除されました。

データストアのクエリーとカウントの取得件数が1000件までに制限されていました。
この1000件の制限が解除されました。
CPUクオータとリクエスト時間の許す範囲でデータを取得できます。

QueryとGqlQueryの基底クラス(_BaseQuery)で、取得できる件数の初期値が1000件に設定されています。

class _BaseQuery(object):
  def count(self, limit=1000, **kwargs):

このため引数で制限を指定しない場合は、取得できる件数は従来と同じで1000件までです。

count = models.Comment.all().count() #=>最大1000

1000件以上取得したい場合は、引数で指定します。

count = models.Comment.all().count(99999) #=>最大99999

(2) Users can now serve custom static error pages for over_quota, dos_api_denial and default cases.

エラーページの設定が可能になりました。
参照:Custom Error Responses

app.yaml

error_handlers:
  # 標準のエラーページ
  - file: default_error.html

エラーごとに表示するエラーページを設定することもできます。

app.yaml

error_handlers:
  # 標準のエラーページ
  - file: default_error.html

  # リソースの割り当てを超えたとき
  - error_code: over_quota
    file: over_quota.html

  # DoS Protection
  - error_code: dos_api_denial:
    file: dos_api_denial.html

  # タイムアウトのとき
  - error_code: timeout:
    file: timeout.html

(3)Automatic image thumbnailing is now available in the Images API using get_serving_url().

get_serving_url()で画像のサイズ変更や切り抜きができるようになりました。
参照:get_serving_url(blob_key, size=None, crop=False)

Google App Engine 1.3.6 – Ian Lewis」によると、別のインフラを使うためにGoogleAppEngineのクオータの制限がかからないそうです。

以下のコードは、get_serving_url(blob_key, size=None, crop=False)を使用したサンプルコードです。
アップロードされ画像に対してサイズ変更したり、切り抜きをした画像のURLを作成します。

myapp/urls.py

view_groups = [
  ViewGroup(
    Rule('/', endpoint='index', view='myapp.views.index'),
    Rule('/upload', endpoint='upload', view=('myapp.views.UploadHandler', (), {})),
  )
]

myapp/views.py

from werkzeug import Response
from kay.utils import render_to_response, url_for
from kay.handlers import blobstore_handlers
from google.appengine.ext import blobstore
from google.appengine.api import images

def index(request):
    upload_url = blobstore.create_upload_url(url_for('myapp/upload'))
    blob_key = request.values.get('blob_key')
    d = {'upload_url': upload_url}
    if blob_key:
        from google.appengine.api.images import get_serving_url
        d['blob_key'] = blob_key
        # サイズ変更
        d['resize_url'] = get_serving_url(blob_key, 64)
        # 切り抜き
        d['crop_url'] = get_serving_url(blob_key, 160, True)

    return render_to_response("myapp/index.html", d)

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        # 'file' is file upload field in the form                                                                                                              
        upload_files = self.get_uploads('file')
        blob_info = upload_files[0]
        headers = {'Location': url_for('myapp/index', blob_key=blob_info.key())}
        return Response(None, headers=headers, status=302)

myapp/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 - myapp</title>
</head>
<body>

{% if blob_key %}
Upload succeeded.<br/>
<a href="{{ resize_url }}">View resizing</a><br />
<a href="{{ crop_url }}">View cropping</a><br />
{% endif %}

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

</body>
</html>

(4)Multitenancy is now supported in the datastore, allowing better compartmentalization of user data.

データストアの名前空間をサポートしました。
参照:Multitenancy and the Namespaces Python API – Google App Engine – Google Code

from google.appengine.api import namespace_manager
namespace = namespace_manager.get_namespace()

namespace_manager.set_namespace('A')  # 名前空間を「A」に設定
do_something() #名前空間「A」でデータストアを操作

namespace_manager.set_namespace('B')  # 名前空間を「B」に設定
do_something() #名前空間「B」でデータストアを操作

namespace_manager.set_namespace(namespace)  # 名前空間を元に戻す

以下のコードは、名前空間を使用したサンプルコードです。
名前空間(‘-global-‘, ‘foo’, ‘bar’)のいずれかのカウンターを1増加し、増加した名前空間とカウンターの値を表示します。

myapp/views.py

from werkzeug import Response
from kay.utils import render_to_response, url_for
from google.appengine.ext import db
from google.appengine.api import namespace_manager
import random

class Counter(db.Model):
    """カウンター"""
    count = db.IntegerProperty()

def update_counter(name):
    """nameのカウンターを1増加する"""
    def _update_counter(name):
        counter = Counter.get_by_key_name(name)
        if counter is None:
            counter = Counter(key_name=name);
            counter.count = 1
        else:
            counter.count = counter.count + 1
        counter.put()
        return counter.count
    return db.run_in_transaction(_update_counter, name)

def index(request):
    """
    名前空間('-global-', 'foo', 'bar')のいずれかのカウンターを1増加し、
    増加した名前空間とカウンターの値を表示する
    """
    # 名前空間のリスト
    ns_list = ('-global-', 'foo', 'bar')
    # 名前空間のリストからランダムに取得
    d = {'ns': random.choice(ns_list)}
    # 現在の名前空間
    namespace = namespace_manager.get_namespace()
    try:
        # 編集するデータストアの名前空間を設定
        namespace_manager.set_namespace(d['ns'])
        # カウンターを増加して結果を取得
        d['count'] = update_counter('SomeRequest')
    finally:
        # 名前空間を元に戻す
        namespace_manager.set_namespace(namespace)
    return render_to_response('myapp/index.html', d)

myapp/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 - myapp</title>
</head>
<body>
<p>namespace = {{ns}}</p>
<p>count = {{count}}</p>
</body>
</html>

(5)Added a pause queue button to the task queue details page in the Admin Console.

管理画面の「Task Queues」に「Pause Queue」ボタンが追加されました。

(6)Historical graphs have been added to all of the dashboard graphs in the Admin Console.


このボタンが追加された?

(7)New method to allocate datastore ids in a given range: db.allocate_id_range().

与えられた範囲でデータストアのidを割り当てる新しいメソッド db.allocate_id_range() が追加されました。
参照:db.allocate_id_range()

(8)New db method is_in_transaction() determines if a transaction is still open.

トランザクション中かどうかを取得する新しいメソッド db.is_in_transaction() が追加されました。
参照:db.is_in_transaction()

(9)Increased several rate limited quotas for free applications.

無料枠が増えました。

(10) Remote API now supports the Blobstore API.

リモートAPIが新しくBlobstore APIをサポートしました。

(11) Content-range headers are supported on Blobstore downloads.

英語には自信がありません。(汗
間違いがあれば教えてください。

コメント

  1. Pingback: Google App Engine バージョン1.3.6リリース « 山本隆の開発日誌

  2. 同じようにUploadHandlerを使って、Blob_storeに登録するとともに、他のData_Storeにも登録したいです。
    例えば
    files = self.get_uploads(‘file_name’)
    if self.request:
    files = self.get_uploads(‘file_name’)
    blob_info = files[0]
    setData= employee(employee_no = self.request.values.get(‘employee_no’), #画面中の項目
    employee_name = self.request.values.get(‘employee_name’),
    blob_key = str(blob_info.key()),
    )
    setData.put()
    でもローカルで問題ないですが、appspotに文字ばけになっています。原因を教えていただけませんか。。。

  3. 山本様
    ご返事ありがとうございました。
    原因が分かりました、それがGoogleの問題そうです。下記Googleディスカッションに情報があります。
    (http://groups.google.com/group/google-app-engine-japan/browse_thread/thread/6df5a80f70d0d1fa)
    いずれにしてもどうもありがとうございます!

  4. Pingback: GAEに於いてcount()で1,000件以上を取得する | Acenumber Technical Issue

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です