Как переписать метод put () в модели движка приложения Python? - PullRequest
6 голосов
/ 27 сентября 2011

В Appengine я пытаюсь автоматически рассчитать значение свойства и сохранить его вместе с объектом.

У меня есть класс 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() непосредственно к объекту Area:

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

Как правильно «подсунуть» вычисленное значение?

Ответы [ 2 ]

7 голосов
/ 28 сентября 2011

Не переопределяйте put - как вы заметили, он хрупок и не вызывается, если вы вызываете db.put вместо функции put модели.

К счастью, App Engine предоставляет ComputedProperty, что делает ваш вариант использования действительно простым:

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

    @db.ComputedProperty
    def area(self):
      return self.width * self.height
1 голос
/ 08 июня 2013

Я согласен, что 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:312 -- UserData.<put>

Где 3041 - количество раз, когда строка 312 activity_summary.py выдает UserData.put().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...