首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django从模型CharField引入了一个外键

问Django从模型CharField引入了一个外键
EN

Stack Overflow用户
提问于 2016-05-21 01:54:24
回答 2查看 798关注 0票数 1

我已经将10,000多条记录从我的旧mySQL数据库迁移到Django/sqlite。在我以前的mysql的歌曲表中,艺术家字段不是1比多的字段,而是一个mysql varchar字段。在我的新Django模型中,我将artist字段转换为一个ForeignKey,并使用temp_artist临时从旧数据库存储艺术家的名字。

如何基于temp_artist字段创建每个歌曲实例的艺术家foreignkey?我假设我应该使用经理的get_or_create方法,但是我应该在哪里以及如何编写代码呢?

我的模型如下:

代码语言:javascript
复制
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")
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-21 03:39:08

由于您目前没有可用的外键,所以必须深入到raw_sql。如果仍然使用mysql,则可以使用UPDATE语法。但不幸的是,Sqlite不支持更新连接。

幸运的是,您只有几千行,这使得迭代它们并单独更新每一行成为可能。

代码语言:javascript
复制
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,但它确实允许您使用子查询设置一个值。所以这也是可行的。

代码语言:javascript
复制
UPDATE myapp_song set artist_id = 
  (SELECT id from myapp_artist WHERE name = myapp_song.temp_artist)

在sqlite控制台或GUI中键入它。确保将myapp替换为您自己的应用程序名。这将是非常快的,因为它是一个单一的查询。所有其他解决方案,包括我在这个答案中的替代解决方案,都涉及10,000个查询。

编辑2

如果你的艺术家表现在是空的,在你做所有这些之前,你必须填充它,下面是一个简单的查询。

代码语言:javascript
复制
INSERT INTO stackoverflow_artist(name)
   SELECT distinct temp_artist from stackoverflow_song

注意,您应该在Artist.name上有一个唯一的索引。

票数 1
EN

Stack Overflow用户

发布于 2016-05-21 03:39:21

您可以编写一个为您执行此逻辑的自定义管理命令。文档为如何设置它提供了很好的指导。命令代码如下所示:

代码语言:javascript
复制
# 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运行管理命令。一旦完成并验证了这一点,您就可以从模型中删除临时字段。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37358120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档