Python 编辑外键引用的值时出现Django IntegrityError
我有一个带有两个(相关)模型的应用程序,本质上是一个CRM:Python 编辑外键引用的值时出现Django IntegrityError,python,django,postgresql,Python,Django,Postgresql,我有一个带有两个(相关)模型的应用程序,本质上是一个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 = m
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"
)
...
现在有人拼错了一个学生的名字,想在StudentTutorRelationshipProfile
中更改Student\u name
,但因为已经有学生名字拼错的时间表记录,Django提出了一个错误(来自psychog):
更改此数据的好方法是什么?我也不介意更改历史时刻表,或者让它们保持原样(但不能删除它们),任何更容易/不太可能导致问题的事情。(是的,我依赖唯一的姓名和姓氏组合这一事实并不理想,但目前不会解决这一问题,除非IntegrityError的更改也需要一些迁移
我正在运行python 3.6,Django 3.0,如果这有帮助的话。这是一个很好的例子,说明了为什么您永远不想使用可能被更新为外键的列。其他不好的外键候选项是,例如,不应该公开的数据、个人或私人数据,如姓名或社会安全号码等。此外,姓名也不是唯一的,这是非常重要的自动取消它们作为唯一标识符(如主键)的资格 使用串行主键,或者有时使用UUID或其他类型的通用自动生成标识符(除了标识行之外没有其他意义)更简单、更安全。它尤其不应包含非ASCII字符(这也会取消名称的资格)因为你永远不知道你是否需要通过一个无法处理它的系统来处理它,就像一个不会说这种语言的人(“你好,我的登录名是指鹿為馬"). 在您的情况下,您可以使用ON UPDATE CASCADE声明外键,以便引用表上的更新级联到引用表。这只会消除一些麻烦,因为一行的简单更新可能会导致引用表中的大量更新 您也可以手动更新所有引用表,但会有一个时间窗口,在此期间引用将不一致。将外键约束设置为“延迟”并在单个事务中执行所有更新可能会起作用 但是,这不会更新数据库之外的内容中的标识符。例如,如果系统使用基于主键的文件名存储学生的照片,或者写入日志、打印纸张,或者将任何使用主键作为参考的内容存储在任何位置……或者如果主键用作url中的标识符,以及她的网站在链接中使用此标识符链接到你的网站…然后这些都不会更新,甚至无法更新 所以,是的,更新或重用主键是一个巨大的蠕虫,毫无益处。一个(坏)解决方案是将外键设为空,暂时将其设为空,更新瞳孔名称保存,然后再次设置外键。这个过程太长且复杂。这次我只需要进行数据迁移,并在没有to_字段的情况下创建一个新的外键。
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".