您正在尝试向用户配置文件添加一个不可为空的字段‘ new_field’,但没有默认值

我知道从 Django 1.7我不需要使用 South 或任何其他迁移系统,所以我只是使用简单的命令 python manage.py makemigrations

然而,我得到的只是这个错误:

You are trying to add a non-nullable field 'new_field' to userprofile without a default;
we can't do that (the database needs something to populate existing rows).

下面是 models.py:

class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True)
new_field = models.CharField(max_length=140)

有什么选择?

248187 次浏览

您需要提供一个默认值:

new_field = models.CharField(max_length=140, default='SOME STRING')

如果“网站”可以是空的,那么 new_field也应该设置为空。

现在,如果你想添加逻辑保存,如果 new_field是空的,从“网站”获取值,所有你需要做的就是覆盖你的 Model的保存功能,像这样:

class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True, default='DEFAULT VALUE')
new_field = models.CharField(max_length=140, blank=True, default='DEFAULT VALUE')


def save(self, *args, **kwargs):
if not self.new_field:
# Setting the value of new_field with website's value
self.new_field = self.website


# Saving the object with the default save() function
super(UserProfile, self).save(*args, **kwargs)

一种选择是为‘ new _ field’声明一个默认值:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE')

另一种选择是将‘ new _ field’声明为可为空的字段:

new_field = models.CharField(max_length=140, null=True)

如果您决定接受‘ new _ field’作为可为空的字段,那么您可能希望接受‘ no input’作为‘ new _ field’的有效输入。然后,你还必须添加 blank=True语句:

new_field = models.CharField(max_length=140, blank=True, null=True)

即使使用 null=True和/或 blank=True,如果需要,也可以添加默认值:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE', blank=True, null=True)

在 new _ file 中添加 boolean 属性 null。

new_field = models.CharField(max_length=140, null=True)

在运行 ./manage.py syncdb刷新数据库之后。 最后运行 ./manage.py makemigrations./manage.py migrate

如果 你处于早期开发周期和 我不在乎关于你当前的 数据库数据,你可以移除它,然后迁移。但是首先您需要清理迁移目录并从表中删除它的行(django _ mobilations)

rm  your_app/migrations/*

注意: 不要删除迁移文件夹中的 _ _ init _ _. py。

rm db.sqlite3
python manage.py makemigrations
python manage.py migrate

如果您之前为 Django 的 Admin web 应用程序创建了一个超级用户,那么您可能需要再次创建该用户。

UserProfile中已经有数据库条目了吗?如果是这样,当您添加新的列时,数据库不知道要将其设置为什么,因为它不能是 NULL。因此,它会询问您希望将 new_fields列中的这些字段设置为什么。为了解决这个问题,我必须将这个表中的所有行都用 删除表示。

(我知道这个问题早就有答案了,但是我只是碰到了这个问题,这就是我的解决方案。希望它能帮助任何看到这一点的新人)

您可以使用本页 https://docs.djangoproject.com/en/1.8/ref/models/fields/#default中 Django Doc 的方法

创建默认值并使用它

def contact_default():
return {"email": "to1@example.com"}


contact_info = JSONField("ContactInfo", default=contact_default)

如果你很早就进入了开发周期,你可以试试这个-

删除/注释该模型及其所有用法。应用迁移。这将删除该模型,然后再次添加该模型,运行迁移,您就拥有了一个添加了新字段的干净模型。

姜戈实际上说的是:

Userprofile 表中有数据,可能有 new_field值 但我不知道,所以你确定要标记 属性为非空,因为如果您这样做,您可能会得到一个错误,如果 有一些值为 NULL

如果确定 userprofile表中没有一个值为 NULL-fall free,则忽略该警告。

在这种情况下,最佳实践是创建一个 RunPython 迁移来处理选项2中所述的空值

2)暂时忽略,让我自己处理现有的 NULL 行(例如,因为您在以前的数据迁移中添加了一个 RunPython 或 RunSQL 操作来处理 NULL 值)

在 RunPython 迁移中,您必须找到所有具有空 new_field值的 UserProfile实例,并在其中放置一个正确的值(或者按照 Django 要求在模型中设置的默认值)。 你会得到这样的东西:

# please keep in mind that new_value can be an empty string. You decide whether it is a correct value.
for profile in UserProfile.objects.filter(new_value__isnull=True).iterator():
profile.new_value = calculate_value(profile)
profile.save() # better to use batch save

玩得开心!

老实说,我发现解决这个问题的最好方法就是创建另一个模型,其中包含您需要的所有字段,并且命名略有不同。运行迁移。删除未使用的模型并再次运行迁移。瞧。

如果 SSH 给了你2个选项,选择1,然后输入“无”。就是这样... ... 暂时的。

不能添加对已有数据的表的引用。
改变:

user = models.OneToOneField(User)

致:

user = models.OneToOneField(User, default = "")

做:

python manage.py makemigrations
python manage.py migrate

再次改变:

user = models.OneToOneField(User)

再次移民:

python manage.py makemigrations
python manage.py migrate

如果可以截断有问题的模型的表,那么可以在提示符中指定一次性的默认值 None。迁移将有多余的 default=None,而您的代码没有默认值。它可以很好地应用,因为表中不再有需要默认值的数据。

在 Models.py

类 UserProfile (Model. Model) : User = model. OneToOneField (User) Site = models.URLField (空白 = True) New _ field = model. CharField (max _ length = 140,default = “ some _ value”)

您需要添加一些默认值。

我在开发周期的早期,所以这可能不适用于每个人(但我不知道为什么不适用)。

我将 blank=True, null=True添加到出现错误的列中,然后运行 python manage.py makemigrations命令。

在运行这个命令之后(以及运行 python manage.py migrate之前) ,我立即从所有列中删除了 blank=True, null=True。然后我再次运行 python manage.py makemigrations。我有一个选项,只是改变自己的专栏,这是我选择的。

然后我运行 python manage.py migrate,一切都很好!

如果有人正在设置 ForeignKey,您可以只允许可为空的字段,而不设置默认值:

new_field = models.ForeignKey(model, null=True)

如果已经在数据库中存储了数据,还可以设置默认值:

new_field = models.ForeignKey(model, default=<existing model id here>)

基本上我解决了这个问题把 null=True在增加的模型。 例如:

我试图在现有的数据库模块中添加 phone _ number。

phone_number = models.CharField(max_length=10)

我之前得到了这个错误:

您正在尝试向客户添加一个不可为空的字段‘ phone _ number’ 没有默认值; 我们不能这样做(数据库需要 填充现有行)。请选择修复:

  1. 提供一次性服务 Default now (将在所有现有行上设置,空值为 本栏)
  2. 退出,并让我添加一个 models.py 中的默认值

在把

phone_number = models.CharField(max_length=10, null=True)


python manage.py makemigrations
Migrations for 'collegekhajagharapp':
collegekhajagharapp\migrations\0002_customer_phone_number.py
- Add field phone_number to customer

如果您的表格是新的,并且您不关心数据,请按照以下步骤操作:

  1. Delete FROM public.django_migrations where app=<your_app_name>
  2. Delete all migrations file from your project
  3. DROP table <your_table_name>
  4. python manage.py makemigrations
  5. python manage.py migrate

如果您关心数据,那么将默认值添加到字段中

new_field = models.CharField(max_length=140, default='your_default_value')

这里有一个不需要做出妥协的解决方案,比如删除所有现有的数据/迁移(yikes) ,需要两个独立的迁移,或者设置一个不需要的默认值。采取以下步骤:

  1. 使用 null=False将新字段添加到模型中
  2. python manage.py makemigrations <app_name> --name <migration_name>
  3. 将新字段更改为 null=True
  4. python manage.py makemigrations <app_name>.在这个步骤中,您将看到一个您以前可能从未见过的选项!您需要选项2: “现在忽略,让我自己用 NULL 处理现有的行(例如,因为您在以前的数据迁移中添加了一个 RunPython 或 RunSQL 操作来处理 NULL 值)”enter image description here
  5. migrations.AlterField操作从第二次迁移移到第一次迁移,并添加一个手动迁移来处理 NULL值(如果不执行这个步骤,您将像前面那样得到完整性错误) ,如下所示:
def initial_display_names(apps, schema):
Player = apps.get_model('my_app', 'Player')
Player.objects.all().update(display_name='Cool Name')


def reversal(*args):
"""Reversal is NOOP since display_name is simply dropped during reverse"""




class Migration(migrations.Migration):


dependencies = [
('my_app', '0049_foo'),
]


operations = [
migrations.AddField(
model_name='player',
name='display_name',
field=models.CharField(help_text='name as shown in the UI', max_length=256, null=True),
),
migrations.RunPython(initial_display_names, reversal),
migrations.AlterField(
model_name='player',
name='display_name',
field=models.CharField(help_text='name as shown in the UI', max_length=256),
),
]
  1. 删除第二次迁移。
  2. python manage.py migrate <app_name>

删除模型 = > Mak颗粒移出模型 = > 迁移模型 = > 返回模型 = > Mak颗粒移出模型 = > 迁移模型