Сложное ограничение в модели Django

У меня есть сценарий использования, в котором я хочу проверить, что значение поля ForeignKey находится в определенном наборе, поэтому что-то вроде:

class Role(models.Model):
    label = models.CharField(max_length=24)

class Group(models.Model):
    roles = models.ManyToManyField(Role, null=False)

class Member(models.Model):
    label = models.CharField(max_length=24)
    group = models.ForeignKey(Group)
    role = models.ForeignKey(Role)

    class Meta:
        constraints = [
            models.CheckConstraint(
                name="%(app_label)s_%(class)s_role",
                check=(
                    models.Q(role__in=... valid roles ...)
                )
            )

Другими словами, разрешить участнику иметь роль только в том случае, если эта роль перечислена в ролях для группы. Я не могу понять, как это выразить.

Вы не можете сделать это с помощью CheckConstraint: такое ограничение может распространяться на всю строку, а не на несколько таблиц. Таким образом, оно не может "следовать" за ForeignKey или другими отношениями.

Можно было бы ссылаться не на Group или Role, а на таблицу переходов, которую Django создал для ManyToManyField, например:

class Role(models.Model):
    label = models.CharField(max_length=24)


class Group(models.Model):
    roles = models.ManyToManyField(Role, null=False)


class Member(models.Model):
    label = models.CharField(max_length=24)
    group_role = models.ForeignKey(Group.roles.through, on_delete=models.PROTECT)

    @property
    def group(self):
        return self.group_role.group

    @property
    def role(self):
        return self.group_role.role

Таким образом, он может ссылаться только на записи в таблице GroupRoles, которая, таким образом, ссылается на Group и Role, и поэтому ограничение FOREIGN KEY гарантирует, что выбранная нами комбинация роль-группа подразумевает, что Role доступна для этой Group.

Вернуться на верх