【问题标题】:How do I set collation_connection in Django?如何在 Django 中设置 collat​​ion_connection?
【发布时间】:2017-09-17 17:37:21
【问题描述】:

我把这个放在settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'NAME': 'db',
        'USER': 'root',
        'PASSWORD': '',
        'OPTIONS': {
            'charset': 'utf8mb4',
            'init_command': 'set collation_connection=utf8mb4_unicode_ci',
        },
    },
}

然后我使用 shell 检查它是否工作:

$ ./manage.py shell
>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute("show variables like 'collation_connection'")
>>> print cursor.fetchall()
((u'collation_connection', u'utf8mb4_general_ci'),)

不幸的是,我通过检查查询日志了解到MySQLdb 在连接时会这样做:

set collation_connection='utf8mb4_unicode_ci'
SET NAMES utf8mb4

没错。它在我的 init 命令之后执行set names。这会将排序规则设置回默认值。

省略 'charset' 选项没有帮助。如果我这样做,它将改为调用set names utf8,这更糟。我尝试将set names 命令作为'init_command' 的一部分,以防万一它不会破坏我的排序规则,如果没有什么可更改的,但不,它仍然会破坏它。

我无法派生 Python 库 MySQLdb,因为我在 Google App Engine 上运行我的应用,而 MySQLdb 是 App Engine 的一部分。

【问题讨论】:

  • 哦,“第 3 方软件阻碍”的列表越来越多!
  • 请提供collation_connection 的错误值给您带来麻烦的情况。
  • collation_connection 仅在不涉及数据库列的操作中很重要。但是,令人讨厌的是那里会出现不一致。如果可能的话,我喜欢删除奇怪的边缘情况。排序规则会影响很多方面,例如任何字符串比较的行为,包括相等 (=) 和排序顺序。

标签: mysql django collation


【解决方案1】:

我能够通过猴子修补 Django 来实现这一点:

from django.db.backends.mysql import base
old_get_new_connection = base.DatabaseWrapper.get_new_connection
def get_new_connection(self, conn_params):
  conn = old_get_new_connection(self, conn_params)
  conn.query("set names 'utf8mb4' collate 'utf8mb4_unicode_520_ci'")
  return conn

base.DatabaseWrapper.get_new_connection = get_new_connection

顺便说一句,这个补丁甚至是在 App Engine 上使用 utf8mb4 字符集所必需的,因为他们使用的是不支持该字符集的旧版本的 MySQL 连接器 C。如果没有此字符集,如果您尝试插入任何 4 字节 UTF8 字符,您的应用程序将会崩溃,并且数据库中的任何现有字符都将显示为问号。

【讨论】:

    猜你喜欢
    • 2017-01-19
    • 1970-01-01
    • 2015-10-10
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 2020-07-16
    相关资源
    最近更新 更多