Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#32337 closed Bug (invalid)

Django Check Constraint is not enforced at all

Reported by: Aryan Iyappan Owned by: nobody
Component: Database layer (models, ORM) Version: 3.1
Severity: Normal Keywords: check constraint
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have a model like this with the following structure.

class Role(BaseModel):
    class Meta:
        verbose_name = 'role'
        verbose_name_plural = 'roles'
        ordering = ['position', 'cluster']
        required_db_features = {
            'supports_deferrable_unique_constraints',
        }
        constraints = [
            models.UniqueConstraint(
                fields=['position', 'cluster'],
                name='deferrable_unique_role_position',
                deferrable=models.Deferrable.DEFERRED
            ),
            models.CheckConstraint(
                name='default_role_check',
                check=(
                    models.Q(is_default=True, position=1, color='#969696', name='@everyone') |
                    models.Q(is_default=False)
                )
            ),
        ]

    permission_flags = [
        'READ_DATA', 'WRITE_DATA', 'MANAGE_RECORDS', 'MANAGE_ROLES',
        'MANAGE_CLUSTER', 'MANAGE_DATASHEETS', 'MANAGE_FIELDS', 'MANAGE_CONSTRAINTS',
        'KICK_MEMBERS', 'MANAGE_MEMBERS',
    ]

    default_perm_flags = ['READ_DATA', 'WRITE_DATA', 'MANAGE_RECORDS']

    def __str__(self):
        return self.name

    objects = managers.RolesManager()
    positions = managers.PositionalManager()
    permissions = BitField(flags=permission_flags, default=default_perm_flags, db_index=True)
    position = models.PositiveSmallIntegerField(null=True, blank=True, db_index=True, editable=True)
    name = models.CharField(max_length=100, validators=[MinLengthValidator(2)], db_index=True, default='new role')
    color = ColorField(db_index=True, default='#969696')
    is_default = models.BooleanField(default=False, db_index=True)
    cluster = models.ForeignKey('api_backend.Cluster', on_delete=models.CASCADE, editable=False)

    REQUIRED_FIELDS = [name, cluster]

Basically I want to ensure that a role with is_default set to True should always have a position of 1 and name of '@everyone' and a color of '#969696'

However, I am able to edit the model through serializers for the same, and the name changes to something other than '@everyone'. No errors are raised. Same with the position.
The constraint isnt enforced for updates or bulkupdates, too.

Change History (3)

comment:1 by Aryan Iyappan, 3 years ago

Resolution: fixed
Status: newclosed
Triage Stage: UnreviewedAccepted

The problem was that the table was altered when there was existing data in the database and the constraint was added. I cleared my database and now, the constraint works properly.

comment:2 by Tim Graham, 3 years ago

Resolution: fixedinvalid

comment:3 by Mariusz Felisiak, 3 years ago

Triage Stage: AcceptedUnreviewed
Note: See TracTickets for help on using tickets.
Back to Top