无论如何使用mysql db后端在django中创建唯一的TextField?

Mas*_*gol 9 mysql django

我为多项选择问题创建了一个模型.每个问题都有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')]
Run Code Online (Sandbox Code Playgroud)

当我运行时migrate,mysql给出了这个错误:

1170,"没有密钥长度的密钥规范中使用的BLOB/TEXT列'问题'

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

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

我需要使用mysql的原因是因为我将部署这个django应用程序的服务器只提供mysql,没有postgresql.

那么,无论如何我能做到这一点吗?

dot*_*mly 3

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

最大密钥长度为 1000 字节。这也可以通过更改源代码并重新编译来更改。对于长度超过 250 字节的密钥的情况,将使用比默认的 1024 字节更大的密钥块大小。来自手册

我不建议这样做,原因有几个,包括性能和黑客行为。我建议您创建一个唯一的哈希字段,而不是重新编译。这将创建所有字段的 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)
Run Code Online (Sandbox Code Playgroud)