Python Django:您正在尝试添加一个不可为空的字段';slug';在没有违约的情况下发布;我们可以';不要那样做

Python Django:您正在尝试添加一个不可为空的字段';slug';在没有违约的情况下发布;我们可以';不要那样做,python,django,slug,Python,Django,Slug,我正在尝试添加slug,以便在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

我正在尝试添加slug,以便在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)

Django无法在此处不允许使用
null
值的情况下自行添加新字段,尤其是在此字段上设置了
unique=True
时。要解决该问题,必须分步骤执行:

  • 添加具有
    null=True
    或不具有
    unique=True
    且具有某些默认值的列
  • 确保数据库中的所有记录都具有唯一值
  • 将字段更改为最终状态
  • 所有这些操作都可以通过3次迁移完成。下面是执行此操作的详细步骤。继续之前,请确保删除在以前解决该问题的尝试中创建的所有迁移。您可能必须从能够成功应用迁移的环境中撤消这些迁移

    1.添加具有
    null=True
    或不具有
    unique=True
    且具有某些默认值的列 您可以让Django为您创建此迁移。只需编辑字段,使其看起来像:

        slug = models.SlugField(unique=True, null=True)
    
    然后运行
    /manage.py makemigrations

    2.确保数据库中的所有记录都具有唯一值。 在某种程度上,这一步骤必须手工制作。首先,通过调用
    /manage.py makemigrations-YOUR\u-APP\u-NAME--empty
    ,让Django为您创建新的空迁移。现在打开这个新的迁移文件,并在
    迁移
    类之前添加此代码(根据您的需要进行相应调整,尤其要确保为每个记录生成唯一的值):

    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
    类中的
    operations
    列表中:

    migrations.RunPython(populate_posts_slug_field, migrations.RunPython.noop),
    
    (RunPython的第二个参数是一个特殊函数,它完全不做任何事情,当您想要取消应用此迁移时,它将被执行)

    3.将字段更改为最终状态。 这也可以由Django自己处理。将字段更改为最终状态(如您的问题所示),然后再次运行
    /manage.py makemigrations

    你都准备好了。现在运行
    /manage.py migrate
    应该会成功


    注意:可以在单个迁移文件中运行所有3个操作,但应避免。在一次迁移中同时运行数据和架构更改可能会导致某些数据库后端出现问题,因此应该完全避免。

    这意味着您尝试在数据库中添加一个新列,但在表
    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)
    • 再次迁移

    我现在收到这个错误“django.db.utils.IntegrityError:UNIQUE constraint failed:new\uu blog\u post.slug”这是否回答了您的问题?如何“填充现有行”?这是Celcuk答案的第3步,因为它已成功迁移,但在删除“null=True”后显示相同的错误。您必须为现有行输入所需的值,或者可能编写脚本来更新这些值。对于现有行的slug应该是什么,没有一个内置的概念。