如何在 Django 模型中使用两个唯一约束?

Com*_*ser 5 django model constraints

我有一个游戏玩家的 Django 模型

class Player(models.Model):
    name = models.CharField(max_length=50)
    team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
    game = models.ForeignKey('Game', on_delete=models.CASCADE)
    objects = GameManager()

    class Meta:
       unique_together = ('name', 'game',)
Run Code Online (Sandbox Code Playgroud)

我只有一个独特的约束,即名称和游戏是独一无二的。

现在,我想通过添加注册用户来扩展我们的页面。因此,我会将其添加到模型中。

        user = models.ForeignKey('auth.User', on_delete=models.CASCADE, blank=True, null=True)
Run Code Online (Sandbox Code Playgroud)

因此,注册用户可以通过添加名称、团队、游戏和他/她的用户来订阅游戏。但是,用户应该只能将他的帐户添加到游戏中,这将是第二个独特的限制

       unique_together = ('user', 'game',)
Run Code Online (Sandbox Code Playgroud)

是否可以在 Django 中为模型提供两个独特的约束?或者我是否必须在保存新条目之前手动在表中搜索?或者,还有更好的方法?

谢谢

Wil*_*sem 7

是的,实际上默认情况下unique_together是一组唯一的字段集合,例如:

class Player(models.Model):
    name = models.CharField(max_length=50)
    team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
    game = models.ForeignKey('Game', on_delete=models.CASCADE)
    objects = GameManager()

    class Meta:
       unique_together = (('name', 'game',), ('user', 'game',))
Run Code Online (Sandbox Code Playgroud)

因此,我们在此指定每一name, game对都是唯一的,并且每一user, game对都是唯一的。所以这是不可能的创建两个Player为同一对象usergame,或为同gamename

仅仅因为单个unique_together约束很常见,所以还可以传递一个字段名称集合,这些字段名称应该是唯一的,如[Django-doc]文档中Options.unique_together所写:

一组字段名称,它们放在一起必须是唯一的:

unique_together = (("driver", "restaurant"),)
Run Code Online (Sandbox Code Playgroud)

这是一个元组的元组,当一起考虑时必须是唯一的。它在 Django admin 中使用,并在数据库级别强制执行(即,UNIQUE语句中包含适当的CREATE TABLE语句)。

为方便起见,unique_together在处理一组字段时可以是单个元组

unique_together = ("driver", "restaurant")
Run Code Online (Sandbox Code Playgroud)


小智 5

您应该使用models.UniqueConstraint参考)。

正如参考文献中指出的:

UniqueConstraint 提供比 unique_together 更多的功能。unique_together 将来可能会被弃用。

做这个:

class Meta:
    constraints = [
        models.UniqueConstraint(fields=['name', 'game'], name="unique_name_game"),
        models.UniqueConstraint(fields=['user', 'game'], name="unique_user_game"),
 ]
Run Code Online (Sandbox Code Playgroud)