Сложное ограничение в модели 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
.