繁体   English   中英

编辑外键引用的值时出现 Django IntegrityError

[英]Django IntegrityError when editing a value referenced by a foreign key

我有一个包含两个(相关)模型的应用程序,本质上是一个 CRM:

class StudentTutorRelationshipProfile(models.Model):
    pupil_name = models.CharField(max_length=100, unique=True)
    parent_name = models.CharField(max_length=100)
    ...

class TimeSheet(models.Model):
    user = models.ForeignKey(
        User, on_delete=models.PROTECT, limit_choices_to={"is_tutor": True}
    )
    student = models.ForeignKey(
        StudentTutorRelationshipProfile, on_delete=models.CASCADE, to_field="pupil_name"
    )
   ...

现在有人拼错了一个学生的名字,想在pupil_name中更改它的 student_name,但是因为已经有 TimeSheet 记录的学生名字拼错了, StudentTutorRelationshipProfile引发了一个错误(来自psychog):

ForeignKeyViolation: update or delete on table "invoicing_studenttutorrelationshipprofile" violates foreign key constraint "invoicing_timesheet_student_id_07889dc0_fk_invoicing" on table "invoicing_timesheet"
DETAIL:  Key (pupil_name)=(Student Name) is still referenced from table "invoicing_timesheet".

  File "django/db/backends/base/base.py", line 243, in _commit
    return self.connection.commit()

IntegrityError: update or delete on table "invoicing_studenttutorrelationshipprofile" violates foreign key constraint "invoicing_timesheet_student_id_07889dc0_fk_invoicing" on table "invoicing_timesheet"
DETAIL:  Key (pupil_name)=(Student Name) is still referenced from table "invoicing_timesheet".

更改此数据的好方法是什么? 我也不介意更改历史时间表或将它们保留原样(但不能删除它们),这更容易/不太可能导致问题。 (是的,我依赖唯一的姓名和姓氏组合这一事实并不理想,但目前不会解决这个问题,除非 IntegrityError 的更改也需要一些迁移。

如果有帮助,我正在运行 python 3.6、Django 3.0。

这是一个很好的例子,说明了为什么您永远不想使用可能被更新为外键的列。 其他不良外键候选者是,例如,不应公开的数据、个人或私人数据(如姓名或社会保险号等)。此外,名称不是唯一的,这会自动取消它们作为主标识符等唯一标识符的资格钥匙。

使用 SERIAL 主键或有时使用 UUID 或其他类型的通用、自动生成的标识符更简单、更安全,除了标识行之外没有其他意义。 它尤其不应包含非 ASCII 字符(这也使名称不合格),因为您永远不知道是否可能必须通过无法处理它的系统对其进行 pipe 处理,就像不会说相关语言的人一样( “你好,我的登录名是指鹿为马”)。

在您的情况下,您可以使用 ON UPDATE CASCADE 声明您的外键,以便引用表上的更新级联到引用表。 这只会消除一些烦恼,因为对一行的简单更新可能会导致引用表中的大量更新。

您也可以手动更新所有引用表,但有时 window 期间引用将不一致。 将外键约束设置为 DEFERRED 并在单个事务中进行所有更新可能会起作用。

但是,这不会更新数据库外部内容中的标识符。 例如,如果系统使用基于主键的文件名存储学生的照片,或者写入日志、打印纸或存储任何使用主键作为参考的任何地方......或者如果主键用作url 中的标识符,以及其他网站使用链接中的此标识符链接到您的标识符......然后这些都不会更新,甚至可以更新。

所以,是的,更新或重用主键是一大堆蠕虫,绝对没有任何好处。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM