Django 3.2+:在 MySQL 表中实现区分大小写的字符串比较
Django 3.2+: implementing case-sensitive string comparisons within MySQL tables
Django 文档(3.2 到 4.0)指出:
In MySQL, a database table’s collation determines whether string
comparisons (such as the expression and substring of this function)
are case-sensitive. Comparisons are case-insensitive by default.
从 3.2 开始,提到现在可以在 CharField 级别定义要使用的排序规则:
https://docs.djangoproject.com/en/3.2/ref/databases/#collation-settings
但我找不到我应该为 db_collation
使用什么值来为给定的 CharField 启用区分大小写的字符串比较:
case_sensitive_collation = ???
name = models.CharField(max_length=50, db_collation=case_sensitive_collation)
刚刚发现这个要点恰恰相反:
CreateCollation and db_collation to implement a case-insensitive Charfield with Postgres > 12
https://gist.github.com/hleroy/2f3c6b00f284180da10ed9d20bf9240a
有人可以帮我吗?
编辑:
这是 SHOW CREATE TABLE
。目标是让字段 pieces
区分大小写:
MariaDB [FormApp_db]> show create table puzzles_puzzlepieces;
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| puzzles_puzzlepieces | CREATE TABLE `puzzles_puzzlepieces` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pieces` varchar(255) NOT NULL,
`uncolored_id` int(11) DEFAULT NULL,
`piece_setup_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `pieces` (`pieces`),
KEY `puzzles_puzzlepieces_uncolored_id_8afb6603_fk_puzzles_p` (`uncolored_id`),
CONSTRAINT `puzzles_puzzlepieces_uncolored_id_8afb6603_fk_puzzles_p` FOREIGN KEY (`uncolored_id`) REFERENCES `puzzles_puzzlepieces` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3094388 DEFAULT CHARSET=utf8mb4 |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.003 sec)
和生成的SELECT
:
>>> x = PuzzlePieces.objects.all()
>>> x[0]
SELECT `puzzles_puzzlepieces`.`id`,
`puzzles_puzzlepieces`.`pieces`,
`puzzles_puzzlepieces`.`uncolored_id`,
`puzzles_puzzlepieces`.`piece_setup_id`
FROM `puzzles_puzzlepieces`
LIMIT 1
Execution time: 0.002870s [Database: default]
为了验证@rickjames 提出的解决方案,我将在此处记录答案的实现:
在settings.py中:
if app_version == 'prod':
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/home/src/my.cnf'
}
}
}
DB_IS_MYSQL = True
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
DB_IS_MYSQL = False
MYSQL_SENSITIVE_COLLATION = 'ascii_bin'
DB_CASE_SENSITIVE_COLLATION = {'db_collation': MYSQL_SENSITIVE_COLLATION} if DB_IS_MYSQL else {}
# Use:
# from django.conf import settings
# pieces = models.CharField(max_length=255, default='empty', unique=True, **settings.DB_CASE_SENSITIVE_COLLATION)
在model.py中:
name = models.CharField(max_length=50, **settings.DB_CASE_SENSITIVE_COLLATION)
Django 文档(3.2 到 4.0)指出:
In MySQL, a database table’s collation determines whether string comparisons (such as the expression and substring of this function) are case-sensitive. Comparisons are case-insensitive by default.
从 3.2 开始,提到现在可以在 CharField 级别定义要使用的排序规则: https://docs.djangoproject.com/en/3.2/ref/databases/#collation-settings
但我找不到我应该为 db_collation
使用什么值来为给定的 CharField 启用区分大小写的字符串比较:
case_sensitive_collation = ???
name = models.CharField(max_length=50, db_collation=case_sensitive_collation)
刚刚发现这个要点恰恰相反:
CreateCollation and db_collation to implement a case-insensitive Charfield with Postgres > 12
https://gist.github.com/hleroy/2f3c6b00f284180da10ed9d20bf9240a
有人可以帮我吗?
编辑:
这是 SHOW CREATE TABLE
。目标是让字段 pieces
区分大小写:
MariaDB [FormApp_db]> show create table puzzles_puzzlepieces;
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| puzzles_puzzlepieces | CREATE TABLE `puzzles_puzzlepieces` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pieces` varchar(255) NOT NULL,
`uncolored_id` int(11) DEFAULT NULL,
`piece_setup_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `pieces` (`pieces`),
KEY `puzzles_puzzlepieces_uncolored_id_8afb6603_fk_puzzles_p` (`uncolored_id`),
CONSTRAINT `puzzles_puzzlepieces_uncolored_id_8afb6603_fk_puzzles_p` FOREIGN KEY (`uncolored_id`) REFERENCES `puzzles_puzzlepieces` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3094388 DEFAULT CHARSET=utf8mb4 |
+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.003 sec)
和生成的SELECT
:
>>> x = PuzzlePieces.objects.all()
>>> x[0]
SELECT `puzzles_puzzlepieces`.`id`,
`puzzles_puzzlepieces`.`pieces`,
`puzzles_puzzlepieces`.`uncolored_id`,
`puzzles_puzzlepieces`.`piece_setup_id`
FROM `puzzles_puzzlepieces`
LIMIT 1
Execution time: 0.002870s [Database: default]
为了验证@rickjames 提出的解决方案,我将在此处记录答案的实现:
在settings.py中:
if app_version == 'prod':
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/home/src/my.cnf'
}
}
}
DB_IS_MYSQL = True
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
DB_IS_MYSQL = False
MYSQL_SENSITIVE_COLLATION = 'ascii_bin'
DB_CASE_SENSITIVE_COLLATION = {'db_collation': MYSQL_SENSITIVE_COLLATION} if DB_IS_MYSQL else {}
# Use:
# from django.conf import settings
# pieces = models.CharField(max_length=255, default='empty', unique=True, **settings.DB_CASE_SENSITIVE_COLLATION)
在model.py中:
name = models.CharField(max_length=50, **settings.DB_CASE_SENSITIVE_COLLATION)