Рекурсивное удаление в Google App Engine - PullRequest
6 голосов
/ 28 июня 2009

Я использую google app engine с django 1.0.2 (и django-helper) и удивляюсь, как люди делают рекурсивное удаление. Предположим, у вас есть модель, похожая на эту:

class Top(BaseModel):
    pass

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

Теперь, когда я удаляю объект типа «Top», я хочу, чтобы все связанные с ним объекты «Bottom» также были удалены.

Как сейчас, когда я удаляю объект Top, объекты Bottom остаются, а затем я получаю данные, которые нигде не принадлежат. При доступе к хранилищу данных в представлении я получаю:

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

Конечно, я мог бы найти все объекты и удалить их, но поскольку моя настоящая модель имеет глубину не менее 5 уровней, я надеюсь, что есть способ убедиться, что это можно сделать автоматически.

Я нашел эту статью о том, как она работает с Java, и, похоже, это тоже почти то, чего я хочу.

Кто-нибудь знает, как я могу получить такое поведение и в django?

Ответы [ 4 ]

6 голосов
/ 29 июня 2009

Вам необходимо реализовать это вручную, просматривая затронутые записи и удаляя их одновременно с удалением родительской записи. При желании вы можете упростить это, переопределив метод .delete () в родительском классе для автоматического удаления всех связанных записей.

По соображениям производительности вы почти наверняка захотите использовать запросы только для ключей (позволяющие получать ключи сущностей, которые нужно удалить без необходимости извлекать и декодировать действительные сущности), а также групповое удаление. Например:

db.delete(Bottom.all(keys_only=True).filter("daddy =", top).fetch(1000))
2 голосов
/ 02 августа 2014

Пересмотреть структуру данных. Если отношение никогда не изменится в течение времени жизни записи, вы можете использовать функцию «предков» 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]

Тогда запрос ancestor = top найдет все записи со всех уровней. Так что их будет легко удалить.

descendants = list(db.Query().ancestor(top))
# should return [top] + middles + bottoms
2 голосов
/ 28 июня 2009

На самом деле это поведение зависит от GAE. ORM Джанго имитирует «УДАЛИТЬ КАСКАД» на .delete ().

Я знаю, что это не ответ на ваш вопрос, но, возможно, он может помочь вам смотреть в неправильных местах.

1 голос
/ 28 июня 2009

Если ваша иерархия имеет небольшое количество уровней, то вы можете сделать что-то с полем, которое выглядит как путь к файлу:

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

такие вещи. Вам нужны уникальные имена, по крайней мере, уникальные среди братьев и сестер.

Путь в идентификаторах объектов вроде этого уже делает, но IIRC, связанный с группами сущностей, которые рекомендуется не использовать для выражения отношений в области данных.

Затем вы можете создать запрос для возврата всех потомков дедушки, используя начальный трюк с подстрокой, например:

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

Очевидно, что это бесполезно, если вы не можете вписать происхождение в 500-байтовый StringProperty.

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