将CharGield中的Django模型字段的类型更改为ForeignKey

问题描述:

我需要将我的某个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

这可能是您想要执行多阶段迁移的情况。我对此的建议看起来如下所示。

首先,让我们假设这是你的初始模型,内部的应用程序调用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

嗯,是的,谢谢你的错误! –