将CharGield中的Django模型字段的类型更改为ForeignKey
问题描述:
我需要将我的某个Django模型中的某个字段的类型从CharField
更改为ForeignKey
。这些字段已经填充了数据,所以我想知道什么是最好的或正确的方式来做到这一点。我可以只更新字段类型并迁移吗?是否有任何可能的“陷阱”需要注意? N.B:我只使用vanilla Django管理操作(makemigrations
和migrate
),而不是南方。将CharGield中的Django模型字段的类型更改为ForeignKey
答
这可能是您想要执行多阶段迁移的情况。我对此的建议看起来如下所示。
首先,让我们假设这是你的初始模型,内部的应用程序调用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正确识别操作。你可以手动创建一个迁移来处理这个问题,但我会把它留给你弄清楚。
如果CharField上没有唯一约束,请留意重复的值?这取决于你之前是否复制数据,或者只是想将它移出到自己的表中。如果是后者,最好的做法取决于你的数据意味着什么。 Django无法推断CharField和ForeignKey之间的某种魔术转换。你必须自己写一个明智的迁移。 – user234461
我觉得这和你要找的东西很相似。 http://stackoverflow.com/questions/5373906/changing-the-django-data-type-in-models-without-droping-the-table – Vibhu