Вставка Unicode-значений при миграции в alembic

Я работаю над небольшим пэт-проектом, который включает в себя учет в нескольких валютах. Во время его разработки я решил перейти от простой настройки БД к миграции БД с использованием alembic. А при некоторых миграциях мне нужно заполнить БД начальными валютами, которые отображаются на украинском языке.

Моя проблема в том, что данные, заполняемые из сценариев миграции alembic, сохраняются в какой-то неизвестной кодировке, поэтому я не могу использовать их в приложении (которое должно быть читаемым человеком). Мои настройки, а также сценарий:

alembic.ini

...
sqlalchemy.url = mysql+pymysql://defaultuser:defaultpwd@localhost/petdb
...

перегонный куб / версия /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"))

После проверки таблицы currency из клиента mysql или mysql-workbench он отображается как:

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 при переносе, которые будут храниться в правильной кодировке. Я что-то пропустил?

1 ответ

Решение

После более расширенного анализа я обнаружил, что MySQL хранит все данные в кодировке "windows-1252". В руководстве MySQL (раздел " Западноевропейские наборы символов") об этой проблеме говорится:

latin1 - набор символов по умолчанию. Латинский1 в MySQL совпадает с набором символов 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  |
+----+----------------------------+------+
Другие вопросы по тегам