必须在mysql连接字符串中显式指定charset=utf8mb4且数据库、表、字段均设为utf8mb4字符集,并确保flask请求体以utf-8解码,否则emoji插入会报incorrect string value错误。

MySQL连接字符串必须显式指定utf8mb4字符集
Flask本身不处理数据库编码,错误根源在SQLAlchemy或底层MySQL驱动没用对字符集。默认utf8在MySQL里实际是utf8mb3,最多存3字节,而Emoji(如 ?、?、??)需要4字节——直接报Incorrect string value错误。
解决方法不是改Flask配置,而是确保连接字符串带charset=utf8mb4,且collation也匹配:
mysql+pymysql://user:pass@localhost/dbname?charset=utf8mb4&collation=utf8mb4_unicode_ci
注意:&是URL转义,别写成&;如果用mysqlclient,参数名是charset,不是encoding。
数据库和表的字符集必须是utf8mb4,不能只靠连接字符串
即使连接设对了,如果库或表还是utf8,插入Emoji时仍会截断或报错。检查方式:
SHOW CREATE DATABASE dbname;
SHOW CREATE TABLE tablename;
若输出中显示DEFAULT CHARSET=utf8或COLLATE utf8_unicode_ci,就得改:
ALTER DATABASE dbname CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意:已有数据可能被损坏,建议先备份;CONVERT TO会锁表,生产环境慎用。
SQLAlchemy模型字段要加collation='utf8mb4_unicode_ci'(仅MySQL)
某些场景下,即使库和连接都设对了,单个String字段仍可能用错排序规则,尤其涉及unique=True或index=True时。MySQL对utf8mb4字段的索引长度有限制(767字节),不显式指定collation可能导致隐式降级。
在定义字段时加上collation参数:
title = db.Column(db.String(200), collation='utf8mb4_unicode_ci')
这个参数只对MySQL生效,PostgreSQL不需要;如果字段内容确定含Emoji,建议所有String和Text类型都加。
Flask请求体中的Emoji需正确解码,别依赖request.form自动处理
浏览器提交含Emoji的表单时,Content-Type通常是application/x-www-form-urlencoded,但部分老客户端可能用iso-8859-1编码发送——这时request.form.get('text')拿到的是乱码字节,后续存库会二次出错。
稳妥做法是手动按UTF-8解码原始数据:
data = request.get_data(as_text=True) # 自动用UTF-8解码
或者从request.values取后强制解码:
text = request.values.get('text', '').encode('latin1').decode('utf8')
更推荐统一前端设置<meta charset="UTF-8"> + 表单accept-charset="UTF-8",避免服务端兜底。
真正卡住人的往往不是某一行代码,而是连接字符串、数据库、表、字段、HTTP请求这五层里有一层漏了utf8mb4——挨个确认比猜更容易见效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











