2011年2月1日火曜日

Kay OwnerProperty定義とエラーについて

Kayには kay.db.OwnerProperty という現在のユーザー情報を簡単に DataStore へ登録できるクラスが用意されている。

使い方は簡単。モデル定義でユーザー情報を格納したいフィールドに、OwnerProperty() を定義するだけである。
from google.appengine.ext import db
from kay.db import OwnerProperty
 
class Comment(db.Model):
    user = OwnerProperty()
    created = db.DateTimeProperty(auto_now_add=True)
    body = db.TextProperty(required=True)

モデルフォームを利用する場合は、forms.py で fields もしくは exclude で OwnerProperty で定義したフィールドを除外する。
from kay.utils.forms.modelform import ModelForm
from myapp.models import Comment
 
class CommentForm(ModelForm):
    class Meta:
        model = Comment
        fields = ('body')
参考:Kayドキュメント 21.1.5. 自動的に現在のユーザーをプロパティに保存する


OwnerPropertyを使用した時に次のようなエラーが出る場合がある。

DuplicatePropertyError: Class MyUser already has property Comment_set
※ MyUser は GoogleUserクラスを継承したモデルクラス、settings.pyのAUTH_USER_MODELにもMyUserを設定している。


エラーは、同じクラス内の複数のフィールドに OwnerProperty で定義した場合、後方参照プロパティの名前が重複することが原因となっている。一旦複数の OwnerProperty フィールドを定義して、一つを残して削除した場合も同じエラーが出ることがある。

OwnerPropertyクラスは google.appengine.ext.db の ReferencePropertyを継承している。このプロパティでは後方参照という機能があり、後方参照プロパティとして Comment_set(モデルクラス名+_set)が自動定義される。このため複数フィールドの OwnerProperty 定義があると名前が衝突するためエラーが発生する。

このエラーの解決策としては、 collection_name としてユニークな名前を定義してあげれば良い。先のモデル定義では次のように設定する。
from google.appengine.ext import db
from kay.db import OwnerProperty
 
class Comment(db.Model):
    user = OwnerProperty(collection_name = "Comment_set_01")
    created = db.DateTimeProperty(auto_now_add=True)
    body = db.TextProperty(required=True)
参考:Google App Engine  (「プロパティと型」の参照の項目に後方参照の説明がある)