【问题标题】:how to update model in django by adding new primary key field?如何通过添加新的主键字段来更新 django 中的模型?
【发布时间】:2015-01-29 00:56:52
【问题描述】:

如何将 Django 模型中的默认主键替换为自定义主键字段?

我有一个模型,一开始没有定义主键,因为 django 默认自动添加一个id 字段作为主字段

#models.py
from django.db import models

class Event(models.Model):
    title = models.CharField(max_length=50, unique=True)
    description = models.CharField(max_length=150)

我从django shell添加了一些对象。

>>e = Event('meeting', 'Contents about meeting')
>>e.save()
>>e = Event('party', 'Contents about party')
>>e.save()

然后我需要将自定义字符字段作为主要添加到此模型中。

class Event(models.Model):
    event-id = models.CharField(max_length=50, primary_key=True)
    ...

运行 ma​​kemigrations

$ python manage.py makemigrations
You are trying to add a non-nullable field 'event-id' to event without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and `django.utils.timezone modules` are available, so you can do e.g. timezone.now()
>>> 'meetings'
Migrations for 'blog':
  0002_auto_20141201_0301.py:
    - Remove field id from event
    - Add field event-id to event

但是在运行 migrate 时却抛出了一个错误:

.virtualenvs/env/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 485, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: blog_event__new.event-id

【问题讨论】:

    标签: python django django-models migrate


    【解决方案1】:

    根据我的经验(在此处使用 Django 1.8.*),我在尝试更新已存在的模型的 PK 字段时遇到过类似的情况,与另一个模型有外键关系, 在后端表中有关联的数据。

    您没有指定此模型是否用于 FK 关系,但似乎是这种情况。

    在这种情况下,您收到的错误消息是因为已经存在的数据需要与您请求的更改保持一致——即一个新的领域将是PK。这意味着必须删除当前的 PK 以便 django 来“替换”它们。 (根据文档[1],Django 仅支持每个模型的单个 PK 字段。)

    提供与相关表中当前现有数据匹配的默认值应该可以工作。

    例如:

    class Organization(models.Model):
        # assume former PK field no longer here; name is the new PK
        name = models.CharField(primary_key=True)
    
    class Product(models.Model):
        name = models.CharField(primary_key=True)
        organization = models.ForeignKey(Organization)
    

    如果您要更新 Organization 模型并且产品已经存在,则必须更新现有产品行以引用有效的 Organization PK 值。在迁移过程中,您需要选择现有的Organization PK(例如“R&D”)之一来更新现有产品。

    [1]https://docs.djangoproject.com/en/1.8/topics/db/models/#automatic-primary-key-fields

    【讨论】:

      【解决方案2】:

      当你制作之前的模型时,Django 已经在你的后端建立了一个自动递增的整数 id 作为主键。

      当您尝试运行新模型时,尝试重新创建失败的新主键列。

      另一个原因是,当你创建该字段时,Django 期望为它找不到的每个新行显式定义一个唯一值,因此原因。

      如上一个答案所述,您可以重新创建迁移,然后再次尝试。它应该可以工作..欢呼:-)

      【讨论】:

        【解决方案3】:

        问题是您使字段唯一,然后尝试对表中的所有行使用相同的值。我不确定是否有办法以编程方式提供密钥,但您可以执行以下操作:

        • 删除迁移
        • 从字段中删除 primary_key 属性
        • 进行新的迁移
        • 应用它
        • 填写所有行的值
        • 将 primary_key 属性添加到字段
        • 进行新的迁移
        • 应用它

        这是蛮力式的,但应该足够好用。

        祝你好运!

        【讨论】:

        • 这是否意味着我们必须以与数据库相同的方式更新模型?
        猜你喜欢
        • 1970-01-01
        • 2021-03-21
        • 2020-04-20
        • 1970-01-01
        • 2015-06-10
        • 1970-01-01
        • 2014-08-10
        • 2019-06-26
        • 2017-03-03
        相关资源
        最近更新 更多