ChristinaLindsay
ChristinaLindsay

Reputation: 35

"Cascading delete" on GAE, NDB, Python app

I have a GAE app using NDB datastore and python which assigns tasks to employees. I have Task Entities and Employee Entities which have arrays of Tasks (storing the tasks' keys). I am trying to implement a "cascading delete" where I can pass my delete function the key of the task to delete, and have it "cascade" to employee entities to clean up references to that task. Right now my delete task function works fine but it does not cascade correctly. When I delete a task and check out an employee who has been assigned that task, its key value still shows. I would greatly appreciate any pointers anyone can provide!

My entity definitions are in a db_models file, with Task entities (consisting only of name as a string) and Employee entities which have arrays of tasks:

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    

My delete function, which I am passing the 'did' or the key of the Task entity to delete

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()

Upvotes: 1

Views: 282

Answers (1)

Brent Washburne
Brent Washburne

Reputation: 13158

First of all, you are requesting Employees one at a time and that is very slow. Instead of:

    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()

use:

    for employee in db_models.Employee.query():

Now you simply need to update your employee.tasks property:

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

Upvotes: 1

Related Questions