Django 模型:使用来自同一 table 的 2 个外键时如何避免引用同一记录
Django model: How to avoid referencing the same record when using with 2 foreign keys from the same table
我有两个如下所示的 Django 模型:
class Team(models.Model):
name = models.CharField(max_length=30)
...
class Game(models.Model):
teamA = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamA')
teamB = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamB')
....
Game
模型有 2 个指向 Team
模型的外键。
当然,一个队不可能和自己比赛,所以我想防止teamA和teamB在DB中引用同一条记录。
所以你不能创建这样的游戏:
Game.objects.create(teamA=ChicagoBulls, teamB=ChicagoBulls)
最好的方法是什么?
您可以在 .clean()
method [Django-doc], and also at the database level with a CheckConstraint
[Django-doc] 中实施约束(但并非所有数据库都会强制执行):
from django.core.exceptions import ValidationError
from django.db.models import F, Q
class Game(models.Model):
teamA = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamA')
teamB = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamB')
# …
def clean(self, *args, **kwargs):
if <b>self.teamA_id == self.teamB_id</b>:
raise ValidationError('The two teams should be different')
super().clean(*args, **kwargs)
class Meta:
constraints = [
models.CheckConstraint(
<b>check=~Q(teamA=F('teamB'))</b>,
name='different_teams'
)
]
使用模型层创建对象时,.clean()
方法未 检查。但是,当您通过 ModelForm
[Django-doc].
创建 Game
时,它会被验证
您可能还想使 Team
的 name
唯一,这样就不能有两个同名的团队:
class Team(models.Model):
name = models.CharField(max_length=30<b>, unique=True</b>)
# …
我有两个如下所示的 Django 模型:
class Team(models.Model):
name = models.CharField(max_length=30)
...
class Game(models.Model):
teamA = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamA')
teamB = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamB')
....
Game
模型有 2 个指向 Team
模型的外键。
当然,一个队不可能和自己比赛,所以我想防止teamA和teamB在DB中引用同一条记录。
所以你不能创建这样的游戏:
Game.objects.create(teamA=ChicagoBulls, teamB=ChicagoBulls)
最好的方法是什么?
您可以在 .clean()
method [Django-doc], and also at the database level with a CheckConstraint
[Django-doc] 中实施约束(但并非所有数据库都会强制执行):
from django.core.exceptions import ValidationError
from django.db.models import F, Q
class Game(models.Model):
teamA = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamA')
teamB = models.ForeignKey(Team, on_delete=CASCADE, related_name='teamB')
# …
def clean(self, *args, **kwargs):
if <b>self.teamA_id == self.teamB_id</b>:
raise ValidationError('The two teams should be different')
super().clean(*args, **kwargs)
class Meta:
constraints = [
models.CheckConstraint(
<b>check=~Q(teamA=F('teamB'))</b>,
name='different_teams'
)
]
使用模型层创建对象时,.clean()
方法未 检查。但是,当您通过 ModelForm
[Django-doc].
Game
时,它会被验证
您可能还想使 Team
的 name
唯一,这样就不能有两个同名的团队:
class Team(models.Model):
name = models.CharField(max_length=30<b>, unique=True</b>)
# …