Каскадное удаление в приложениях GAE, NDB, Python

У меня есть приложение GAE, использующее хранилище данных NDB и python, которое назначает задачи сотрудникам. У меня есть объекты задач и объекты сотрудников, которые имеют массивы задач (хранящие ключи задач). Я пытаюсь реализовать «каскадное удаление», при котором я могу передать моей функции удаления ключ удаляемой задачи и «каскадировать» ее для объектов сотрудников, чтобы очистить ссылки на эту задачу. Прямо сейчас моя функция удаления задачи работает нормально, но она не каскадируется правильно. Когда я удаляю задачу и проверяю сотрудника, которому была назначена эта задача, ее значение ключа по-прежнему отображается. Я был бы очень признателен за любые указатели, которые кто-либо может предоставить!

Мои определения сущностей находятся в файле db_models с сущностями Task (состоящими только из имени в виде строки) и сущностями Employee, которые имеют массивы задач:

class Employee(ndb.Model):
    name = ndb.StringProperty(required=True)
    title = ndb.StringProperty(required=True)
    tasks = ndb.KeyProperty(repeated=True)

    def to_dict(self):
        d = super(Employee, self).to_dict()
        d['tasks'] = [m.id() for m in d['tasks']]
        return d    

Моя функция удаления, которой я передаю «сделал» или ключ объекта «Задача» для удаления

class TaskDelete(webapp2.RequestHandler):
    def get(self, **kwargs):
        if 'application/json' not in self.request.accept:
            webapp2.abort(406, details="Not Acceptable, API only supports application/json MIME type")
            return
        if 'did' in kwargs:
            entity = ndb.Key(db_models.Task, int(kwargs['did'])).delete()
        q = db_models.Employee.query()
        key = q.fetch(keys_only=True)
        for x in key:
            employee = ndb.Key(db_models.Employee, int(x.id())).get()
            for task in employee.tasks:
                if 'did' == task:
                    task.delete()
                    employee.put()

person ChristinaLindsay    schedule 23.04.2016    source источник
comment
если задачи — это список ключей, я не понимаю, почему вы сравниваете его со строкой «сделал»?   -  person marcadian    schedule 23.04.2016
comment
Извините, забыл добавить часть main.py, где я на самом деле вызываю вещь! Я использую curl для тестирования функций и сделал это, какой бы ключ я ни передал. Я вручную отслеживаю свои ключи задач прямо сейчас и передаю их напрямую. Это из моего основного app.router.add(webapp2.Route(r'/task/‹did:[0-9]+›‹:/?›/delete','task.TaskDelete'))   -  person ChristinaLindsay    schedule 23.04.2016
comment
Вы извлекаете сотрудников с помощью запроса, и если это произойдет вскоре после обновления, вы обнаружите, что возможная согласованность может означать, что у вас есть устаревшие значения. Чтобы доказать/опровергнуть это, извлеките объект, который вы обновили по его ключу, и посмотрите, является ли это проблемой.   -  person Tim Hoffman    schedule 23.04.2016
comment
Кроме того, даже если вы удаляете задачи, где вы удаляете задачи в Epmployee.tasks, это поле также необходимо обновить, чтобы отразить, что задача больше не существует. Простое удаление объекта не повлияет на экземпляры Employee, которые ссылаются на него.   -  person Tim Hoffman    schedule 23.04.2016


Ответы (1)


Во-первых, вы запрашиваете сотрудников по одному, а это очень медленно. Вместо:

    q = db_models.Employee.query()
    key = q.fetch(keys_only=True)
    for x in key:
        employee = ndb.Key(db_models.Employee, int(x.id())).get()

использовать:

    for employee in db_models.Employee.query():

Теперь вам просто нужно обновить свойство employee.tasks:

        for task in employee.tasks:
            if 'did' == task:
                task.delete()
                employee.tasks.remove(task)   # add this line
                employee.put()
                break                         # add this line too
person Brent Washburne    schedule 05.10.2016