请查看Paul的以下回应,以获取有关与Django / South较新版本兼容的一些说明。
这似乎是一个有趣的问题,并且我正成为南方的忠实拥护者,所以我决定对此进行一些研究。我根据您上面描述的摘要构建了一个测试项目,并成功地使用South执行了您要的迁移。在使用代码之前,有一些注意事项:
南方文档建议将架构迁移和数据迁移分开进行。我在这方面也遵循了。
在后端,Django通过在继承模型上自动创建OneToOne字段来表示继承的表
理解了这一点,我们的South迁移需要手动正确地处理OneToOne字段,但是,在尝试进行此操作时,South(或Django本身)似乎无法在多个具有相同名称的继承表上创建一个OneToOne。因此,我将Movies / tv应用程序中的每个子表重命名为其各自的应用程序(即MovieVideoFile / ShowVideoFile)。
在使用实际的数据迁移代码时,South似乎更喜欢先创建OneToOne字段,然后再为其分配数据。在创建期间将数据分配给OneToOne字段会导致South窒息。(为南方的所有凉爽做出公平的妥协)。
说了这么多,我试图保留发出的控制台命令的日志。我将在必要时插入评论。最终代码在底部。
命令历史
django-admin.py startproject southtestmanage.py startapp moviesmanage.py startapp tvmanage.py syncdbmanage.py startmigration movies --initialmanage.py startmigration tv --initialmanage.py migratemanage.py shell # added some fake data...manage.py startapp mediamanage.py startmigration media --initialmanage.py migrate# edited pre, wrote new models, but left old ones intactmanage.py startmigration movies unified-videofile --auto# create a new (blank) migration to hand-write data migrationmanage.py startmigration movies videofile-to-movievideofile-data manage.py migrate# edited pre, wrote new models, but left old ones intactmanage.py startmigration tv unified-videofile --auto# create a new (blank) migration to hand-write data migrationmanage.py startmigration tv videofile-to-movievideofile-datamanage.py migrate# removed old VideoFile model from appsmanage.py startmigration movies removed-videofile --automanage.py startmigration tv removed-videofile --automanage.py migrate
为了节省空间,并且由于模型最终总是看起来相同,因此我仅使用“电影”应用程序进行演示。
电影/models.py
from django.db import modelsfrom media.models import VideoFile as baseVideoFile# This model remains until the last migration, which deletes # it from the schema. Note the name conflict with media.modelsclass VideoFile(models.Model): movie = models.ForeignKey(Movie, blank=True, null=True) name = models.CharField(max_length=1024, blank=True) size = models.IntegerField(blank=True, null=True) ctime = models.DateTimeField(blank=True, null=True)class MovieVideoFile(baseVideoFile): movie = models.ForeignKey(Movie, blank=True, null=True, related_name='shows')
电影/迁移/0002_unified-videofile.py(模式迁移)
from south.db import dbfrom django.db import modelsfrom movies.models import *class Migration: def forwards(self, orm): # Adding model 'MovieVideoFile' db.create_table('movies_movievideofile', ( ('videofile_ptr', orm['movies.movievideofile:videofile_ptr']), ('movie', orm['movies.movievideofile:movie']), )) db.send_create_signal('movies', ['MovieVideoFile']) def backwards(self, orm): # Deleting model 'MovieVideoFile' db.delete_table('movies_movievideofile')电影/迁移/0003_videofile-to-movievideofile-data.py(数据迁移)
from south.db import dbfrom django.db import modelsfrom movies.models import *class Migration: def forwards(self, orm): for movie in orm['movies.videofile'].objects.all(): new_movie = orm.MovieVideoFile.objects.create(movie = movie.movie,) new_movie.videofile_ptr = orm['media.VideoFile'].objects.create() # videofile_ptr must be created first before values can be assigned new_movie.videofile_ptr.name = movie.name new_movie.videofile_ptr.size = movie.size new_movie.videofile_ptr.ctime = movie.ctime new_movie.videofile_ptr.save() def backwards(self, orm): print 'No Backwards'
南真棒!
好的,标准免责声明:您正在处理实时数据。我在这里已经为您提供了工作代码,但是请使用
--db-dry-run来测试您的架构。在尝试任何操作之前,请务必进行备份,并且通常要格外小心。
兼容性通知
我将保留原始消息,但South已将命令更改
manage.py startmigration为
manage.py schemamigration。



