【问题标题】:Inserting Unicode values on alembic migration在 alembic 迁移中插入 Unicode 值
【发布时间】:2016-06-29 03:47:47
【问题描述】:

我正在从事一个小型的宠物项目,其中涉及到多种货币的会计。在其开发过程中,我决定从直接的数据库设置转移到使用 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-workbench查看表currency后,显示为:

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 值,这些值将以正确的编码存储。我错过了什么吗?

【问题讨论】:

  • 您是否将collation(在服务器、数据库、表或列上)设置为 UTF-8 排序规则?
  • 是的。 mysql> 显示创建表货币; |表 |创建表 +----------+------------------------------------ ---------------------+ |货币 |创建表currency (id int(11) NOT NULL AUTO_INCREMENT, name varchar(120) COLLATE utf8_unicode_ci NOT NULL, abbr varchar(3) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (@987654333) =InnoDB AUTO_INCREMENT=4 默认字符集=utf8 COLLATE=utf8_unicode_ci |

标签: python python-2.7 unicode sqlalchemy alembic


【解决方案1】:

经过更深入的分析,我发现 MySQL 将所有数据保存在“windows-1252”编码中。 MySQL 手册(“West European Character Sets”部分)对此问题的陈述如下:

latin1 是默认字符集。 MySQL 的 latin1 与 Windows cp1252 字符集相同。

看起来 MySQL 忽略了 character_set_client,我认为它是“utf-8”,或者 SQLAlchemy / alembic 没有通知服务器接受数据作为“UTF-8”编码数据。不幸的是,推荐选项 '?charset=utf8' 无法在 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  |
+----+----------------------------+------+

【讨论】:

    猜你喜欢
    • 2016-09-06
    • 2013-07-04
    • 2014-05-18
    • 2013-07-06
    • 2020-02-17
    • 2014-12-02
    • 1970-01-01
    • 2013-03-17
    • 2020-04-20
    相关资源
    最近更新 更多