在SqlAlchemy中以数据库无关的方式指定列为UTF-8?

3 投票
1 回答
986 浏览
提问于 2025-04-18 10:22

我发现我的MySQL数据库默认不是设置为UTF-8,而是选择了latin1_swedish_ci这种字符排序方式。

因此,我遇到了一个用户报告的bug,说明我的应用程序不支持特殊字符。我检查了一下,确保我的应用程序能够正确处理UTF-8,写了一个测试,结果在内存中的SQLite上运行得很好,但在生产环境的MySQL上却不行。从SQLAlchemy的文档中,我似乎找到了一个解决方案,就是在我的列上指定一个字符排序方式:

 column = db.Column(db.String(500, collation='utf8_general_ci'))

可惜的是,这导致我基于SQLite的单元测试失败——因为utf8_general_ci并不是SQLite支持的编码方式。这是MySQL特有的。

SQLite似乎在不指定字符排序的情况下也能很好地支持UTF-8。我可以用MySQL进行测试,但在内存中的SQLite数据库是一个更快、更简单的测试选项,适合快速测试。我非常重视测试的便利性,所以回到使用SQLite进行测试对我来说非常重要。

我尝试过的其他方法

我还尝试在我的连接字符串中添加

charset=utf8&use_unicode=1

我也用db.Unicode代替了db.String,但似乎没有什么区别。

问题

有没有一种简单且不依赖于数据库的方式,通过SQLAlchemy来指明某一列应该使用UTF-8编码?

1 个回答

2

我解决问题的方法是通过 __table_args__ 来修改表的排序规则:

class Foo(Base):
    __tablename__ = "foo"
    __table_args__ = {'mysql_collate': 'utf8_general_ci'}

    ...

    column = db.Column(db.String(500))

SQLite 对这个 MySQL 的设置毫不在意,而 MySQL 则能正确识别这个设置。

撰写回答