Django+Postgres使用UUID做主键报bigint类型不匹配错误
问题解答
报错根本原因
你最初创建Book模型时未显式指定主键,Django默认生成了bigint类型的自增id字段作为主键,且你已经执行过迁移在PostgreSQL中创建了对应表结构。后续你直接修改模型将id调整为UUIDField类型,但Django默认迁移工具无法自动完成「已有bigint主键转UUID主键」的字段类型变更,导致数据库中表的id字段实际仍为bigint类型,ORM操作时按照模型定义传入UUID值,就触发了类型不匹配的报错。
更简便的解决方法
表内无需要保留的业务数据
无需删除整个应用,仅重置对应应用的Book模型相关迁移即可:
- 删除该应用
migrations目录下除__init__.py外的所有迁移文件 - 进入PostgreSQL执行SQL删除对应表:
DROP TABLE IF EXISTS 你的应用名_book; - 删除
django_migrations表中该应用对应的迁移记录:DELETE FROM django_migrations WHERE app='你的应用名'; - 重新生成并执行迁移:
python manage.py makemigrations python manage.py migrate
该方案仅调整出问题的模型相关配置,不需要修改其他业务代码、也无需重建整个应用。
表内有需要保留的业务数据
需要手动编写迁移完成字段类型转换,步骤如下:
- 先在
Book模型中新增临时UUID字段:
temp_id = models.UUIDField(default=uuid.uuid4, unique=True, null=True)
生成并执行一次迁移,为现有所有数据自动填充UUID值。
2. 手动创建空迁移文件:
python manage.py makemigrations 你的应用名 --empty
- 编辑新生成的空迁移文件,添加主键切换的SQL操作:
from django.db import migrations class Migration(migrations.Migration): dependencies = [ ('你的应用名', '上一步生成的迁移文件的前缀名'), ] operations = [ migrations.RunSQL( """ ALTER TABLE 你的应用名_book DROP CONSTRAINT 你的应用名_book_pkey; ALTER TABLE 你的应用名_book RENAME COLUMN id TO old_id; ALTER TABLE 你的应用名_book RENAME COLUMN temp_id TO id; ALTER TABLE 你的应用名_book ADD PRIMARY KEY (id); """ ) ]
- 执行迁移后,将
Book模型中的临时temp_id字段和旧的主键定义删除,换回你当前使用的UUID类型id字段定义,再次生成并执行迁移即可。不需要保留旧id数据的话,可以额外执行SQL删除old_id字段。
内容的提问来源于stack exchange,提问作者ProgrammingProbie12
相关产品推荐
相关产品推荐

