在Sqlite3中(使用Django)可以实现不区分大小写的'唯一'约束吗?

12 投票
3 回答
5138 浏览
提问于 2025-04-11 19:17

假设我在用Python 2.5自带的sqlite3,并且我有一个Django模型类,代码如下:

class SomeEntity(models.Model):
    some_field = models.CharField(max_length=50, db_index=True, unique=True)

我已经设置好了管理界面,所有功能看起来都正常,但我可以创建两个SomeEntity记录,一个是some_field='some value',另一个是some_field='Some Value',因为some_field的唯一性约束似乎是区分大小写的。

有没有办法让sqlite在检查唯一性时忽略大小写进行比较呢?

我在Django的文档中找不到这个选项,我在想有没有什么方法可以直接对sqlite进行设置,让它按照我想要的方式工作。:-)

3 个回答

2

对于2021年的人来说,借助于 Django 4.0 的 UniqueConstraint 表达式,你可以像下面这样在你的模型中添加一个 Meta 类:

class Meta:
    constraints = [
        models.UniqueConstraint(
            Lower('<field name>'),
            name='<constraint name>'
        ),
    ]
4

也许你可以创建一个自定义的模型字段;这个字段可以是CharField的一个子类,但需要提供一个叫做 db_type 的方法,这个方法返回“text collate nocase”。

11

是的,这个可以很简单地通过给表添加一个唯一索引来实现,使用下面的命令:

CREATE UNIQUE INDEX uidxName ON mytable (myfield COLLATE NOCASE)

如果你需要对非ASCII字符(比如中文、日文等)进行不区分大小写的处理,你需要注册你自己的排序规则,命令类似于下面这样:

下面的例子展示了一个自定义的排序规则,它的排序方式是“反向的”:

import sqlite3

def collate_reverse(string1, string2):
    return -cmp(string1, string2)

con = sqlite3.connect(":memory:")
con.create_collation("reverse", collate_reverse)

cur = con.cursor()
cur.execute("create table test(x)")
cur.executemany("insert into test(x) values (?)", [("a",), ("b",)])
cur.execute("select x from test order by x collate reverse")
for row in cur:
    print row
con.close()

关于sqlite3的更多Python文档可以在 这里 找到

撰写回答