2011-09-27 20 views
6

Appengineでは、私はプロパティ値を自動的に計算し、オブジェクトと共に保存しようとしています。pythonアプリケーションエンジンモデルでput()メソッドを上書きする方法はありますか?

私はクラスRectangleを持っており、幅、高さ、面積を持っています。明らかに、この領域は幅と高さの関数ですが、ソートに使用したいので、これをプロパティにします。だから私はそうのような矩形を格納する際に面積をこっそりPUT()関数を変更しよう:

class Rectangle(db.Model): 
    width = db.IntegerProperty() 
    height = db.IntegerProperty() 
    area = db.IntegerProperty() 

    def put(self, **kwargs): 
     self.area = self.width * self.height 
     super(Rectangle, self).put(**kwargs) 

私は直接エリアオブジェクトにput()を呼び出すとき、これは動作します:

re1 = Rectangle(width=10, height=10) 
re1.put() 
print re1.area  # >> 10 

しかしとき私はdb.put()を使います(例えば、一度にたくさんのものを保存するなど)、これが壊れます。

re2 = Rectangle(width=5, height=5) 
db.put(re2) 
print re2.area  # >> None 

計算された値を「入れる」適切な方法は何ですか?

+0

データベースからアイテムを取得するとどうなりますか?計算された面積ですか? – rocksportrocker

+0

データストアをチェックしたところ、データストアは同じです。最初の矩形は '10'、2番目の矩形は' None'です。 – Paul

+1

私は 'db.put()'があなたのオブジェクトの個々の 'put()'メソッドを決して呼び出さないと思っています。おそらくデータベースのプロパティを調べて、一括挿入ステートメントを作成します。 'put'ではなく' __init__'で領域を設定すると、どうなりますか? – larsks

答えて

7

putをオーバーライドしないでください。観察すると壊れやすく、モデルのput関数の代わりにdb.putを呼び出すと呼び出されません。

幸いなことに、App Engineはあなたのユースケースは、本当に簡単になりComputedPropertyを提供しています。

class Rectangle(db.Model): 
    width = db.IntegerProperty() 
    height = db.IntegerProperty() 

    @db.ComputedProperty 
    def area(self): 
     return self.width * self.height 
+0

ありがとう、それは魅力のように動作します! – Paul

1

私はComputedPropertyが記載された特定のシナリオに進むべき道であることに同意します。ただし、put関数のオーバーロードには依然として役立つ可能性があります。たとえば、次のコードを使用して、データストアの書き込みを発行しているすべての呼び出し元を追跡し、書き込みのスパイクを簡単にデバッグできるようにします。

from google.appengine.ext import db 

_orig_db_put_async = db.put_async 
_orig_db_model_put = db.Model.put 

def _new_db_put_async(models, *args, **kwargs): 
    """Instrumented version of db.put_async (which db.put also calls).""" 
    retval = _orig_db_put_async(models, *args, **kwargs) 
    msg = ['query: %s' % _get_caller()] 
    # 'models' can be either a single model instance, or a list of them. 
    try: 
     for model in models: 
      msg.append(model.__class__.__name__ + '.<db.put>') 
    except TypeError: 
     msg.append(models.__class__.__name__ + '.<db.put>') 
    instance_cache.increment(' -- '.join(msg)) 
    return retval 


def _new_db_model_put(self, *args, **kwargs): 
    """Like entity.put() but stores put-stats in the instance cache.""" 
    retval = _orig_db_model_put(self, *args, **kwargs) 
    msg = ['query: %s' % _get_caller()] 
    msg.append(self.__class__.__name__ + '.<put>') 
    instance_cache.increment(' -- '.join(msg)) 
    return retval 

このコードはコードパスがmemcacheので書き込みを発行しているのカウントを保持して、時折、ログにそれを洗い流します。 3041は回数がactivity_summary.pyの312UserData.put()を発行したラインです

3041: activity_summary.py:312 -- UserData.<put>

:ログの行は次のようになり。

関連する問題