views:

160

answers:

2

I am using Django admin for managing my data. I have the following tables: Users, Groups, and Domains. Users has a many-to-many relationship with both Groups and Domains. Domains has a one-to-many relationship with Groups. When I remove a User from a Domain, I also want to remove any entries in Users_Groups for that particular User and Groups belonging to the Domain.

How do I do this? Where do I put the code?

Thanks.

+1  A: 

The Django book (specifically, Appendix B) seems to suggest you override the delete method on the User model class and have it trigger the extra deletes.

Hank Gay
+1  A: 

I would suggest overriding save, but I'm guessing you're using the django.contrib.auth.User object. In that case, you can accomplish about the same thing with a pre_save signal:

def manage_domains(signal,**kwargs):
    if kwargs.has_key('instance'):
        instance = kwargs['instance']
    else: return
    old_instance = User.objects.get(pk=instance.pk)
    instance_categories = instance.categories.all()
    for group in old_instance.groups.all():
        if group not in instance_categories:
            instance.groups.clear()
pre_save.connect(manage_domains, sender=User)

This is not even close to an efficient solution. What will happen is that when a User object is saved, the above changes will be made to the object in memory, then the save will overwrite the object in the database. You've gone to the trouble not only of hitting the database to find out if the unmodified version of the object agrees with with what you're about to save, but you're also looping through two category sets, both requiring a database hit to load.

The best way to make an efficiency improvement here would be to subclass the ManyToMany field manager itself, because that's what's paying attention to changes as they occur in memory, rather than merely comparing state after the fact. But this would be a bit more involved and would also require you to abandon the built-in User object.

David Berger