Подтвердить что ты не робот

Можно ли определить с помощью NDB, если модель устойчива в хранилище данных или нет?

Я перемещаюсь от db.Model до ndb.Model. Единственная проблема, которую я должен решить, прежде чем завершить эту миграцию, заключается в том, что нет метода Model.is_saved. Я использовал db.Model.is_saved в своем приложении, чтобы определить, должны ли обновляться оверенные счетчики на put/delete, чтобы проверить конфликтующие ключи при создании объектов и т.д.

В документации указано, что ndb.Model не имеет эквивалента для метода is_saved. Я могу переопределить некоторые варианты использования get_or_insert вместо is_saved. Но не все из них.

Как грязный хак, я могу установить флаг как _in_memory_instance для каждого экземпляра, который я создал, вызвав конструктор. Но это не решает мою проблему. Я все равно должен обновить этот флаг, по крайней мере, после каждого вызова put().

Возникает вопрос: существует ли лучший способ определить, является ли модель постоянной в хранилище данных или нет без дополнительного удаления хранилища данных?

Изменить 1: Забыл упомянуть: все сущности получили ключи, поэтому проверка на Model._has_complete_key() не работает для меня.

Изменить 2: после этого обсуждения https://groups.google.com/d/topic/google-appengine/Tm8NDWIvc70/discussion кажется, что единственный способ решить мою проблему - использовать _post_get_hook/_post_put_hook. Мне интересно, почему такая тривиальная вещь не была включена в официальный API.

Edit 3: Я закончил с базовым классом для всех моих моделей. Теперь я могу оставить свою кодовую базу (почти) нетронутой:

class BaseModel(ndb.Model):

    @classmethod
    def _post_get_hook(cls, key, future):
        self = future.get_result()
        if self:
            self._is_saved = bool(key)

    def _post_put_hook(self, future):
        self._is_saved = future.state == future.FINISHING

    def is_saved(self):
        if self._has_complete_key():
            return getattr(self, "_is_saved", False)
        return False
4b9b3361

Ответ 1

Чтобы получить такое же состояние в NDB, вам понадобится комбинация пост-крюк и пост-крючок для установки флага. Здесь работает Пример:

class Employee(ndb.Model):
  <properties here>

  saved = False  # class variable provides default value

  @classmethod
  def _post_get_hook(cls, key, future):
    obj = future.get_result()
    if obj is not None:
      # test needed because post_get_hook is called even if get() fails!
      obj.saved = True

  def _post_put_hook(self, future):
    self.saved = True

Нет необходимости проверять статус будущего - когда либо крюк называется, будущее всегда имеет результат. Это связано с тем, что hook на самом деле является обратным вызовом в будущем. Однако существует необходимость проверьте, нет ли его результата None!

PS: внутри транзакции крючки вызываются, как только вызов put() возвращается; успех или неудача транзакции не влияют на них. См. https://developers.google.com/appengine/docs/python/ndb/contextclass#Context_call_on_commit для способа запуска крюка после успешной фиксации.

Ответ 2

Основываясь на идее @Tim Hoffmans, вы можете сделать так:

class Article(ndb.Model):
    title = ndb.StringProperty()

    is_saved = False

    def _post_put_hook(self, f):
        if f.state == f.FINISHING:
            self.is_saved = True
        else:
            self.is_saved = False


article = Article()
print article.is_saved ## False
article.put()
print article.is_saved ## True

Я не могу гарантировать, что он сохраняется в хранилище данных. Не нашел ничего об этом в google:)

На стороне нет, глядя на то, что экземпляр ndb.Model имеет ключ, вероятно, не будет работать, поскольку новый экземпляр, похоже, получит ключ до его отправки в хранилище данных. Вы можете посмотреть исходный код, чтобы узнать, что происходит, когда вы создаете экземпляр класса ndb.Model.