15 十月

Django 1.7 Migration

雖然之前就有用 South, 基本上是一樣的東西, 但是當 Django 1.7 把他納入成為 Migration 之後, 就有種扶正的感覺, 當然也開心的使用、試用。

其中一個我很喜歡的功能是 RunPython。他可以讓你執行 arbitrary code, 也許是新增一些你想要的 fixtures, 或是針對你想要的狀況作一些資料的轉換、增減等等。

不過如果你按照官方文件上面的作法, 可能有些 behavior 會跟預期的不同。例如以下的 code

def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    # if we directly import it, it'll be the wrong version
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).bulk_create([
        Country(name="USA", code="us"),
        Country(name="France", code="fr"),
    ])

你可能會預期 Country 就是跟你現在 models.py 裡頭的 Country 一樣。但事實上, 他是依照整個 migrations 裡頭依序建構出來的 models。譬如說, 假設 0005_blablabla.py 定義了 Country, 但是上述的 procedure 是在 0004_blablabla.py, 那麼當 django 在 migrate 的時候, get_model 就會噴錯告訴你找不到 Country。

因此, dependency 要做好… (雖然 documentation 有提到, 但有時候看到 sample code 太興奮就直接用了 XD 最後 trace code 才發現是怎麼回事 orz)

另外還有一件事情就是他的 schema_editor 有提供一些 functions, 例如 alter_db_table(…) 可以把一個 table 改名字, 或是 create_model、delete_model 等, 但由於這些東西你可能會寫在 RunPython 呼叫的 function 裡頭, 導致 django migration 在 traverse 整個 migration tree 的時候無法追蹤, 因此就會造成不一致的狀況。其實目前也不知道這是該怎麼解… 所以… 就盡量避免使用吧。