如何在Django模型中创建唯一值?并为列建立索引

10 投票
5 回答
6073 浏览
提问于 2025-04-15 16:21

这是我简单的Django数据库模型,专门用来做一个5星评分系统。

class Rating(models.Model):
    content = models.OneToOneField(Content, primary_key=True)
    ip =  models.CharField(max_length=200, blank=True)
    rating = models.IntegerField(default=0)

你可以看到,它和“内容”关联在一起,而“内容”是我存放文档的表格。我的问题是:

  • 我怎么才能让内容和IP地址组合起来是唯一的呢?也就是说,允许多个内容,但不允许同一个内容和IP地址重复评分(我不想让用户评分两次)。
  • 我怎么为内容和IP地址创建一个数据库索引呢?因为我总是需要根据这两个来查询(看看它们是否已经在数据库里)。

5 个回答

5

关于索引的部分:对于 content 字段,你不需要做任何事情,因为它是主键,系统会自动为它建立索引。至于 ip 字段,只需要在 CharField 的构造函数中加上 db_index=True 就可以了:

ip = models.CharField(max_length=200, blank=True, db_index=True)

想了解更多关于 db_index 和其他字段选项的信息,可以点击 这里

7

顺便说一下,如果你用“IP地址”来代表用户身份的话,请不要这样做——这真的是个糟糕透顶的主意。通过互联网服务提供商(ISP)上网的用户,他们的IP地址会随机变化,所以他们可能会投两次票;而那些在咖啡店、图书馆等地方用笔记本电脑上网的用户,IP地址也总是不同;还有共享网络的用户(比如住在同一个公寓的室友),或者每个从大学校园上网的用户,可能都会通过网络地址转换(NAT)获得相同的IP地址,这样只有一个人能投票……很难想象还有比这更糟糕的方式来表示个人身份了!

如果你把ip这个名字用在“用户身份”字段上是无意的,并且和使用IP地址没有关系,我表示歉意,但在这种情况下,请务必改一下这个字段的名字!

15

关于你的第一个问题:你可以看看 unique_together,因为这个可能会帮你解决问题。

class Rating(models.Model):
    content = models.OneToOneField(Content, primary_key=True)
    ip =  models.CharField(max_length=200, blank=True)
    rating = models.IntegerField(default=0)

    class Meta:
        unique_together= (('content', 'ip'),)

撰写回答