django.db.utils.OperationalError:3780引用列和被引用列不兼容

问题描述 投票:0回答:3

我正在尝试在 Django 中的两个模型之间添加外键关系,但出现此错误。

Notification
型号:

class Notification(models.Model):
    ...
    lab_extension = models.ForeignKey(Labs, on_delete=models.CASCADE, null=True, to_field='lab_id')
    ...

Lab
型号

class Lab(models.Model):
    ...
    lab_id = models.AutoField(primary_key=True)
    ...

将此外键字段分配给

Notification
模型后,我在执行
python manage.py migrate
时收到此错误:

django.db.utils.OperationalError: (3780, "Referencing column 'lab_extension_id' and referenced column 'lab_id' in foreign key constraint [constraint name] are incompatible.")

如果我从

AutoField
模型中删除
Lab
并使用默认的 id 字段,此错误可能不会持续存在。但我正处于项目的某个阶段,我无法做到这一点。我还意识到外键字段通常不可为空,但对于这个项目,
Notification
模型可能会也可能不会指向
Lab
模型。

SHOW CREATE TABLE notification
给了我这个:

notification_notification, CREATE TABLE `notification_notification` (
  `id` int NOT NULL AUTO_INCREMENT,
  `read` tinyint(1) NOT NULL,
  `message` longtext NOT NULL,
  `user_id` int NOT NULL,
  `category` varchar(2) NOT NULL,
  `created` datetime(6) NOT NULL,
  `question_id` int DEFAULT NULL,
  `submission_id` int DEFAULT NULL,
  `update_request_id` int DEFAULT NULL,
  `lab_extension_id` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `notification_notific_user_id_e9d6f5f4_fk_user_mana` (`user_id`),
  KEY `notification_notification_question_id_af1ad55d_fk_qa_question_id` (`question_id`),
  KEY `notification_notific_submission_id_78f78d05_fk_community` (`submission_id`),
  KEY `notification_notific_update_request_id_39cf03ba_fk_community` (`update_request_id`),
  CONSTRAINT `notification_notific_submission_id_78f78d05_fk_community` FOREIGN KEY (`submission_id`) REFERENCES `community_communitysubmission` (`id`),
  CONSTRAINT `notification_notific_update_request_id_39cf03ba_fk_community` FOREIGN KEY (`update_request_id`) REFERENCES `community_submissionupdaterequest` (`id`),
  CONSTRAINT `notification_notific_user_id_e9d6f5f4_fk_user_mana` FOREIGN KEY (`user_id`) REFERENCES `user_manager_user` (`id`),
  CONSTRAINT `notification_notification_question_id_af1ad55d_fk_qa_question_id` FOREIGN KEY (`question_id`) REFERENCES `qa_question` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3241 DEFAULT CHARSET=latin1

SHOW CREATE TABLE lab
给了我这个:

lab, CREATE TABLE `lab` (
  `lab_id` int unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int unsigned NOT NULL,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  `project_dir` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '/opt/PacketAccess/',
  `lab_model` int unsigned NOT NULL DEFAULT '0',
  `project_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  `pn_account` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  `deployed` int NOT NULL,
  `progress` int NOT NULL,
  `request_time` int NOT NULL,
  `deploy_time` int NOT NULL,
  `destroy_time` int NOT NULL,
  `user_ip` varchar(260) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `status` int NOT NULL DEFAULT '1',
  `labRegion` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'EWR1',
  `pn_progress` int NOT NULL,
  `pn_project_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'n/a',
  `pn_host_name` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'unknown',
  `pn_device_id` varchar(255) COLLATE utf8_bin NOT NULL,
  `pn_device_ip` varchar(40) COLLATE utf8_bin NOT NULL,
  `pn_sdn_ip` varchar(40) COLLATE utf8_bin NOT NULL,
  `pn_nfmp_ip` varchar(40) COLLATE utf8_bin NOT NULL,
  `pn_flow_ip` varchar(40) COLLATE utf8_bin NOT NULL,
  `pn_nfmt_ip` varchar(40) COLLATE utf8_bin NOT NULL,
  `pn_nrcx_ip` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '0.0.0.0',
  `pn_nrcs_ip` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '0.0.0.0',
  `pn_elastic_ip` varchar(40) COLLATE utf8_bin NOT NULL,
  `lab_version` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '17.3',
  `lab_tags` varchar(255) COLLATE utf8_bin NOT NULL,
  `user_email` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'n/a',
  `voucher_id` int NOT NULL,
  `admin_password` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `oss_password` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `deployed_email` text CHARACTER SET utf8 COLLATE utf8_bin,
  `lab_name` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `customer_lab_ip` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '0.0.0.0',
  `deployment_test` tinyint(1) DEFAULT NULL,
  `ssl_enabled` tinyint(1) DEFAULT NULL,
  `associated_lab_id` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`lab_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11995 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin

注意:为了保护隐私,我更改了本文中的一些表和字段的名称,因此如果某些名称不一致,请忽略。

python mysql django migration
3个回答
3
投票

对我来说,问题出在整理

我检查了第一个表的排序规则为:

select column_name, COLLATION_NAME, CHARACTER_SET_NAME from information_schema.`COLUMNS` where table_name = "<table_name>";

然后将默认数据库排序规则修复为:

alter database <database_name> CHARACTER SET <utf8mb4> COLLATE <utf8mb4_desired_value>;

0
投票

这是问题,

在实验台上

  `lab_id` int unsigned NOT NULL AUTO_INCREMENT

在通知中

lab_extension_id` int DEFAULT NULL

这些字段不同,不能设置为外键,请将一种类型移至另一种类型。


0
投票

我也有类似的问题。 您的问题源于具有不同的默认字符集和排序规则。

当您运行 SHOW CREATE TABLE 通知时, 结果的最后一行显示

) ENGINE=InnoDB AUTO_INCREMENT=3241 DEFAULT CHARSET=latin1

当您运行 SHOW CREATE TABLE 实验室时, 结果的最后一行显示

) ENGINE=InnoDB AUTO_INCREMENT=11995 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin

您的两列只是使用自己的表的字符集和排序规则,并且它们恰好不同。

据我所知,django 并没有真正处理字符集和排序规则(也许有人可以纠正我); django 将只使用数据库正在使用的任何默认值;问题和解决方案与数据库相关。

您需要做的就是使所有内容都匹配(数据类型、字符集、排序规则),然后 Django 应该能够使您的外键约束。

老版本的MySQL似乎默认字符集和排序规则是latin1,现在默认是utf8。如果您从旧数据库转储并恢复到新数据库,您可能会遇到此错误(看来您和我都是此问题的受害者)。

就我而言,我已经有了数据库的转储,而这个新数据库只是实验性的,因此我删除了实验数据库,使用正确的字符集和排序规则重新创建了它,并使用我拥有的转储恢复了它,然后运行我的 Django 迁移。

删除数据库 yourdbname;

创建数据库 yourdbname 字符集 latin1 整理 latin1_swedish_ci;

如果您所在的数据库不应该被删除,您可以尝试在数据库级别、表级别或列级别上更新字符集和排序规则。 看来您已经搞乱了字符集和排序规则,因为您的实验室表有一些不同的列(如 SHOW CREATE TABLE 实验室所示)

© www.soinside.com 2019 - 2024. All rights reserved.