[英]Django throws a Foreign Key IntegrityError with a valid ForeignKey
[英]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.