2016-03-14 54 views
1

我正在研究一個涉及多種貨幣會計的小型項目。在開發過程中,我決定使用alembic從簡單的DB設置轉移到DB-migrations。而在一些遷移中,我需要用初始貨幣填充數據庫,這些數據以烏克蘭語顯示。在alembic遷移中插入Unicode值

我的問題是從alembic遷移腳本填充的數據正在保存在一些未知的編碼中,所以我不能在應用程序內使用它(這期望是人類可讀的)。是我的設置以及腳本如下:

alembic.ini

... 
sqlalchemy.url = mysql+pymysql://defaultuser:[email protected]/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")) 

MySQL的檢查表currency後客戶端或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值遷移將以正確的編碼進行存儲。我錯過了什麼嗎?

+0

你設置[整理](https://dev.mysql.com/doc/refman/5.7/en /charset-syntax.html)(在服務器,數據庫,表或列上)轉換爲UTF-8歸類? – univerio

+0

是的。 mysql> SHOW CREATE TABLE currency; |表|創建表 + ---------- + ----------------------------------- ---------------------- + |貨幣| CREATE TABLE'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 ') )ENGINE = InnoDB AUTO_INCREMENT = 4 DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci | – wanderlust

回答

0

經過更多擴展分析後,我發現MySQL保留了所有數據的'windows-1252'編碼。 MySQL手冊(部分「West European Character Sets」)指出這個問題爲:

latin1是默認字符集。 MySQL的latin1與Windows cp1252字符集相同。

它看起來像任何的MySQL忽略character_set_client這一點,我認爲是「UTF-8」,或SQLAlchemy的/蒸餾器沒有告知服務器接受的數據爲「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 | 
+----+----------------------------+------+ 
相關問題