如何在Python中显示波兰字符及解决Django数据库解码错误
解决Django原生SQL查询波兰字符时的UnicodeDecodeError
这个问题我之前帮朋友排查过,大概率是数据库字符集的配置没完全统一导致的——尤其是MySQL里的utf8有个容易踩的坑,咱们一步步来解决:
1. 先确认数据库/表/列的实际字符集
首先得搞清楚你的数据库、目标表和那个varchar列,是不是真的用了正确的UTF-8编码(MySQL里推荐用utf8mb4,它是完整的UTF-8,而默认的utf8其实是utf8mb3,只支持部分Unicode字符)。
登录数据库,执行这几条SQL检查:
-- 查看数据库默认字符集 SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = '你的数据库名'; -- 查看目标表的字符集 SELECT table_collation FROM information_schema.TABLES WHERE table_schema = '你的数据库名' AND table_name = '你的表名'; -- 查看目标列的字符集 SELECT column_name, character_set_name, collation_name FROM information_schema.COLUMNS WHERE table_schema = '你的数据库名' AND table_name = '你的表名' AND column_name = '你的列名';
如果列的字符集不是utf8或utf8mb4,赶紧修改:
ALTER TABLE 你的表名 MODIFY COLUMN 你的列名 VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
(优先用utf8mb4,避免以后遇到其他特殊字符再出问题)
2. 配置Django的数据库连接字符集
就算数据库本身是UTF-8,如果Django和数据库的连接没指定正确的字符集,也会出现解码错误。打开settings.py,在DATABASES配置里加上OPTIONS:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '你的数据库名', 'USER': '你的用户名', 'PASSWORD': '你的密码', 'HOST': 'localhost', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', 'use_unicode': True, }, } }
如果用的是mysqlclient(现在Django推荐的MySQL驱动),charset设置就足够;如果是旧的MySQLdb,use_unicode=True也得加上。
3. 检查数据本身的编码是否正确
如果之前这个列用的是其他编码(比如波兰常用的latin2),直接改字符集可能会导致乱码。这种情况得先导出数据转码再导入:
- 导出数据时指定原编码(比如latin2):
mysqldump -u 用户名 -p --default-character-set=latin2 你的数据库名 你的表名 > data.sql - 把数据转成utf8mb4编码:
iconv -f latin2 -t utf8mb4 data.sql > data_utf8.sql - 先备份好原数据,然后清空表、修改表/列字符集为utf8mb4,最后导入转码后的数据:
mysql -u 用户名 -p --default-character-set=utf8mb4 你的数据库名 < data_utf8.sql
4. 原生SQL查询时的临时处理
如果前面几步都做了还是有问题,试试在原生查询前先设置连接的字符集:
from django.db import connection def your_view(request): with connection.cursor() as cursor: # 先强制设置连接字符集 cursor.execute("SET NAMES utf8mb4;") # 再执行你的查询 cursor.execute("SELECT 你的列名 FROM 你的表名;") rows = cursor.fetchall() # 确保结果是正确的字符串 results = [row[0] if isinstance(row[0], str) else row[0].decode('utf8mb4') for row in rows] # 后续业务逻辑 ...
最后提醒个误区
你加的# -- coding: utf-8 --只是告诉Python解释器这个视图文件本身的编码,和数据库交互的编码完全没关系,不用纠结这个配置~
内容的提问来源于stack exchange,提问作者vba_user
相关产品推荐
相关产品推荐

