Through the on_delete option, Django provides various alternatives for what to do with objects that have a foreign key to an object that is being deleted.
I'm wondering if there is a way I could do something similar, but conditionally. Here's the scenario. I am utilizing Django 1.5's new custom User model and all my users have a ForeignKey to Site. Like so:
class TenantSiteUser(AbstractUser):
site = models.ForeignKey(Site, null=True)
If a site is deleted, then I'd prefer to delete all the non-superusers linked to that site (i.e., KASKADE-like behavoir), since their existence is now meaningless. But if its a superuser, I'd prefer to just set the user's site to null (i.e., SET_NULL) and let them keep existing, since that's probably me or someone I work with and we tend to not want to unintentionally delete ourselves.
Is there something I can override to manually do a check and implement this type of on_delete behavior?
EDIT: Here's the code that ended up working for me, based on @Kevin's answer and some study of how the existing handlers work:
def NULLIFY_SUPERUSERS_ELSE_CASCADE(collector, field, sub_objs, using):
superusers = []
for user in sub_objs:
if user.is_superuser:
sub_objs = list(sub_objs)
sub_objs.remove(user)
superusers.append(user)
CASCADE(collector, field, sub_objs, using)
if len(superusers):
collector.add_field_update(field, None, superusers)
class TenantSiteUser(AbstractUser):
site = models.ForeignKey(Site, null=True, on_delete=NULLIFY_SUPERUSERS_ELSE_CASCADE)
The options Django provides (CASCADE
, PROTECT
etc.) are all functions - here's where they're defined for 1.5.
I haven't tested it, but it should be possible to write your own NULL_OR_CASCADE
function and pass that in as your field's on_delete argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With