Massimo,
I created a small test to try your function:
db.define_table('carrier',
Field('name', type='string'),
Field('description', type='string')
)
db.carrier.name.requires = IS_NOT_IN_DB(db(db.carrier.id > 0),
'carrier.name')
db.define_table('manufacturer',
Field('name', type='string'),
Field('country', type='string')
)
db.manufacturer.name.requires = IS_NOT_IN_DB(db(db.manufacturer.id > 0),
'manufacturer.name')
db.define_table('phone',
Field('model', type='string'),
Field('manufacturer', db.manufacturer),
Field('carrier', db.carrier)
)
db.phone.manufacturer.requires = IS_IN_DB(db, 'manufacturer.id', '%(name)s')
db.phone.carrier.requires = IS_IN_DB(db, 'carrier.id', '%(name)s')
def delete_linked(query, table=db.carrier):
ids = [t.id in db(query).select(db.table.id)]
for field in table._referenced_by:
db(field._table._id.belongs(ids)).delete()
db.carrier._before_delete.append(delete_linked)
I can create an Apple iPhone on Verizon and an Apple iPhone on Sprint. If
I run this under sqlite and I delete the carrier 'Sprint' I see one of the
phones deleted as well (even without the '_before_delete' event which makes
sense since that's the default behavior).
However if I run this under GAE:
- Without the '_before_delete' event the carrier 'Sprint' is deleted but
not the phone. This is expected since cascading doesn't work.
- With the '_before_delete' event (code just as above) *nothing* gets
deleted, not even the carrier. I can see it disappear from the list but if
I refresh the page it comes right back. I can also verify the record is
still there by looking at the GAE admin page (Datastore viewer). Also,
none of the phones are deleted either.
Am I missing something?
Also, when you say that if I delete too many records the operation may fail
midway... is that a GAE limitation? Is the 1000 record limit I've read
somewhere about?
Thanks,
Julian
On Saturday, November 17, 2012 1:06:01 PM UTC-6, Massimo Di Pierro wrote:
>
> You can try something like
>
> def delete_linked(query, table=table):
> ids = [t.id in db(query).select(db.table.id)]
> for field in table._referenced_by:
> db(field._table._id.belongs(ids)).delete()
>
> db.table._before_delete.append(delete_linked)
>
> but you will run into consistency problems. If there are too many records
> this may fail midway.
>
> On Wednesday, 14 November 2012 19:07:02 UTC-6, Julian Sanchez wrote:
>>
>> Hi Everyone!! Long time lurker & first time posting...
>>
>> I am working on a simple application that I intend to deploy in GAE. I
>> have a few tables with fields that reference other tables which by default
>> enables the ondelete=CASCADE behavior. This works fine when I run the app
>> locally using sqlite as the database.
>> I believe GAE doesn't support cascading deletes natively.
>> I presume web2py doesn't support cascading deletes when running under GAE
>> because I don't see that happening. When I delete a row (rendered through
>> SQLFORM.grid) only that row is deleted an all dependent tables remain
>> untouched.
>>
>> The problem I have is that I can't find a way for me to implement the
>> cascading behavior manually. I added a 'ondelete=mydelete' event for the
>> SQLFORM.grid where I do the manual delete of the dependent tables and
>> commit in the database, but that doesn't seem to work either. I searched
>> through this forum but didn't find any suggestions either. Any suggestions
>> as to what could I do to solve this?? Do I have to stay away from
>> SQLFORM.grid to avoid this problem?
>>
>> Many Thanks!!
>> Julian
>>
>> I am using web2py Version 2.2.1 (2012-10-21 16:57:04) stable on OS X
>> Mountain Lion and GoogleAppEngineLauncher version 1.7.3 (1.7.3.333)
>>
>
--