您试图将非空字段'new_field'添加到用户配置文件中,而没有默认设置


108

我知道从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)

有哪些选择?


3
我想补充一点,该问题是在更改现有表时发生的,而不是在创建新表时发生的。
x-yuri

Answers:


91

您需要提供一个默认值:

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

如果我需要new_field网站字段的副本该怎么办。那应该看起来如何?default = website没有做这份工作
IrmantasŽelionis2014年

7
您可能希望首先使用假的默认值进行迁移,然后创建数据迁移以遍历每个记录并将其设置new_fieldwebsite
dgel 2014年

CharField的默认值应为可选
佛罗伦萨

87

如果您处于早期开发周期,并且不关心当前的数据库数据,则可以将其删除然后迁移。但是首先,您需要清除迁移目录并从表中删除其行(django_migrations)

rm  your_app/migrations/*

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

8
还有一件事。您需要清理迁移表,例如:mysql -u[user] [database] -e "delete from django_migrations where app=[your_app]"
helpe 2015年

就是这样 我认为Django在迁移和模型检测等方面很烂。想要对此进行重大更新。
WesternGun

我已从迁移中删除了所有文件,并从django_migrations中删除了所有行,现在我在运行时收到“ django.db.migrations.exceptions.NodeNotFoundError:迁移故事。0001_initial依赖项引用了不存在的父节点('源','0002_auto_20180903_1224')“移民。
brainLoop

1
另外,请确保您不要__init__.py 从迁移中删除,或者稍后将其还原,否则makemigrations将无法正常工作stackoverflow.com/a/46362750/1649917
nmu

python manage.py sqlmigrate name_of_your_app nb_of_the_migration还需要
zar3bski

37

一种选择是声明“ 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”作为可为空的字段,则可能要接受“无输入”作为“ 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)

7
«避免在基于字符串的字段(例如CharField和TextField)上使用null。如果基于字符串的字段的值为null = True,则表示它有两个可能的“无数据”值:NULL和空字符串。» — 模型领域参考
Chema

7

如果您处于开发周期的初期,可以尝试以下方法-

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


并按照此处概述的方式清理迁移表django_migrations:stackoverflow.com/questions/26185687/…或仅使用GUI并删除所需的行。
RusI

4

如果“网站”可以为空,new_field则还应该设置为空。

现在,如果您要在保存上添加逻辑,如果if 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)

4

如果有人设置ForeignKey,则可以只允许设置可为空的字段,而无需设置默认值:

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

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

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

3

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

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

2

在new_file中,添加boolean属性null。

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

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



2

表中是否已经有数据库条目UserProfile?如果是这样,那么当您添加新列时,数据库就不会知道将其设置为的原因NULL。因此,它询问您要将列中的那些字段设置为什么new_fields。我必须删除该表中的所有行以解决问题。

(我知道这是在一段时间前回答的,但是我只是遇到了这个问题,这是我的解决方案。希望它将对任何看到此问题的新人有所帮助)


1
我还没有在表中插入行,仍然可以得到它。正如Tomasz所建议的,我必须删除所有迁移历史记录,清除迁移表以更改模型。
WesternGun

1

老实说,我认为最好的解决方法是使用所需的所有字段创建另一个模型,并命名稍有不同。运行迁移。删除未使用的模型,然后再次运行迁移。瞧


1

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


1

我还处于开发周期的初期,所以这可能并不适合所有人(但我不明白为什么不行)。

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

在运行此命令后(以及在运行之前python manage.py migrate),我立即blank=True, null=True从所有列中删除了。然后我又跑python manage.py makemigrations了。我可以选择自己更改列。

然后我跑了python manage.py migrate,一切顺利!


0

Django实际说的是:

Userprofile表中有数据,并且可能new_field有空值,但我不知道,所以您确定要将属性标记为不可空值,因为如果这样做,如果存在带有NULL的值,则可能会出错

如果您确定userprofile表中的所有值都不为NULL-请放心使用,并忽略该警告。

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

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

在RunPython迁移中,您必须找到所有UserProfile具有空new_field值的实例,然后在其中放置正确的值(或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

玩得开心!


我似乎找不到在文档中写的位置。您能发布链接吗
Cody

0

在models.py中

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

您需要添加一些默认值。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.