我已经将10,000多条记录从我的旧mySQL数据库迁移到Django/sqlite。在我以前的mysql的歌曲表中,艺术家字段不是1比多的字段,而是一个mysql varchar字段。在我的新Django模型中,我将artist字段转换为一个ForeignKey,并使用temp_artist临时从旧数据库存储艺术家的名字。
如何基于temp_artist字段创建每个歌曲实例的艺术家foreignkey?我假设我应该使用经理的get_or_create方法,但是我应该在哪里以及如何编写代码呢?
我的模型如下:
class Artist (models.Model):
name = models.CharField(max_length=100)
class Song (models.Model):
artist = models.ForeignKey(Artist, blank=True, null=True, on_delete=models.CASCADE, verbose_name="Artist")
temp_artist = models.CharField(null=True, blank=True, max_length=100)
title = models.CharField(max_length=100, verbose_name="Title")
duration = models.DurationField(null=True, blank=True, verbose_name="Duration")发布于 2016-05-21 03:39:08
由于您目前没有可用的外键,所以必须深入到raw_sql。如果仍然使用mysql,则可以使用UPDATE语法。但不幸的是,Sqlite不支持更新连接。
幸运的是,您只有几千行,这使得迭代它们并单独更新每一行成为可能。
raw_query = '''SELECT s.*, a.id as fkid
FROM myapp_song s
INNER JOIN myapp_artist a on s.temp_artist = a.name'''
for song in Song.objects.raw(raw_query)
song.artist_id = s.fkid
song.save()这可能需要几分钟才能完成,因为您没有关于temp_artist和名称的索引。注意将myapp替换为应用程序的实际名称。
Edit1:
尽管Sqlite没有update,但它确实允许您使用子查询设置一个值。所以这也是可行的。
UPDATE myapp_song set artist_id =
(SELECT id from myapp_artist WHERE name = myapp_song.temp_artist)在sqlite控制台或GUI中键入它。确保将myapp替换为您自己的应用程序名。这将是非常快的,因为它是一个单一的查询。所有其他解决方案,包括我在这个答案中的替代解决方案,都涉及10,000个查询。
编辑2
如果你的艺术家表现在是空的,在你做所有这些之前,你必须填充它,下面是一个简单的查询。
INSERT INTO stackoverflow_artist(name)
SELECT distinct temp_artist from stackoverflow_song注意,您应该在Artist.name上有一个唯一的索引。
发布于 2016-05-21 03:39:21
您可以编写一个为您执行此逻辑的自定义管理命令。文档为如何设置它提供了很好的指导。命令代码如下所示:
# e.g., migrateauthors.py
from django.core.management.base import BaseCommand
from myapp import models
class Command(BaseCommand):
help = 'Migrate authors from old schema'
def handle(self, *args, **options):
for song in myapp.models.Song.objects.all():
song.artist, _ = models.Artist.objects.get_or_create(name=song.temp_artist)
song.save()然后,只需使用manage.py migrateauthors运行管理命令。一旦完成并验证了这一点,您就可以从模型中删除临时字段。
https://stackoverflow.com/questions/37358120
复制相似问题