Django South - 创建非空的ForeignKey

时间:2013-04-25 08:45:37

标签: django django-models django-south

我有一个模特

class Mystery(models.Model):
    first = models.CharField(max_length=256)
    second = models.CharField(max_length=256)
    third = models.CharField(max_length=256)
    player = models.ForeignKey(Player)

我添加了播放器ForeignKey但是当我尝试使用South迁移它时,似乎我无法创建这个whith null = False。我有这样的信息:

  

字段'Mystery.player'没有指定默认值,但是   不是NULL。由于您要添加此字段,因此必须指定默认值   用于现有行的值。你想要:
   1.立即退出,并在models.py中的字段中添加默认值    2.指定现在用于现有列的一次性值

我使用这个命令:

  

manage.py schemamigration myapp --auto

非常感谢!

3 个答案:

答案 0 :(得分:11)

这最好在3次迁移中完成。

步骤1.创建新模型并允许玩家为空:player = models.ForeignKey(Player, null=True)

步骤2.运行./manage.py schemamigration <app> --auto

步骤3.运行./manage.py datamigration <app> set_default_players

步骤4.在<app>/migrations/<number>_set_default_players.py中向前和向后更新,以使用您喜欢的任何逻辑来设置默认播放器。确保每个Mystery对象都具有player的值。

步骤5.更新Mystery模型,以便player拥有null=False

步骤6.运行./manage.py schemamigration <app> --auto

步骤7.运行./manage.py migrate <app>

答案 1 :(得分:5)

另一种选择是在添加ForeignKey之前创建data migration,在其中创建具有特定id的新Player实例。请确保以前数据库中不存在该ID。

1.创建数据迁移文件

$ ./manage.py datamigration myapp add_player
Created 00XX_add_player.py

2.编辑文件的转发向后方法:

def forwards(self, orm):
    orm['myapp.Player'].objects.create(name=u'Very misterious player', id=34)

def backwards(self, orm):
    # Haven't tested this one yet
    orm['myapp.Player'].objects.filter(id=34).delete()

3.将ForeignKey添加到您的Mistery类并再次迁移架构。它将要求您的数据迁移ID的默认值,在本例中为34。

 $ ./manage.py schemamigration --auto myapp
 ? The field 'Mistery.player' does not have a default specified, yet is NOT NULL.
 ? Since you are adding this field, you MUST specify a default
 ? value to use for existing rows. Would you like to:
 ?  1. Quit now, and add a default to the field in models.py
 ?  2. Specify a one-off value to use for existing columns now
 ? Please select a choice: 2
 ? Please enter Python code for your one-off default value.
 ? The datetime module is available, so you can do e.g. datetime.date.today()
 >>> 34
 + Added field player on myapp.Mistery
Created 0010_auto__add_field_mistery_player.py. You can now apply this migration with: ./manage.py migrate myapp

4.最后运行migrate命令,它将按顺序执行迁移,插入新播放器并使用对新播放器的引用更新所有Mistery行。

答案 2 :(得分:2)

如果您的数据库已经包含Mystery对象,那么South必须知道放入player字段的值,因为它不能为空。

一种可能的解决方案:

选择

    2. Specify a one-off value to use for existing columns now

然后输入1.因此,所有现有的Mystery对象现在将指向播放器,其中pk = 1.然后您可以在管理页面中更改(如果需要)。