python - Django:Unicode、MySQL 和编码(latin1、koi8-r)
问题描述
Django 2.0 版。蟒蛇 3
我的数据库字符集和排序规则:
mysql> SELECT @@character_set_database, @@collation_database;
+--------------------------+----------------------+
| @@character_set_database | @@collation_database |
+--------------------------+----------------------+
| latin1 | latin1_swedish_ci |
+--------------------------+----------------------+
老开发者使用 Perl 以KOI8-R编码插入数据:(
为了从数据库中获取正确的值,我使用了丑陋的构造str(username).encode('latin1').decode('koi8-r')
。什么?我需要在我的所有项目中使用它来将数据发送到输出?或者编写函数来编码上下文字典,但我还需要额外的编码/解码所有数据。它将影响可用性和生产力
没有这个,我会得到类似的东西ëÏÚÌÑÎËÏ òÏÍÁÎ éÏÓÉÆÏ×ÉÞ
如何在 Django 中全局设置编码以防止在每个地方进行编码/解码操作?我改变了不同的编码方式,没有任何反应。
在 settings.py 我尝试将 DEFAULT_CHARSET 设置为不同的编码(如果我将 default_charset 设置为 KOI8-R 我得到一个错误:UnicodeEncodeError: 'charmap' codec can't encode characters in position 6228-6235: character maps to 。使用其他编码没有错误但没有结果)。我试图在 settings.py 的数据库部分设置不同的字符集和排序规则值。
'OPTIONS': {
'charset': 'latin1',
'init_command': "SET sql_mode='STRICT_TRANS_TABLES', character_set_client=latin1, character_set_results=latin1, character_set_connection=latin1, collation_connection=latin1_swedish_ci",
}
我在 index.html 模板中添加<meta http-equiv="Content-type" content="text/html; charset=koi8-r (or other)" />
了标签。<head>
没有结果。
似乎DjangoSET NAMES utf8
每次都执行
为什么在 Perl 中我可以发送带有 charset=koi8-r 的标头,并且我使用 CGI 从浏览器中的这个表中获取正常值?为什么使用 Django 或 Flask 在 Python 中没有类似的结果?Perl 中的简单示例
解决方案
我认为您将网络字符编码与存储编码混淆了。在 MySQL 中,字符串数据的生命周期大致是这样的:
disk_storage --decode--> MySQL --encode--> network --decode--> database_driver
当从磁盘读取字符串数据时,MySQL 使用该character_set_database
值对其进行解码。当客户端通过网络连接时,客户端会指定连接的编码。对于 Python,这通常是 UTF-8。MySQL 然后将数据编码为连接编码。然后,Python Mysql 驱动程序使用它设置的连接编码解码它接收到的数据。
如果这些解码或编码中的任何一个使用了错误的值,则会创建错误的数据。如果character_set_database
设置不正确,那么 MySQL 将在对网络连接上的坏数据进行编码之前错误地解码数据。
解决方案应该像更改character_set_database
为正确的值而不更改实际数据一样简单。
这可以通过以下方式实现:
ALTER DATABASE dbname CHARACTER SET koi8r COLLATE koi8r_general_ci;
(不要运行ALTER TABLE tbl_name CONVERT..
- 这实际上会重新编码您的数据。由于旧的 character_set 值错误,您的数据将在编码为新编码之前被错误地解码)
将所有 Python 设置更改回默认值(UTF-8 等)。不要设置DEFAULT_CHARSET
或任何其他值。
确保 MySQL 驱动程序正确连接并使用 UTF-8 作为网络连接集use_unicode=True
和charset="utf8"
例如
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
推荐阅读
- python-3.x - ModuleNotFoundError:没有名为“pyyaml”的模块
- android - 在某些后台应用程序中发生 Android 崩溃
- php - 任务完成后,Laravel cron withoutOverlapping 再次启动
- javascript - 流中基于 Promise 的函数
- javascript - 仅在当前方块上绘制轮廓
- javascript - Vanilla JS 相当于 jQuery $.once()?
- javascript - 如何从 Firebase 中提取数据并使用 JavaScript 将其放入公共变量中?
- vector - 我不确定为什么使用迭代器的循环运行的次数超过了所需的次数
- postgresql - 为同一个数据库运行两个 Postgress 服务器,然后将数据库复制到另外两个服务器
- java - 是否可以结合 List 中方法调用的结果
> 使用 Stream API 将文件写入新的供应商?