ここでブランドンの答えに基づいて構築します。
可能であれば、Pythonファイルですべてのアチーブメントを定義する方がはるかに高速であるため、アチーブメントはメモリ内にあり、データベースをフェッチする必要はありません。これも実装が簡単です。
class StaticAchievement(object):
"""
An achievement defined in a Python file.
"""
by_name = {}
by_index = []
def __init__(self, name, description="", picture=None):
if picture is None: picture = "static/default_achievement.png"
StaticAchievement.by_name[name] = self
StaticAchievement.by_index.append(self)
self.index = len(StaticAchievement.by_index)
# This automatically adds an entry to the StaticAchievement.by_name dict.
# It also adds an entry to to the StaticAchievement.by_index list.
StaticAchievement(
name="tied your shoe",
description="You successfully tied your shoes!",
picture="static/shoes.png"
)
次に、各プレーヤーの実績のIDをdb.StringListPropertyに保持するだけです。プレーヤーのオブジェクトをロードした場合、アチーブメントをレンダリングするために追加のデータベースルックアップは必要ありません。すでにIDを持っているので、StaticAchievement.allでそれらをルックアップする必要があります。これは実装が簡単で、どのユーザーが特定の成果を上げているかなどを簡単に照会できます。他に何も必要ありません。
ユーザーがアチーブメントを所有していることに関連する追加データ(たとえば、アチーブメントが取得された日付)が必要な場合は、次のアプローチを選択できます。
1:同じ長さの別のListPropertyに格納します。
これにより、実装の単純さとプロパティのインデックス作成が維持されます。ただし、この種の解決策は、すべての人の好みに合うわけではありません。このデータの使用をより面倒にする必要がある場合は、次のようにプレーヤーオブジェクトにメソッドを記述します。
def achievement_tuples(self):
r = []
for i in range(0, len(self.achievements)):
r.append( (self.achievements[i], self.achievement_dates[i]) )
return r
整数の並列ListPropertyを維持し、ユーザーが進行したときにそれらの整数をインクリメントすることで、進行状況を処理できます。
データがどのように表現されるかを理解できる限り、その表現を必要なメソッドの背後に簡単に隠すことができます。これにより、必要なインターフェイスと、必要なパフォーマンスおよびインデックス付けの特性の両方を実現できます。ただし、インデックス作成が本当に必要でなく、リストが気に入らない場合は、オプション#2を参照してください。
2:追加データをBlobPropertyに保存します。
これには、データのシリアル化と逆シリアル化が必要であり、listpropertiesの優れたクエリをあきらめますが、並列リストの概念が嫌いな場合は、おそらくもっと幸せになるでしょう。これは、App Engineの方法とは異なり、Pythonの方法で物事を実行したいときに人々が行う傾向があることです。
3:追加データをデータベースに保存します
(たとえば、Achievement IDのStringProperty、DateProperty、およびUserPropertyの両方を含むPlayersAchievementオブジェクト、およびPlayersAchievementオブジェクトへの参照でいっぱいのachivementsリストプロパティ)
プレイヤーは潜在的に多数のアチーブメントを取得することが予想されるため、このオーバーヘッドは急速に悪化します。memcache、事前にレンダリングされたHTMLのブロブやタプルのシリアル化されたリストなどの中間データの保存、タスクの設定など、それを回避するのは非常に複雑になります。これは、アチーブメントの定義が必要な場合に実行する必要がある種類の作業でもあります。それ自体を変更可能/DBに保存します。