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