Opened 9 years ago

Closed 9 years ago

#25148 closed Uncategorized (duplicate)

Add a warning for `CASCADE`ing foreign keys on custom User models.

Reported by: Flavio Curella Owned by: Flavio Curella
Component: contrib.auth Version: 1.8
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Flavio Curella)

Assume a custom user models is created as such:

class Taco(models.Model):
    flavor = models.CharField(max_length=64, unique=True)


class User(AbstractBaseUser):
    USERNAME_FIELD = 'username'

    username = models.CharField(max_length=64, unique=True)
    favorite_taco = models.ForeignKey(Taco, null=True)

When deleting the related object, the user will also be deleted because of cascading:

        taco = Taco.objects.create(flavor="vegetarian")
        user = User.objects.create_user(
            username='taco fan',
            favorite_taco=taco
        )
        User.objects.count()  # 1
        taco.delete()
        User.objects.count()  # 0

This is intended behavior, but it's still pretty dangerous and a common trap for beginners.

I'd like to leverage the system check framework to add a Warning whenever a FK with on_delete=CASCADE is added to a User model. Something along the lines of:

class AbstractUser():
    @classmethod
    def check(cls, **kwargs):
        errors = super(AbstractUser, cls).check(**kwargs)
        for field in cls._meta.fields:
            if isinstance(field, models.ForeignKey):
                if field.rel.on_delete == models.CASCADE:
                    errors.append(checks.Warning(
                        "Field {0} is set to CASCADE on delete. You might lose users".format(field.name),
                        hint="Explicitly set {0}.on_delete to something else than `models.CASCADE".format(field.name),
                        obj=field,
                        id="{0}.W001".format(cls._meta.app_label)
                    ))
        return errors

Change History (5)

comment:1 by Flavio Curella, 9 years ago

Description: modified (diff)

comment:2 by Flavio Curella, 9 years ago

Owner: changed from nobody to Flavio Curella
Status: newassigned

comment:3 by Tim Graham, 9 years ago

A better use of your time may be to fix #21127 -- changing the default of on_delete. At that point, I don't think such a check would be needed.

comment:4 by Flavio Curella, 9 years ago

Thank Tim, I'll see if I can get consensus on that ticket.

comment:5 by Flavio Curella, 9 years ago

Resolution: duplicate
Status: assignedclosed
Note: See TracTickets for help on using tickets.
Back to Top