这里可以删除tb_content
和 tb_content_category
表,然后按照正常的程序去迁移这两个表的迁移文件。
查看django_migrate
表,这个表记录了哪些文件已经迁移过了。
我们将对应的miagration文件填入django_migrate表,这样django就会认为自己迁移过了,从而后面修改模型迁移的工作可以正常进行。
执行迁移的过程中报错:
(venv) fan@ubuntu:Dmall$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, areas, auth, contents, contenttypes, goods, oauth, sessions, user
Running migrations:
Applying goods.0002_goodsvisitcount...Traceback (most recent call last):
File "/home/fan/PycharmProjects/Dmall/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/fan/PycharmProjects/Dmall/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73,
...
django.db.utils.OperationalError: (3780, "Referencing column 'category_id' and referenced column 'id' in foreign key constraint 'tb_goods_visit_category_id_b3e36237_fk_tb_goods_category_id' are incompatible.")
意思是外键束tb_goods_visit_category_id_b3e36237_fk_tb_goods_category_id
中引用列category_id
和引用列id
不兼容。
原因分析:
说明两个表关联的列数据类型不一致,比如:varchar 与 int,或者 int无符号 与 int有符号,都不行,必须要一模一样才可以。
我的报错是因为tb_goods_visit
表中的category_id
为bigint类型,tb_goods_category
表中的id
为int类型,它俩不一致。
显然,这里tb_goods_category
是int
,而我们查看迁移文件goods\migrations\0001_initial.py
, id
是bigint
。
migrations.CreateModel(
name='GoodsCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('name', models.CharField(max_length=10, verbose_name='名称')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subs', to='goods.goodscategory', verbose_name='父类别')),
],
options={
'verbose_name': '商品类别',
'verbose_name_plural': '商品类别',
'db_table': 'tb_goods_category',
},
查看 goods\migrations\0002_goodsvisitcount.py
, 它依赖goods\migrations\0001_initial.py
, 外键 也就按照上面的迁移文件goods\migrations\0001_initial.py
中的 是 models.BigAutoField 即 bigint
。
...
DROP TABLE IF EXISTS `tb_goods_category`;
...
CREATE TABLE `tb_goods_category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`create_time` datetime(6) NOT NULL,
`update_time` datetime(6) NOT NULL,
`name` varchar(10) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `tb_goods_category_parent_id_5abc16fa_fk_tb_goods_category_id` (`parent_id`),
CONSTRAINT `tb_goods_category_parent_id_5abc16fa_fk_tb_goods_category_id` FOREIGN KEY (`parent_id`) REFERENCES `tb_goods_category` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=556 DEFAULT CHARSET=utf8;
...
这里对django生成的表进行了删除重建操作,主键是int
, 而 tb_goods_visit
外键依赖的 标记为bigint,所以出错了。
下面开始修改主键字段,让它和数据库中主键的字段保持一致 (ps:我不想删表,所以主要操作都放在了操作迁移文件这块了)
goods\apps.py
from django.apps import AppConfig
class GoodsConfig(AppConfig):
default_auto_field = 'django.db.models.AutoField' # Django3.2后这里默认是BigAutoField,这里我们改为AutoField
name = 'goods'
迁移过程又出错了,还是上面的那个问题。但是又生成了一个文件goods\migrations\0003_alter_brand_id_alter_goodscategory_id_and_more.py
,这个文件又依赖 goods\migrations\0002_goodsvisitcount.py
。
python manage.py showmigrations
查看迁移情况有X
的表示已经执行(迁移过的),没有的表示还没有迁移。显然,goods应用下的migration文件,只有第一步迁移了(goods\migrations\0001_initial.py
)。
将goods\migrations\0003_alter_brand_id_alter_goodscategory_id_and_more.py
和 goods\migrations\0002_goodsvisitcount.py
删除,重新生成迁移,并执行迁移: