如何在Django中指定关系中的唯一性

时间:2012-11-07 19:00:05

标签: python django database-design

我正试图在Django中代表一些电影收视率数据。以下是我的模型的简化版本,用于说明我的问题:

class RatingSystem(models.Model):
    """This denotes a rating authority and territory in which they operate"""
    name = models.CharField(max_length=16)
    territory = models.CharField(max_length=32)

class Rating(models.Model):
    """This represents a rating designation used by a rating system."""
    code = models.CharField(max_length=16)
    description = models.TextField()
    system = models.ForeignKey(RatingSystem)

class FilmRating(models.Model):
    """This is a rating for a film and the reason why it received the rating.

    Each film can have many ratings, but only one per rating system.
    """
    rating = models.ForeignKey(Rating)
    film = models.ForeignKey('Film')
    reason = models.TextField()

class Film(models.Model):
    """Data for a film."""
    title = models.CharField(max_length=64)
    synopsis = models.TextField()
    ratings = models.ManyToManyField(Rating, through=FilmRating)

正如评论所示,每部电影可以有多个评级,但每个评级系统只有一个评级。例如,MPAA不能将电影评为“R”和“PG”。但是,它可以被MPAA评为'R',BBFC评为'15'。

我正在努力在Django中形式化这个约束。我想这样做:

unique_together = ('film', 'rating__system')
FilmRating中的

但似乎不允许遵循这样的关系。如果我使用纯SQL,我会在code中将systemRating作为复合主键,然后在systemfilm上设置唯一约束在FilmRatings。不幸的是,Django不支持复合键。我已经考虑覆盖save()的{​​{1}}方法,但如果可能的话,我宁愿在数据库级别使用约束。

任何人都知道如何做到这一点?如果有帮助的话,重组表也没关系。

3 个答案:

答案 0 :(得分:2)

我认为你应该看看validate_unique

This same problem some years ago in stackoverflow

The Django Docs

答案 1 :(得分:2)

编辑:根据@ JoshSmeaton和@ MSaavedra的评论更新答案

使用Django的syncdb hook,您可以直接在数据库上运行ALTER TABLE语句。如果违反了唯一约束,Django将引发IntegrityError,即使django没有定义该约束。

然后,将约束添加到validate_unique将减少开发人员后来的混淆,并在Django中安全地执行约束。

答案 2 :(得分:1)