Docker环境下Django迁移PostgreSQL遇bigint转uuid错误求助
问题
将网站迁移至Docker环境,替换数据库为PostgreSQL后,执行命令docker-compose exec web python manage.py migrate时出现如下错误:
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 87, in _execute return self.cursor.execute(sql) ^^^^^^^^^^^^^^^^^^^^^^^^ psycopg2.errors.CannotCoerce: cannot cast type bigint to uuid LINE 1: ...quirementschat" ALTER COLUMN "id" TYPE uuid USING "id"::uuid ^ The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/code/manage.py", line 22, in <module> main() File "/code/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/usr/local/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/usr/local/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/usr/local/lib/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv self.execute(*args, **cmd_options) File "/usr/local/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute output = self.handle(*args, **options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/core/management/base.py", line 106, in wrapper res = handle_func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/migrate.py", line 356, in handle post_migrate_state = executor.migrate( ^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/migrations/executor.py", line 135, in migrate state = self._migrate_all_forwards( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/migrations/executor.py", line 167, in _migrate_all_forwards state = self.apply_migration( ^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/migrations/executor.py", line 252, in apply_migration state = migration.apply(state, schema_editor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/migrations/migration.py", line 132, in apply operation.database_forwards( File "/usr/local/lib/python3.11/site-packages/django/db/migrations/operations/fields.py", line 235, in database_forwards schema_editor.alter_field(from_model, from_field, to_field) File "/usr/local/lib/python3.11/site-packages/django/db/backends/base/schema.py", line 830, in alter_field self._alter_field( File "/usr/local/lib/python3.11/site-packages/django/db/backends/postgresql/schema.py", line 287, in _alter_field super()._alter_field( File "/usr/local/lib/python3.11/site-packages/django/db/backends/base/schema.py", line 1055, in _alter_field self.execute( File "/usr/local/lib/python3.11/site-packages/django/db/backends/postgresql/schema.py", line 48, in execute return super().execute(sql, None) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/backends/base/schema.py", line 201, in execute cursor.execute(sql, params) File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 102, in execute return super().execute(sql, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute return self._execute_with_wrappers( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers return executor(sql, params, many, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute with self.db.wrap_database_errors: File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 87, in _execute return self.cursor.execute(sql) ^^^^^^^^^^^^^^^^^^^^^^^^ django.db.utils.ProgrammingError: cannot cast type bigint to uuid LINE 1: ...quirementschat" ALTER COLUMN "id" TYPE uuid USING "id"::uuid ^
已尝试过重命名id字段并执行迁移、删除数据库中所有记录、将字段从CharField改为UUIDField,但错误仍存在。当前models.py代码:
class RequirementsChat(models.Model): id = models.CharField(primary_key=True, max_length=38) #id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, max_length=37) alias = models.CharField(max_length=20, blank=True, null=True) email = models.CharField(max_length=80, blank=True, null=True) language = models.CharField(max_length=10, blank=True, null=True) due_date = models.CharField(max_length=10, blank=True, null=True) subtitle_type = models.CharField(max_length=10, blank=True, null=True) transcript_file_type = models.CharField(max_length=10, blank=True, null=True) additional_requirements = models.TextField(max_length=500, blank=True, null=True) date = models.DateTimeField(auto_now_add=True, blank=True, null=True) url = models.CharField(max_length=250, blank=True, null=True) task_completed = models.BooleanField(default=False) class UploadedFile(models.Model): input_file = models.FileField(upload_to='files') chat_id = models.CharField(max_length=33, null= True) requirements_chat = models.ForeignKey(RequirementsChat, on_delete=models.CASCADE, related_name='files', null=True)
解决建议
方案一:清空数据库重新生成迁移(适合无重要数据场景)
因为你已经删除过数据库所有记录,这个方法最简单:
- 删除PostgreSQL数据库并重新创建:
# 进入PostgreSQL容器 docker-compose exec db psql -U 你的用户名 # 删除数据库 DROP DATABASE 你的数据库名; # 重新创建数据库 CREATE DATABASE 你的数据库名; # 退出psql \q - 删除项目中
migrations目录下除__init__.py外的所有迁移文件 - 修改
models.py为最终想要的UUID主键配置:import uuid class RequirementsChat(models.Model): id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True) # 其他字段保持不变... class UploadedFile(models.Model): input_file = models.FileField(upload_to='files') chat_id = models.CharField(max_length=33, null= True) requirements_chat = models.ForeignKey(RequirementsChat, on_delete=models.CASCADE, related_name='files', null=True) - 重新生成迁移文件:
docker-compose exec web python manage.py makemigrations - 执行迁移:
docker-compose exec web python manage.py migrate
方案二:分步修改字段(适合保留数据场景)
如果需要保留现有数据,不能直接将bigint类型的id转为UUID,需要分步操作:
- 添加临时UUID字段:修改
models.py,保留原id字段,新增一个UUID字段:import uuid class RequirementsChat(models.Model): id = models.AutoField(primary_key=True) # 恢复为原来的自增主键(如果之前是这个),或保留当前CharField uuid = models.UUIDField(default=uuid.uuid4, unique=True, null=True) # 其他字段不变... - 生成并执行迁移:
docker-compose exec web python manage.py makemigrations docker-compose exec web python manage.py migrate - 填充UUID字段:进入Django Shell批量生成UUID值:
在Shell中执行:docker-compose exec web python manage.py shellfrom your_app.models import RequirementsChat import uuid for chat in RequirementsChat.objects.all(): chat.uuid = uuid.uuid4() chat.save() - 修改外键关联:修改
UploadedFile的外键指向新的uuid字段:
生成并执行迁移:class UploadedFile(models.Model): input_file = models.FileField(upload_to='files') chat_id = models.CharField(max_length=33, null= True) requirements_chat = models.ForeignKey(RequirementsChat, on_delete=models.CASCADE, related_name='files', null=True, to_field='uuid')docker-compose exec web python manage.py makemigrations docker-compose exec web python manage.py migrate - 切换主键到UUID字段:修改
RequirementsChat模型,将uuid设为主键并删除原id字段:
生成并执行迁移,完成切换。class RequirementsChat(models.Model): id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True) # 删除原uuid字段和旧的id字段 # 其他字段不变...
内容的提问来源于stack exchange,提问作者tthheemmaannii
相关产品推荐
相关产品推荐

