2012-07-21 21 views
5

Mi pregunta es, ¿cuál es la mejor manera de crear una nueva entidad de modelo, y luego leerla inmediatamente después? Por ejemplo,¿Cómo puedo crear una nueva entidad de modelo y luego leerla inmediatamente después?

class LeftModel(ndb.Model): 
    name = ndb.StringProperty(default = "John") 
    date = ndb.DateTimeProperty(auto_now_add=True) 

class RightModel(ndb.Model): 
    left_model = ndb.KeyProperty(kind=LeftModel) 
    interesting_fact = ndb.StringProperty(default = "Nothing") 

def do_this(self): 
    # Create a new model entity 
    new_left = LeftModel() 
    new_left.name = "George" 
    new_left.put() 

    # Retrieve the entity just created 
    current_left = LeftModel.query().filter(LeftModel.name == "George").get() 

    # Create a new entity which references the entity just created and retrieved 
    new_right = RightModel() 
    new_right.left_model = current_left.key 
    new_right.interesting_fact = "Something" 
    new_right.put() 

Esto a menudo se produce una excepción como:

AttributeError: 'NoneType' object has no attribute 'key' 

es decir, la recuperación de la nueva entidad LeftModel no tuvo éxito. He enfrentado este problema varias veces con appengine y mi solución siempre ha sido un poco hacky. Usualmente pongo todo en un intento excepto o un ciclo while hasta que la entidad se recupera con éxito. ¿Cómo puedo asegurarme de que la entidad modelo siempre se recupera sin correr los riesgos de bucles infinitos (en el caso del bucle while) o estropear mi código (en el caso de las declaraciones try except)?

+1

simplemente configure una clave para LeftModel al momento de la creación en lugar de usar la que se generó automáticamente. –

+1

+1 problema bien establecido – msw

Respuesta

9

¿Por qué intenta obtener el objeto mediante una consulta inmediatamente después de haber realizado el put()?

Se debe utilizar la new_left que acaba de crear y de inmediato asignarlo al new_right como en new_right.left_model = current_left.key

La razón por la que no se puede consultar de inmediato se debe a HRD utiliza un modelo de consistencia eventual, lo que significa que resultado de la put ser visible eventualmente. Si desea un resultado coherente, debe realizar consultas de antecesores y esto implica un antecesor en la clave de la creación. Dado que estás creando un árbol, esto probablemente no sea práctico. Lea sobre Estructuración de datos para una consistencia fuerte https://developers.google.com/appengine/docs/python/datastore/structuring_for_strong_consistency

No veo ningún motivo por el que simplemente no utilice la entidad que acaba de crear sin la consulta adicional.

+0

+1 Para amplificar: "¿cómo lo leo inmediatamente después?" no puede, ese no es un objetivo de diseño de NDB y hay buenas razones para que no esté disponible de inmediato. – msw

+7

Para aclarar: esa razón no tiene nada que ver con NDB: la semántica de consulta de HRD se implementa en el back-end. NDB solo pasa las malas noticias. (En cuanto a por qué el OP está intentando esto: mis conjeturas son tan buenas como cualquier otra, pero espero que el ejemplo se simplifique en comparación con el código real donde sucedió esto, y/o están escribiendo algún tipo de prueba, también tal vez estaban traduciendo expresiones idiomáticas de SQL a App Engine). –

Cuestiones relacionadas