【问题标题】:How to make uniques in Django Models? And also index a column in Django如何在 Django 模型中创建唯一性?并且还在 Django 中索引一列
【发布时间】:2009-11-25 00:40:54
【问题描述】:

这是我的简单 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 创建数据库索引...因为我将始终选择它们(以比较它是否已在数据库中)。

【问题讨论】:

  • 为什么使用CharField()而不是IPAddressField()作为IP?

标签: python mysql django django-models


【解决方案1】:

这是使用 Django 3.0+ 的人的答案。

最好使用UniqueConstraint(根据文档)来制作唯一性。

 class Rating(models.Model):
    ...

    class Meta:
        constraints = [ models.UniqueConstraint(fields=['content', 'ip'], name="unique-content-ip") ]
        indexes = [ models.Index(fields=['content', 'ip']) ]

因此您可以定义多个约束和indexes

【讨论】:

    【解决方案2】:

    关于您的第一个问题: 你应该看看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'),)
    

    【讨论】:

    • 在存储之前将IP转换为int可能会更好,并使用IntegerField。它将使用更少的空间(我不确定为什么您为 IP 地址分配了 200 个字节),并允许更多的查询灵活性。您可能还想查看django-ratings (github.com/dcramer/django-ratings),它可以很好地处理匿名投票和经过身份验证的投票。
    【解决方案3】:

    顺便说一句,如果从您的术语中可以看出,您使用 IP 地址来代表用户的身份,请不要 - 这是一个非常可怕的想法。通过他们的 ISP 进来的用户会随机更改他们的 IP,因此他们可能会投票两次;使用笔记本电脑连接各种咖啡店、图书馆等的用户将拥有不断变化的 IP;共享连接的用户(例如,公寓伙伴),甚至是来自大学校园的每个用户,都可能通过 NAT 获得相同的 IP 地址,因此只有一个人能够投票……很难想象代表个人身份的任何更糟糕的方式!-)

    如果您在“用户身份”字段中使用名称 ip 是偶然的,并且与在那里使用 IP 地址无关,我很抱歉,但在这种情况下,请重命名该字段!-)

    【讨论】:

    • 另一种想法是使用 cookie 或 LocalStorage。
    【解决方案4】:

    关于索引:content不需要做任何事情,因为它是主键,它会被索引。对于ip,只需将db_index=True 添加到CharField 构造函数调用中:

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

    更多关于 db_index 和其他字段选项的信息here

    【讨论】:

    • 索引第二个字段不会使该字段与主键唯一。
    • 我没有回答关于唯一性的问题。问题中的第二个项目符号询问有关索引 ip 的问题。
    【解决方案5】:

    请试试这个 meta 关键字:“unique_together”

        class PowerBoardSwitches(models.Model):
            id = models.AutoField(primary_key=True, verbose_name='Switch id')
            powerBoardId = models.ForeignKey(PowerBoardDevice, models.DO_NOTHING, db_column='powerBoardId', verbose_name='Power Board Id')
            powerBoardSwitchId = models.IntegerField()
            powerBoardSwitchStatus = models.IntegerField()
            createdOn = models.DateTimeField(auto_now_add=True, verbose_name='Created on date')
            updatedOn = models.DateTimeField(auto_now_add=True, verbose_name='Updated on date')
    
            class Meta:
                unique_together = (('powerBoardId', 'powerBoardSwitchId'), )
    

    【讨论】:

      猜你喜欢
      • 2010-12-07
      • 2021-10-30
      • 1970-01-01
      • 2021-08-26
      • 2011-08-12
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多