ohroy / blog

A super blog lite -- just one page. use vue with github api !
https://blog.6h.work
Do What The F*ck You Want To Public License
148 stars 15 forks source link

flask-migrate的各种骚操作 #24

Open ohroy opened 6 years ago

ohroy commented 6 years ago

自定义版本

很多时候我们可能不能依靠

flask db migrate

这样的话,在修改表名修改字段名等的时候,如果你信赖自动生成的话,那你可能就要瞎了,因为这样的话,他会先删除再创建,你会发现

mmp,我的数据呢!!!

所以,这个时候,你就需要

flask db revision

来创建一个自定义版本,来自己写升级脚本

修改表名

op.rename_table('shop_print_rules', 'label_print_rules')

修改字段名

op.alter_column('label_print_rules', 'box_template_type', new_column_name='template_type',
                existing_type=sa.Enum('single_box', 'all_box', 'pick', 'putaway',
                                      'stockin', 'stockout', 'delivery')
                server_default='single_box')

增加枚举值

这个很蛋疼的问题是,很多时候,你创建一个枚举,然而改动后可能不会被检测到。

op.alter_column('label_print_rules', 'template_type', 
                existing_type=sa.Enum('single_box', 'all_box', 'pick', 'putaway',
                                      'stockin', 'stockout', 'delivery'),
                type_=sa.Enum('single_box', 'all_box', 'pick', 'putaway',
                              'stockin', 'stockout', 'delivery', 'single_picking_label',
                              'multi_picking_label', 'order_picking_label'),
                server_default='single_box')

然后你就会发现,它会提示你

sqlalchemy.exc.CompileError: PostgreSQL ENUM type requires a name.

好吧,这个是sqlalchemy报错了,意思是说这个枚举必须得有一个名字,那我们给加上。

op.alter_column('label_print_rules', 'template_type', 
                existing_type=sa.Enum('single_box', 'all_box', 'pick', 'putaway',
                                      'stockin', 'stockout', 'delivery',name='style'),
                type_=sa.Enum('single_box', 'all_box', 'pick', 'putaway',
                              'stockin', 'stockout', 'delivery', 'single_picking_label',
                              'multi_picking_label', 'order_picking_label',name='style'),
                server_default='single_box')

很好,现在不报错了,然而,仔细检查一下,你会发现,这个代码并不会如你想象中的那样工作。。。

好吧,我们继续一番探索,发现pgsql中的enum类型是一个自定义类型,可以使用

ALTER TYPE xxxxx ADD value 'XXXXX'

来添加, 好吧,那我们修改以上的代码

def upgrade():
    op.execute('ALTER TYPE xxxxx ADD value \'XXXXX\''')

这下总没毛病了吧?然而生活就是这样,你以后生活只是给你一巴掌,那你就错了,他接下来还要给你一脚。

psycopg2.InternalError: ALTER TYPE ... ADD cannot run inside a transaction block

这句话的意识是这条指令不能运行在一个事务中,那怎么办呢。我们灵机一动

def upgrade():
    op.execute('COMMIT')
    op.execute('ALTER TYPE xxxxx ADD value \'XXXXX\''')
ohroy commented 6 years ago

life is short...