I found a solution on my own, and it's a doozy. If anyone can think of something a bit less ugly, let me know. The reason why the global variables are lists is to keep Python from trying to rebind the names as local variables inside the functions on assignment (the very behaviour that makes closures ugly to do in Python - one of the few things that annoy me about Python).
This one's a beaut. It combines the code to delete the whole tree with the code to save the parent keys if necessary by listening to pre_delete. What it does is keep track of the id of the last SubKeyRing it tried to kill... when the SubKeyRing tries to commit matricide, Mom tries to kill it, naturally, which results in it trying to kill Mom in an endless loop, but since we keep track of the last SubKeyRing that tried to be killed, we only let that go on for one cycle. When we detect the endless cycle of violence, we stash away the id of the parent key. We also listen to post_delete for both kinds of keys, and if the id of the key that was just deleted matches the id of a parent that should not have been deleted, we set the subkeyring to None and save the instance, basically putting it back in the database. Anyway: from django.db.models import signals subkeyring_tried_to_kill = [None] put_root_key_back = [None] put_sub_key_back = [None] def delete_subkeyring(sender, instance, **kwargs): if instance.subkeyring: if instance.subkeyring.id == subkeyring_tried_to_kill[0]: if isinstance(instance, SubKey): put_sub_key_back[0] = instance.id else: put_root_key_back[0] = instance.id else: subkeyring_tried_to_kill[0] = instance.subkeyring.id instance.subkeyring.delete() def return_parent(sender, instance, **kwargs): if isinstance(instance, SubKey): if instance.id == put_sub_key_back[0]: instance.subkeyring = None instance.save() put_sub_key_back[0] = None elif instance.id == put_root_key_back[0]: instance.subkeyring = None instance.save() put_root_key_back[0] = None signals.pre_delete.connect(delete_subkeyring, sender=RootKey) signals.pre_delete.connect(delete_subsubkeyring, sender=SubKey) signals.post_delete.connect(return_parent, sender=RootKey) signals.post_delete.connect(return_parent, sender=SubKey) On Nov 30, 10:26 am, stevedegrace <[EMAIL PROTECTED]> wrote: > Another problem! I'm using Django 1.0.2, Python 2.5.2, on Ubuntu 8.10. > > I have a structure of keys and keyrings arranged in a tree of > arbitrary depth which I decided to implement as a bunch of models: > RootKeyRing, RootKey, SubKeyRing, SubKey (rather than as XML like > maybe I should have done) because I wanted to use the Admin interface > with it and not manually edit XML or write a special admin. > > A SubKey has a ForeignKey which is a SubKeyRing to which it must > belong, and a OneToOneField with attributes blank=True and null=True > which is a SubKeyRing it may optionally point to. That all works > great. The problem comes when I go to delete a SubKeyRing. > > The desired behaviour is for all of the SubKeyRing's SubKeys to die, > and it does that (the case of killing any SubKeyRings that belong to > the SubKeys is handled by using the pre_delete signal, and not the > problem right now). However, it has an unpleasant side effect - it > also kills its parent key, which is pointing to it with the > OneToOneField, even though that field is allowed to be none. > > I understand it is doing this because OneToOneField is based off of > ForeignKey - but what I would like to have happen is to set the > OneToOneField to None instead of deleting the parent key. Is there > some way to suppress the delete cascade behaviour for a relation? I > tried connecting a function to the pre_delete signal for the > SubKeyRing and just setting the parent_key to None, but it tries to > delete the parent key anyway and raises an AttributeError, so that's > not going to cut it. > > Any ideas? I would rather suppress the delete cascade behaviour than > restructure my models because aside from this one problem, I really > like the structure I'm using and don't want to refactor it. > > Thanks, > > Stephen --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---