【问题标题】:How to use two unique constraints in Django model?如何在 Django 模型中使用两个唯一约束?
【发布时间】:2019-06-01 01:37:12
【问题描述】:

我有一个游戏玩家的 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',)

我只有一个唯一约束,即名称和游戏是唯一的。

现在,我想通过添加注册用户来扩展我们的页面。所以,我会把它添加到模型中。

        user = models.ForeignKey('auth.User', on_delete=models.CASCADE, blank=True, null=True)

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

       unique_together = ('user', 'game',)

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

【问题讨论】:

    标签: django model constraints


    【解决方案1】:

    您应该使用models.UniqueConstraint (reference)。

    这样做:

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['name', 'game'], name="sample_name"),
            models.UniqueConstraint(fields=['user', 'game'], name="sample_name"),
     ]
    

    【讨论】:

    • 嗨!您是否可以编辑您的答案以添加解释如何/为什么改进已经存在了一段时间的已接受答案?
    【解决方案2】:

    是的,实际上默认情况下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',))

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

    只是因为单个unique_together 约束很常见,所以也可以传递应该是唯一的字段名称的单个集合,如documentation on Options.unique_together [Django-doc] 中所写:

    字段名称集合,它们一起必须是唯一的:

    unique_together = (("driver", "restaurant"),)
    

    这是一个元组的元组,在考虑时必须是唯一的 一起。它在 Django 管理员中使用并在 数据库级别(即,包括适当的 UNIQUE 语句 在CREATE TABLE 语句中)。

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

    unique_together = ("driver", "restaurant")
    

    【讨论】:

    • 感谢您的回答。但是使用这个解决方案我有一个问题:我想链接到用户帐户是可选的。 (该字段可以是空白的)但是,唯一的一起意味着只有一个非关联玩家可以加入。
    • @Cometchaser: 通常唯一的一起将允许NULL 有多个值,所以我没有看到这个问题。请注意,blankforms 的相关性比与模型本身的相关性更高。说null=True 允许NULL 值就足够了。
    猜你喜欢
    • 1970-01-01
    • 2021-08-05
    • 2015-05-22
    • 2019-09-25
    • 1970-01-01
    • 2020-05-19
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多