Вставка 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 |
+----+----------------------------+------+