2016-03-14 169 views
5

我需要將我的某個Django模型中的某個字段的類型從CharField更改爲ForeignKey。這些字段已經填充了數據,所以我想知道什麼是最好的或正確的方式來做到這一點。我可以只更新字段類型並遷移嗎?是否有任何可能的「陷阱」需要注意? N.B:我只使用vanilla Django管理操作(makemigrationsmigrate),而不是南方。將CharGield中的Django模型字段的類型更改爲ForeignKey

+2

如果CharField上沒有唯一約束,請留意重複的值?這取決於你之前是否複製數據,或者只是想將它移出到自己的表中。如果是後者,最好的做法取決於你的數據意味着什麼。 Django無法推斷CharField和ForeignKey之間的某種魔術轉換。你必須自己寫一個明智的遷移。 – user234461

+1

我覺得這和你要找的東西很相似。 http://stackoverflow.com/questions/5373906/changing-the-django-data-type-in​​-models-without-droping-the-table – Vibhu

回答

25

這可能是您想要執行多階段遷移的情況。我對此的建議看起來如下所示。

首先,讓我們假設這是你的初始模型,內部的應用程序調用discography

from django.db import models 

class Album(models.Model): 
    name = models.CharField(max_length=255) 
    artist = models.CharField(max_length=255) 

現在,你意識到你想用一個ForeignKey的藝術家來代替。那麼,如上所述,這不僅僅是一個簡單的過程。它必須分幾步完成。

步驟1,添加一個新的領域對於ForeignKey的,確保將其標記爲空:

from django.db import models 

class Album(models.Model): 
    name = models.CharField(max_length=255) 
    artist = models.CharField(max_length=255) 
    artist_link = models.ForeignKey('Artist', null=True) 

class Artist(models.Model): 
    name = models.CharField(max_length=255) 

...創造這種變化遷移。

./manage.py makemigrations discography 

第2步,填充您的新字段。爲了做到這一點,你必須創建一個空的遷移。

./manage.py makemigrations --empty --name transfer_artists discography 

一旦你有了這個空遷移,你想一個RunPython操作,以連結您的記錄添加到它。在這種情況下,它可能是這個樣子:

def link_artists(apps, schema_editor): 
    Album = apps.get_model('discography', 'Album') 
    Artist = apps.get_model('discography', 'Artist') 
    for album in Album.objects.all(): 
     artist, created = Artist.objects.get_or_create(name=album.artist) 
     album.artist_link = artist 
     album.save() 

現在你的數據被轉移到新的領域,你實際上可以做,離開一切,是,使用新的領域的一切。或者,如果您想要進行一些清理,則需要創建兩個以上的遷移。

爲了您的第一次遷移,您需要刪除原始字段artist。對於第二次遷移,請將新字段artist_link重命名爲artist

這是通過多個步驟完成的,以確保Django正確識別操作。你可以手動創建一個遷移來處理這個問題,但我會把它留給你弄清楚。

+0

謝謝你的及時和全面的迴應。這也刺激了我最終坐下來正確學習Django遷移! – ChrisM

+0

不應該是'./manage.py makemigrations --empty ...',但是?第二步有'makemigration'(單數)。 – ChrisM

+0

嗯,是的,謝謝你的錯誤! –

相關問題