2009-06-28 14 views
6

estoy usando Google App Engine con Django 1.0.2 (y el django-helper) y se preguntan cómo las personas van haciendo recursiva eliminar. Suponga que tiene un modelo que es algo como esto:eliminación recursiva en Google App Engine

 
class Top(BaseModel): 
    pass 

class Bottom(BaseModel): 
    daddy = db.ReferenceProperty(Top) 

Ahora, cuando se borra un objeto de tipo 'Top', quiero que todos los objetos 'bottom' asociados que se eliminarán también.

Como están las cosas ahora, cuando elimino un objeto 'Superior', los objetos 'Inferiores' se quedan y luego obtengo datos que no pertenecen a ningún lado. Al acceder al almacén de datos en una vista, termino con:

Caught an exception while rendering: ReferenceProperty failed to be resolved.

por supuesto que pude encontrar todos los objetos y eliminarlos, pero ya que mi modelo real es al menos 5 niveles de profundidad, estoy esperando que hay una manera para asegurarse de que esto se pueda hacer de forma automática.

He encontrado este article sobre cómo funciona con Java y eso parece ser lo que yo también quiero.

Alguien sabe cómo podría conseguir que el comportamiento en Django así?

Respuesta

6

Debe implementar esto manualmente, buscando los registros afectados y eliminándolos al mismo tiempo que elimina el registro primario. Puede simplificar esto, si lo desea, anulando el método .delete() en su clase principal para eliminar automáticamente todos los registros relacionados.

Por motivos de rendimiento, es casi seguro que desee utilizar consultas exclusivas (lo que le permite eliminar las claves de las entidades sin tener que buscar y descodificar las entidades reales), y elimina por lotes. Por ejemplo:

db.delete(Bottom.all(keys_only=True).filter("daddy =", top).fetch(1000)) 
+0

Fuera de interés, ¿db.delete llama a delete() en cada entidad? Está optimizado diabólicamente, entonces soy un poco sospechoso de que no puedes combinar estos dos trucos. Buen punto en keys_only, though. –

+0

No, db.delete() corresponde directamente a un solo RPC que envía todas las claves que se eliminarán en paralelo. Entity.delete() es simplemente azúcar sintáctica que llama a db.delete (self). –

+1

¿No funcionaría 'db.delete (top.bottom_set)'? –

2

hecho de que el comportamiento es GAE-específica. El ORM de Django simula "ON DELETE CASCADE" en .delete().

sé que esto no es una respuesta a su pregunta, pero tal vez le puede ayudar a buscar en los lugares equivocados.

1

Si su jerarquía es sólo un pequeño número de niveles de profundidad, entonces usted podría ser capaz de hacer algo con un campo que se parece a una ruta de archivo:

daddy.ancestry = "greatgranddaddy/granddaddy/daddy/" 
me.ancestry = daddy.ancestry + me.uniquename + "/" 

tipo de cosas. Necesitas nombres únicos, al menos únicos entre los hermanos.

La ruta en las ID de objetos ya lo hace de alguna manera, pero IIRC está vinculado a grupos de entidades, que se recomienda no usar para expresar relaciones en el dominio de datos.

Entonces puede construir una consulta para devolver todos los descendientes de granddaddy utilizando el truco inicial subcadena, así:

query = Person.all() 
query.filter("ancestry >", gdaddy.ancestry + "\U0001") 
query.filter("ancestry <", gdaddy.ancestry + "\UFFFF") 

Obviamente, esto no sirve de nada si no puede adaptarse a la ascendencia en un StringProperty 500 bytes .

2

Reconsidere la estructura de datos. Si la relación no va a cambiar en el curso de la vida de registro, usted podría utilizar "antepasados" característica de GAE:

class Top(db.Model): pass 
class Middle(db.Model): pass 
class Bottom(db.Model): pass 

top = Top() 
middles = [Middle(parent=top) for i in range(0,10)] 
bottoms = [Bottom(parent=middle) for i in range(0,10) for middle in middles] 

A continuación, las consultas a los antepasados ​​= parte superior encontrará todos los registros de todos los niveles.Por lo tanto, será fácil eliminarlos.

descendants = list(db.Query().ancestor(top)) 
# should return [top] + middles + bottoms 
+0

Hermoso. Buen uso de las listas de comprensión. ¡Mi primera vez viendo uno teniendo dos vueltas! Parece que estarían en el otro orden, sin embargo, con el bucle externo en primer lugar. –