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

问题:您试图将非空字段’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)

有哪些选择?

I know that from Django 1.7 I don’t need to use South or any other migration system, so I am just using simple command python manage.py makemigrations

However, all I get is this error:

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).

Here is models.py:

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

What are options?


回答 0

您需要提供一个默认值:

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

You need to provide a default value:

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

回答 1

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

rm  your_app/migrations/*

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

If you are in early development cycle and don’t care about your current database data you can just remove it and then migrate. But first you need to clean migrations dir and remove its rows from table (django_migrations)

rm  your_app/migrations/*

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

回答 2

一种选择是声明“ 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)

One option is to declare a default value for ‘new_field’:

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

another option is to declare ‘new_field’ as a nullable field:

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

If you decide to accept ‘new_field’ as a nullable field you may want to accept ‘no input’ as valid input for ‘new_field’. Then you have to add the blank=True statement as well:

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

Even with null=True and/or blank=True you can add a default value if necessary:

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

回答 3

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

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

If you are early into the development cycle you can try this –

Remove/comment that model and all its usages. Apply migrations. That would delete that model and then add the model again, run migrations and you have a clean model with the new field added.


回答 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)

If “website” can be empty than new_field should also be set to be empty.

Now if you want to add logic on save where if new_field is empty to grab the value from “website” all you need to do is override the save function for your Model like this:

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)

回答 5

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

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

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

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

In case anyone is setting a ForeignKey, you can just allow nullable fields without setting a default:

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

If you already have data stored within the database, you can also set a default value:

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

回答 6

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

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

You can’t add reference to table that have already data inside.
Change:

user = models.OneToOneField(User)

to:

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

do:

python manage.py makemigrations
python manage.py migrate

change again:

user = models.OneToOneField(User)

do migration again:

python manage.py makemigrations
python manage.py migrate

回答 7

在new_file中,添加boolean属性null。

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

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

In new_file add the boolean property null.

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

after you run a ./manage.py syncdb for refresh the DB. and finally you run ./manage.py makemigrations and ./manage.py migrate


回答 8

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

创建默认值并使用它

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

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

You can use method from Django Doc from this page https://docs.djangoproject.com/en/1.8/ref/models/fields/#default

Create default and use it

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

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

回答 9

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

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

Do you already have database entries in the table UserProfile? If so, when you add new columns the DB doesn’t know what to set it to because it can’t be NULL. Therefore it asks you what you want to set those fields in the column new_fields to. I had to delete all the rows from this table to solve the problem.

(I know this was answered some time ago, but I just ran into this problem and this was my solution. Hopefully it will help anyone new that sees this)


回答 10

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

I honestly fount the best way to get around this was to just create another model with all the fields that you require and named slightly different. Run migrations. Delete unused model and run migrations again. Voila.


回答 11

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

If you are fine with truncating the table of the model in question, you can specify a one-off default value of None in the prompt. The migration will have superfluous default=None while your code has no default. It can be applied just fine because there’s no data in the table anymore which would require a default.


回答 12

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

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

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

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

I was early in my development cycle, so this may not work for everyone (but I don’t see why it wouldn’t).

I added blank=True, null=True to the columns where I was getting the error. Then I ran the python manage.py makemigrations command.

Immediately after running this command (and before running python manage.py migrate), I removed the blank=True, null=True from all the columns. Then I ran python manage.py makemigrations again. I was given an option to just change the columns myself, which I selected.

Then I ran python manage.py migrate and everything worked well!


回答 13

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

玩得开心!

What Django actually says is:

Userprofile table has data in it and there might be new_field values which are null, but I do not know, so are you sure you want to mark property as non nullable, because if you do you might get an error if there are values with NULL

If you are sure that none of values in the userprofile table are NULL – fell free and ignore the warning.

The best practice in such cases would be to create a RunPython migration to handle empty values as it states in option 2

2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)

In RunPython migration you have to find all UserProfile instances with empty new_field value and put a correct value there (or a default value as Django asks you to set in the model). You will get something like this:

# 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

Have fun!


回答 14

在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")

您需要添加一些默认值。

In 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")

You need to add some values as default.


回答 15

如果使用SSH,它有2个选项,请选择数字1,然后输入“无”。只是……暂时。

If the SSH it gives you 2 options, choose number 1, and put “None”. Just that…for the moment.