【问题标题】:Is there anyway to create unique TextField in django with mysql db backend?无论如何在 django 中使用 mysql db 后端创建唯一的 TextField 吗?
【发布时间】:2023-03-21 15:00:01
【问题描述】:

我为多项选择题创建了一个模型。每个问题有5个选择 的答案。我需要每个问题对象都是独一无二的 问题和答案。所以,我这样设计模型。

from django.db import models


class MultipleChoiceQuestion(models.Model):
    ANSWERS = [('a', 'a'), ('b', 'b'), ('c', 'c'), ('d', 'd'), ('e', 'e')]
    question = models.TextField()
    a = models.TextField()
    b = models.TextField()
    c = models.TextField()
    d = models.TextField()
    e = models.TextField()
    true_answer = models.CharField(max_length=1, choices=ANSWERS)

    class Meta:
        unique_together = [('question', 'a', 'b', 'c', 'd', 'e')]

当我运行migrate 时,mysql 报此错误:

1170, "BLOB/TEXT 列“问题”用于密钥规范 没有密钥长度”

我发现这个错误已经被讨论过here。但是,我不能使用 CharField 限制很小,因为我需要存储长文本 (直到 10000 个字符或更多)。

sqlite3 和 postgresql 可以做到这一点(我的意思是 django 没有抱怨 TEXT 的关键规范)。

我需要使用 mysql 的原因是我将部署它的服务器 django app只提供mysql,不提供postgresql。

那么,我有没有办法做到这一点?

【问题讨论】:

    标签: mysql django


    【解决方案1】:

    看起来这是一个 django/mysql 错误,其中django blames MySql 并“不会修复”它。他们的建议是离开模型的关键,只需手动添加约束。巨大的黑客但是是的,这可能是唯一的解决方案。但是,如果您的密钥超过 1000 字节,则需要重新编译 MySql。

    最大密钥长度为 1000 字节。这也可以通过更改源并重新编译来更改。对于长度超过 250 字节的密钥,使用比默认值 1024 字节更大的密钥块大小。 From The Manual

    我不建议这样做,原因包括性能和黑客攻击。我建议您创建一个唯一的哈希字段,而不是重新编译。这将创建所有字段的 md5 总和,并且始终为 32 个字符。重复的几率是 2^128 中的 1,所以你很安全。

    from django.db import models
    import hashlib
    
    
    class MultipleChoiceQuestion(models.Model):
        ANSWERS = [('a', 'a'), ('b', 'b'), ('c', 'c'), ('d', 'd'), ('e', 'e')]
        question = models.TextField()
        a = models.TextField()
        b = models.TextField()
        c = models.TextField()
        d = models.TextField()
        e = models.TextField()
        true_answer = models.CharField(max_length=1, choices=ANSWERS)
        unique_hash = models.CharField(max_length=32, unique=True)
    
        def save(self, *args, **kwargs):
            m = hashlib.md5()
            m.update(self.question)
            m.update(self.a)
            m.update(self.b)
            m.update(self.c)
            m.update(self.d)
            m.update(self.e)
            self.unique_hash = m.digest()
            super(MultipleChoiceQuestion, self).save(*args, **kwargs)
    

    【讨论】:

    • 您可能希望使用m.hexdigest(),因为m.digest() 将返回如下对象:b'\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\t\x98\xec\xf8B~' 其中m.hexdigest() 将返回d41d8cd98f00b204e9800998ecf8427e
    猜你喜欢
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2012-01-10
    • 1970-01-01
    • 2021-11-13
    相关资源
    最近更新 更多