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
-~----------~----~----~----~------~----~------~--~---

Reply via email to