强制django管理员搜索栏不区分大小写

时间:2018-08-21 15:53:59

标签: mysql django django-models encoding character-encoding

我的问题是,对于我的其中一个模型,相应的管理页面上的搜索栏正在执行区分大小写不敏感的搜索,而应该按不区分大小写进行搜索默认。

从我能找到的here来看,我觉得这可能与数据库编码有关,但是从the doc开始,它说Django假设所有内容都是UTF-8编码的,因此我检查了MySQL表和字段均以UTF-8编码。

可能是由于我的领域之一中存在希腊字符吗?如何至少在不包含希腊字母的字段中至少进行不区分大小写的搜索?当前,搜索对所有字段区分大小写。但是对于其他模型,它可以正常工作(不区分大小写)。

型号:

class MyModel(models.Model):
    id = models.AutoField(primary_key=True)
    field1 = models.CharField(max_length=200) # Might contain greek letters
    field2 = models.CharField(max_length=200, unique=True)

不共享管理类代码,因为这里没有花哨的内容。 list_displaysearch_fieldsorderingfieldsets的标准组合。

使用Django 1.10

编辑
这是该表的SHOW CREATE TABLE的输出:

CREATE TABLE `my_model` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `field1` varchar(200) COLLATE utf8_bin NOT NULL,
    `field2` varchar(200) COLLATE utf8_bin NOT NULL,
    # Non relevant other fields
    PRIMARY KEY (`id`),
    UNIQUE KEY `my_model_field2_63f9df5e_uniq` (`field2`)
) ENGINE=InnoDB AUTO_INCREMENT=657 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

现在我看到了,这可能是由于_bin造成的吧?我应该用_ci转换成什么吗?在Django中这样做的方式是什么?

2 个答案:

答案 0 :(得分:1)

utf8_bin is case sensitive. Change to utf8_unicode_520_ci (if using MySQL 5.6 or 5.7):

ALTER TABLE my_model CONVERT TO COLLATION utf8_unicode_520_ci;

Using LOWER() may work, but it is slow because it prevents using the index, thereby potentially making queries run a lot slower than they could.

Note: To allow for Emoji and all of Chinese, utf8mb4 is needed in place of utf8.

Your model specifies 3 unique keys for a single table? That seems excessive. Then I am confused by the CREATE TABLE -- it shows only 2. (Note: PRIMARY KEY is UNIQUE.)

According to Django docs "In all cases, you set the collation by directly manipulating the database tables; Django doesn’t provide a way to set this on the model definition." As demonstrated by the OP, using SHOW CREATE TABLE via MySQL utilities can tell you what collation is currently being used.

答案 1 :(得分:0)

from django.db.models.functions import Lower
qs = MyModel.objects.annotate(field1_lower=Lower('field1')) # annotate each item in the queryset with the code_lower

现在使用field1_lower而不是field1搜索。希望有帮助。