因爲工作需要,使用的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的創建。