4

我有一个模型

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 迁移它时,似乎无法使用 null=False 创建它。我有这个消息:

字段“Mystery.player”没有指定默认值,但不为空。由于您要添加此字段,因此您必须指定用于现有行的默认值。您是否希望:
1. 立即退出,并在 models.py 中为字段添加默认值
2. 立即指定一次性值以用于现有列

我使用这个命令:

manage.py schemamigration myapp --auto

非常感谢 !

4

3 回答 3

11

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

步骤 1. 创建新模型并允许 player 为空: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使.playernull=False

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

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

于 2014-03-24T17:56:17.823 回答
5

另一种选择是在添加 ForeignKey 之前创建数据迁移,您可以在其中创建具有特定 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 添加到您的 Misery 类并再次迁移架构。它将要求您的数据迁移 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 命令,它将按顺序执行迁移,插入新 Player 并使用对新 Player 的引用更新所有 Mistery 行。

于 2013-07-16T09:37:26.237 回答
2

如果您的数据库已经包含神秘对象,那么南必须知道在player字段中输入了什么值,因为它不能为空。

一种可能的解决方案:

选择

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

然后输入 1。因此,您所有现有的神秘对象现在都将指向具有 pk = 1 的 Player。然后您可以在管理页面中更改(如果需要)它。

于 2013-04-25T09:17:29.940 回答