Django:您正试图在没有默认值的情况下将 non-nullable 字段 'slug' 添加到 post;我们不能那样做
Django: You are trying to add a non-nullable field 'slug' to post without a default; we can't do that
我正在尝试添加 slug,以便 post 的标题出现在 url 中,但我在控制台上收到此消息:
You are trying to add a non-nullable field 'slug' to post without a default; we can't do that Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.title)
super().save(*args, **kwargs)
如果此处不允许 null
值,Django 无法自行添加新字段,尤其是当您在此字段上设置了 unique=True
时。要解决该问题,您必须按以下步骤执行:
- 添加具有
null=True
或不具有 unique=True
并具有一些默认值的列
- 确保数据库中的所有记录都具有唯一值。
- 将字段更改为最终状态。
您可以通过 3 次迁移完成所有这些操作。以下是执行此操作的详细步骤。在继续之前,请确保删除之前为解决该问题而尝试创建的所有迁移。您可能必须从能够成功应用它们的环境中撤消这些迁移。
1。添加具有 null=True
或不具有 unique=True
且具有一些默认值
的列
您可以让 Django 为您创建此迁移。只需将您的字段编辑为:
slug = models.SlugField(unique=True, null=True)
然后 运行 ./manage.py makemigrations
之后
2。确保数据库中的所有记录都具有唯一值。
这一步在一定程度上需要手工制作。首先要求 Django 通过调用 ./manage.py makemigrations YOUR_APP_NAME --empty
为您创建新的空迁移。现在打开这个新的迁移文件并在 Migration
class:
之前添加此代码(根据您的需要进行调整,特别是确保为每条记录生成唯一值)
def populate_posts_slug_field(apps, schema_editor):
for post in apps.get_model('YOUR_APP_NAME.post'):
post.slug = # generate a unique value for every post here
post.save()
现在,添加一个操作,在执行此迁移时将 运行 上面定义的代码。为此,请将此条目添加到迁移的 Migration
class 中的 operations
列表中:
migrations.RunPython(populate_posts_slug_field, migrations.RunPython.noop),
(RunPython
的第二个参数是一个特殊的函数,它什么都不做,当你想取消应用这个迁移时它会被执行)。
3。将字段更改为最终状态。
这也可以由Django 自己处理。将您的字段更改为最终状态(如您的问题所示)并再次 运行 ./manage.py makemigrations
。
大功告成。 运行 ./manage.py migrate
现在应该成功了。
注意:可以 运行 在单个迁移文件中执行所有 3 个操作,但应避免这样做。 运行 一次迁移中的数据和架构更改都可能导致某些数据库后端出现问题,因此应完全避免。
这意味着您尝试在数据库中添加一个新列,但是 table Post
中存在另一个旧数据。所以旧数据对列 slug
.
没有价值
在这种情况下你需要:
- 添加
null=True
、slug = models.SlugField(unique=True, null=True)
。
- 迁移您的数据库
py manage.py makemigrations
和 py manage.py migrate
。
- 为现有行填充
slug
的数据。
- 删除
null=True
、slug = models.SlugField(unique=True)
- 再次迁移。
尝试转换,转到 models.py 并将“默认”设置为空字符串:
author = models.ForeignKey(User, on_delete=models.CASCADE, default="")
运行 在 shell 上进行迁移。
返回 models.py 并删除默认值。
运行 再次进行迁移。
那应该已经解决了。
如果您不关心您现有的数据,也不关心您的迁移历史,最简单的解决方案是将其全部删除并重新开始。
- 删除数据库
- 删除您的迁移
- 运行
./manage.py makemigrations
- 运行
./manage.py migrate
我正在尝试添加 slug,以便 post 的标题出现在 url 中,但我在控制台上收到此消息:
You are trying to add a non-nullable field 'slug' to post without a default; we can't do that Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.title)
super().save(*args, **kwargs)
如果此处不允许 null
值,Django 无法自行添加新字段,尤其是当您在此字段上设置了 unique=True
时。要解决该问题,您必须按以下步骤执行:
- 添加具有
null=True
或不具有unique=True
并具有一些默认值的列 - 确保数据库中的所有记录都具有唯一值。
- 将字段更改为最终状态。
您可以通过 3 次迁移完成所有这些操作。以下是执行此操作的详细步骤。在继续之前,请确保删除之前为解决该问题而尝试创建的所有迁移。您可能必须从能够成功应用它们的环境中撤消这些迁移。
1。添加具有 null=True
或不具有 unique=True
且具有一些默认值
的列
您可以让 Django 为您创建此迁移。只需将您的字段编辑为:
slug = models.SlugField(unique=True, null=True)
然后 运行 ./manage.py makemigrations
之后
2。确保数据库中的所有记录都具有唯一值。
这一步在一定程度上需要手工制作。首先要求 Django 通过调用 ./manage.py makemigrations YOUR_APP_NAME --empty
为您创建新的空迁移。现在打开这个新的迁移文件并在 Migration
class:
def populate_posts_slug_field(apps, schema_editor):
for post in apps.get_model('YOUR_APP_NAME.post'):
post.slug = # generate a unique value for every post here
post.save()
现在,添加一个操作,在执行此迁移时将 运行 上面定义的代码。为此,请将此条目添加到迁移的 Migration
class 中的 operations
列表中:
migrations.RunPython(populate_posts_slug_field, migrations.RunPython.noop),
(RunPython
的第二个参数是一个特殊的函数,它什么都不做,当你想取消应用这个迁移时它会被执行)。
3。将字段更改为最终状态。
这也可以由Django 自己处理。将您的字段更改为最终状态(如您的问题所示)并再次 运行 ./manage.py makemigrations
。
大功告成。 运行 ./manage.py migrate
现在应该成功了。
注意:可以 运行 在单个迁移文件中执行所有 3 个操作,但应避免这样做。 运行 一次迁移中的数据和架构更改都可能导致某些数据库后端出现问题,因此应完全避免。
这意味着您尝试在数据库中添加一个新列,但是 table Post
中存在另一个旧数据。所以旧数据对列 slug
.
在这种情况下你需要:
- 添加
null=True
、slug = models.SlugField(unique=True, null=True)
。 - 迁移您的数据库
py manage.py makemigrations
和py manage.py migrate
。 - 为现有行填充
slug
的数据。 - 删除
null=True
、slug = models.SlugField(unique=True)
- 再次迁移。
尝试转换,转到 models.py 并将“默认”设置为空字符串:
author = models.ForeignKey(User, on_delete=models.CASCADE, default="")
运行 在 shell 上进行迁移。 返回 models.py 并删除默认值。 运行 再次进行迁移。 那应该已经解决了。
如果您不关心您现有的数据,也不关心您的迁移历史,最简单的解决方案是将其全部删除并重新开始。
- 删除数据库
- 删除您的迁移
- 运行
./manage.py makemigrations
- 运行
./manage.py migrate