在 alembic 迁移中插入 Unicode 值
Inserting Unicode values on alembic migration
我正在从事一个涉及多种货币会计的小型宠物项目。在它的开发过程中,我决定从直接的数据库设置转移到使用 alembic 的数据库迁移。在某些迁移中,我需要使用以乌克兰语显示的初始货币填充数据库。
我的问题是从 alembic 迁移脚本填充的数据以某种未知编码保存,因此我无法在应用程序(期望人类可读)中使用它。我的设置和脚本如下:
alembic.ini
...
sqlalchemy.url = mysql+pymysql://defaultuser:defaultpwd@localhost/petdb
...
alembic/versions/f433ab2a814_adding_currency.py
from alembic import op
# -*- coding: utf-8 -*-
"""Adding currency
Revision ID: f433ab2a814
Revises: 49538bba2220
Create Date: 2016-03-08 13:50:35.369021
"""
# revision identifiers, used by Alembic.
revision = 'f433ab2a814'
down_revision = '1c0b47263c82'
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
'currency',
Column('id', Integer, primary_key=True),
Column('name', Unicode(120), nullable=False),
Column('abbr', String(3), nullable=False)
)
op.execute(u'INSERT INTO currency SET name="{}", abbr="{}";'.format(u"Гривня", "UAH"))
从mysql客户端或mysql-[=45=检查tablecurrency
后],显示为:
mysql> SELECT * FROM currency;
+----+----------------------------+------+
| id | name | abbr |
+----+----------------------------+------+
| 1 | Ð“Ñ€Ð¸Ð²Ð½Ñ | UAH |
+----+----------------------------+------+
预期结果是:
mysql> SELECT * FROM currency;
+----+----------------------------+------+
| id | name | abbr |
+----+----------------------------+------+
| 1 | Гривня | UAH |
+----+----------------------------+------+
在我的应用程序中,我一直按如下方式设置此值:
from petproject import app
app.config.from_object(config.DevelopmentConfig)
engine = create_engine(app.config["DATABASE"]+"?charset=utf8",
convert_unicode=True, encoding="utf8", echo=False)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
if len(db_session.query(Currency).all()) == 0:
default_currency = Currency()
default_currency.name = u"Гривня"
default_currency.abbr = u"UAH"
db_session.add(default_currency)
db_session.commit()
所以我想知道如何在将以正确编码存储的迁移中插入初始 Unicode 值。我错过了什么吗?
经过更深入的分析,我发现 MySQL 将所有数据保存在 'windows-1252' 编码中。 MySQL 手册(“West European Character Sets”部分)将此问题描述为:
latin1 is the default character set. MySQL's latin1 is the same as the Windows cp1252 character set.
看起来 MySQL 忽略了 character_set_client
,我认为是 'utf-8',或者 SQLAlchemy / alembic 没有通知服务器接受数据 'UTF-8'编码数据。不幸的是,无法在 alembic.ini
.
中设置推荐选项 '?charset=utf8'
为了以正确的编码接受和保存数据,我通过调用 op.execute('SET NAMES utf8');
手动设置了字符集。因此完整的代码如下所示:
def upgrade():
op.create_table(
'currency',
Column('id', Integer, primary_key=True),
Column('name', Unicode(120), nullable=False),
Column('abbr', String(3), nullable=False)
)
op.execute('SET NAMES utf8')
op.execute(u'INSERT INTO currency SET name="{}", abbr="{}";'.format(u"Гривня", "UAH"))
结果如预期:
mysql> SELECT * FROM currency;
+----+----------------------------+------+
| id | name | abbr |
+----+----------------------------+------+
| 1 | Гривня | UAH |
+----+----------------------------+------+
我正在从事一个涉及多种货币会计的小型宠物项目。在它的开发过程中,我决定从直接的数据库设置转移到使用 alembic 的数据库迁移。在某些迁移中,我需要使用以乌克兰语显示的初始货币填充数据库。
我的问题是从 alembic 迁移脚本填充的数据以某种未知编码保存,因此我无法在应用程序(期望人类可读)中使用它。我的设置和脚本如下:
alembic.ini
...
sqlalchemy.url = mysql+pymysql://defaultuser:defaultpwd@localhost/petdb
...
alembic/versions/f433ab2a814_adding_currency.py
from alembic import op
# -*- coding: utf-8 -*-
"""Adding currency
Revision ID: f433ab2a814
Revises: 49538bba2220
Create Date: 2016-03-08 13:50:35.369021
"""
# revision identifiers, used by Alembic.
revision = 'f433ab2a814'
down_revision = '1c0b47263c82'
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
'currency',
Column('id', Integer, primary_key=True),
Column('name', Unicode(120), nullable=False),
Column('abbr', String(3), nullable=False)
)
op.execute(u'INSERT INTO currency SET name="{}", abbr="{}";'.format(u"Гривня", "UAH"))
从mysql客户端或mysql-[=45=检查tablecurrency
后],显示为:
mysql> SELECT * FROM currency;
+----+----------------------------+------+
| id | name | abbr |
+----+----------------------------+------+
| 1 | Ð“Ñ€Ð¸Ð²Ð½Ñ | UAH |
+----+----------------------------+------+
预期结果是:
mysql> SELECT * FROM currency;
+----+----------------------------+------+
| id | name | abbr |
+----+----------------------------+------+
| 1 | Гривня | UAH |
+----+----------------------------+------+
在我的应用程序中,我一直按如下方式设置此值:
from petproject import app
app.config.from_object(config.DevelopmentConfig)
engine = create_engine(app.config["DATABASE"]+"?charset=utf8",
convert_unicode=True, encoding="utf8", echo=False)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
if len(db_session.query(Currency).all()) == 0:
default_currency = Currency()
default_currency.name = u"Гривня"
default_currency.abbr = u"UAH"
db_session.add(default_currency)
db_session.commit()
所以我想知道如何在将以正确编码存储的迁移中插入初始 Unicode 值。我错过了什么吗?
经过更深入的分析,我发现 MySQL 将所有数据保存在 'windows-1252' 编码中。 MySQL 手册(“West European Character Sets”部分)将此问题描述为:
latin1 is the default character set. MySQL's latin1 is the same as the Windows cp1252 character set.
看起来 MySQL 忽略了 character_set_client
,我认为是 'utf-8',或者 SQLAlchemy / alembic 没有通知服务器接受数据 'UTF-8'编码数据。不幸的是,无法在 alembic.ini
.
为了以正确的编码接受和保存数据,我通过调用 op.execute('SET NAMES utf8');
手动设置了字符集。因此完整的代码如下所示:
def upgrade():
op.create_table(
'currency',
Column('id', Integer, primary_key=True),
Column('name', Unicode(120), nullable=False),
Column('abbr', String(3), nullable=False)
)
op.execute('SET NAMES utf8')
op.execute(u'INSERT INTO currency SET name="{}", abbr="{}";'.format(u"Гривня", "UAH"))
结果如预期:
mysql> SELECT * FROM currency;
+----+----------------------------+------+
| id | name | abbr |
+----+----------------------------+------+
| 1 | Гривня | UAH |
+----+----------------------------+------+