¿Es posible determinar con NDB si el modelo es persistente en el almacén de datos o no?

Estoy en proceso de migración de db.Model a ndb.Model . El único problema que tengo que resolver antes de finalizar esta migración es que no hay Model.is_saved método Model.is_saved . He usado db.Model.is_saved en mi aplicación para determinar si los contadores fragmentados deben actualizarse en put / delete , para verificar si hay claves en conflicto en la creación de entidades, etc.

La documentación dice que ndb.Model no tiene equivalente para el método is_saved . Puedo get_or_insert a get_or_insert algunos casos de uso con get_or_insert lugar de is_saved . Pero no todos ellos.

Como truco sucio, puedo establecer una _in_memory_instance como _in_memory_instance para cada instancia que he creado al llamar al constructor. Pero no resuelve mi problema. Todavía tengo que actualizar esta bandera al menos después de cada llamada put() .

La pregunta es: ¿existe una mejor manera de determinar si el modelo es persistente en el almacén de datos o no sin el golpe adicional del almacén de datos?

Edición 1: olvidé mencionar: todas las entidades obtuvieron las claves, así que verifique que Model._has_complete_key() no funcione para mí.

Edición 2: después de esta discusión https://groups.google.com/d/topic/google-appengine/Tm8NDWIvc70/discussion , parece que la única forma de resolver mi problema es usar _post_get_hook / _post_put_hook . Me pregunto por qué una cosa tan trivial no se incluyó en la API oficial.

Edición 3: Terminé con la siguiente clase base para todos mis modelos. Ahora puedo dejar mi código base (casi) intacto:

 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 

Para obtener el mismo tipo de estado en NDB, necesitaría una combinación de post-get-hook y post-put-hook para establecer una bandera. Aquí hay un ejemplo de trabajo:

 class Employee(ndb.Model):  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 

No hay necesidad de verificar el estado del futuro: cuando se llama a cualquiera de los ganchos, el futuro siempre tiene un resultado. Esto es porque el gancho es en realidad una callback en el futuro. Sin embargo, es necesario comprobar si el resultado es Ninguno.

PD: Dentro de una transacción, los enlaces se llaman tan pronto como se devuelve la llamada put (); El éxito o el fracaso de la transacción no les afecta. Consulte https://developers.google.com/appengine/docs/python/ndb/contextclass#Context_call_on_commit para ver una manera de ejecutar un gancho después de una confirmación exitosa.

Basado en la idea de @Tim Hoffmans puedes hacer un gancho de publicación así:

 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 

No puedo garantizar que haya persistido en el almacén de datos. No encontré nada al respecto en google 🙂

En un lado no, mirar para ver si una instancia de ndb.Model tiene una clave probablemente no funcionará ya que una nueva instancia parece obtener una clave antes de que se envíe al almacén de datos. Puede mirar el código fuente para ver qué sucede cuando crea una instancia de la clase ndb.Model.