Home » Uncategorized » 使用peewee_migrate来进行数据库结构自动迁移

使用peewee_migrate来进行数据库结构自动迁移

因为工作需要,使用的orm工具为peewee。peewee号称轻量级的orm,果然不假,核心代码就四千多行,也满足了工作的基本要求。可是peewee不像SQLAlchemy有alembic或者Django有South,peewee没有自动对数据库进行DDL语句升级的工具。其在playhouse自带了一个手动的migrator,留着以后扩展用的。但身为程序员怎么能忍受手动的事情呢?本着能躺着就不坐着的心态,能自动的就让他自动呗。于是上github搜索,果不其然,人家已经造好轮子了,peewee_migrate。今天就来聊聊怎么使用它,具体文档他的github也有,大家可以自行去看看。

首先我们先用peewee创建一个model.py:



















import peewee as pw

db = pw.MySQLDatabase(
    host='127.0.0.1', user='root', passwd='password', database='pw_migrate', charset='utf8')


class BaseModel(pw.Model):
    class Meta:
        database = db


class Person(BaseModel):
    name = pw.CharField()
    birthday = pw.DateField()
    is_relative = pw.BooleanField()

class Pet(BaseModel):
    owner = pw.ForeignKeyField(Person, related_name='pets')
    name = pw.CharField()
    animal_type = pw.CharField()

然后我们使用peewe_migrate来创建表pw_migrate.py:










import model
from peewee_migrate import Router

model.db.connect()

router = Router(model.db)

router.create(auto=model)
router.run()

model.db.close()

运行pw_migrate.py,会生成一个001_auto.py的文件,用于迁移的。上面的命令中就是用router.create(auto=model)来生成这个文件的。然后使用router.run()来操作数据库,生成相应的表。其中生成的表中有一张名为migratehistory,是用来记录你迁移成功了哪些文件。如果你按我上面那样进行,如无意外会有多一张表:basemodel,很明显我们并不想要生成他,所以可以这样做。

router = Router(model.db, ignore='basemodel')

这样便不会生成basemodel这张表,当然peewe_migrate 也提供rollback功能:

router.rollback('001_auto')

如果你在上一步生成了basemodel这张表会无法rollback的,只能注释调001_auto.py文件的相应部分,并且手动删除这张表。

讲了这么多,才到我们真正主要的部分,自动迁移。跟alembic或者South一样,你只需要修改你的model部分就可以进行迁移了。




class Pet(BaseModel):
    owner = pw.ForeignKeyField(Person, related_name='pets')
    name = pw.CharField()
    animal_type = pw.CharField()
    birthday = pw.DateField(null=True)

 

在运行pw_migrate.py原来的pet表就会多了birthday字段了。一切如此简单,真是惬意。当然peewee_migrate的代码也写的很不错,并且代码量不多,如果你对peewee足够熟悉可以上去阅读学习。

另外,如果你的数据库已经有了数据,且不想删除它,可以这样:

router.run(fake=True)

这样可以避免重复创建已有表的错误。

当然peewee_migrate还在不断进行维护和更新当中,使用过程中会不少bug,比如说,尚未支持联合外键的创建字段的约束也无法自动生成,当然像rename这些都是要手动的,不然会导致数据的丢失,因为自动生成的操作是删除旧的字段,重新生成你所重命名的字段。如果使用 from peewee import * 也会迁移失败。还有现在还不支持外键的更改,主要是peewee那边的外键更改支持有bug。

在我fork的分支上针对mysql支持的以上的内容,github。当然你要配套里面的peewee才能支持外键更改,另外对DateField支持datetime.datetime.now的创建。