为啥不能在 Django ManyToMany 字段上强制执行唯一性?
Posted
技术标签:
【中文标题】为啥不能在 Django ManyToMany 字段上强制执行唯一性?【英文标题】:Why can't uniqueness be enforced on Django ManyToMany field?为什么不能在 Django ManyToMany 字段上强制执行唯一性? 【发布时间】:2015-11-18 21:37:49 【问题描述】:我正在为我的网站创建一个简单的二元评级系统,它是一个学习资料网站,其摘要可以评级为 +1 或 -1。
我在 Summary 模型和 User 模型之间定义了 ManyToMany 字段,如下所示:
users_rated_positive = models.ManyToManyField(
User, blank=True, related_name='summaries_rated_positive')
users_rated_negative = models.ManyToManyField(
User, blank=True, related_name='summaries_rated_negative')
但是很明显,给定用户不能多次评价给定摘要。
我尝试设置 unique=True 但 Django 似乎不允许我这样做。
是否有更优化的方式来存储更符合我意图的评分?
【问题讨论】:
您是否检查过是否可以有效地添加重复关系?这个答案似乎暗示不允许重复关系:***.com/questions/4870935/… 所以我不需要在我的视图中实际检查这个? 我自己从未尝试过,所以不能确定,但这就是我链接的答案中描述的内容。您可以尝试重现要检查的答案中的测试用例。 【参考方案1】:考虑使用多对多through table。
class Summary(models.Model):
user_ratings = models.ManyToManyField(
'User', blank=True, through='UserRating',
)
class UserRating(models.Model):
user = models.ForeignKey('User')
summary = models.ForeignKey('Summary')
is_positive = models.BooleanField()
class Meta:
unique_together = ('user', 'summary')
然后,您可以使用类似的方式查询积极评价摘要的用户
summary.user_ratings.filter(is_positive=True)
summary.user_ratings.filter(is_positive=False)
unique_together
属性确保用户不能两次查看同一个摘要。
您甚至可以使用自定义查询集保留类似的语法。以下是对它可能是什么样子的猜测:
class SummaryQuerySet(models.QuerySet):
def users_rated_negative(self):
return self.user_ratings.filter(is_positive=False)
def users_rated_positive(self):
return self.user_ratings.filter(is_positive=True)
class Summary(models.Model):
user_ratings = models.ManyToManyField(
'User', blank=True, through='UserRating',
)
objects = SummaryQuerySet.as_manager()
现在使用的语法是summary.users_rated_positive
如果您也需要,User
的类似自定义查询集将为您提供 summaries_rated_positive
属性。
【讨论】:
以上是关于为啥不能在 Django ManyToMany 字段上强制执行唯一性?的主要内容,如果未能解决你的问题,请参考以下文章
如何在模板上显示 Django ManyToMany?需要简单的代码