使用inspectdb后,如何迁移Django Rest中已修改的模型?
问题解决步骤
核心问题在于你跳过了「标记初始模型与数据库同步」的步骤,直接修改模型后生成的迁移会尝试创建已存在的表,导致冲突。按以下步骤操作即可解决:
1. 恢复初始模型状态
先把models.py改回和数据库中api_task表完全匹配的初始版本(也就是inspectdb生成的原始内容,注意默认会带managed=False,表示Django不管理表的创建):
class ApiTask(models.Model): task_id = models.AutoField(primary_key=True) task_title = models.CharField(max_length=15, blank=True, null=True) task_description = models.CharField(max_length=150, blank=True, null=True) class Meta: managed = False db_table = 'api_task'
2. 标记初始模型已同步
生成初始迁移文件,再告诉Django这个迁移对应的表已经在数据库里了,不用执行创建操作:
python manage.py makemigrations api python manage.py migrate api --fake-initial
3. 修改模型为你需要的状态
这里要注意:如果要保留原有字段的数据,别直接改模型字段名,用db_column指定对应数据库的列名,避免数据丢失。示例:
class ApiTask(models.Model): task_id = models.AutoField(primary_key=True) # 用db_column映射到原数据库的task_title列,同时修改max_length title = models.CharField(max_length=100, blank=True, db_column='task_title') # 映射到原task_description列,改成TextField类型 description = models.TextField(max_length=250, blank=True, db_column='task_description') # 添加新字段 created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title class Meta: db_table = 'api_task' managed = True # 现在让Django管理表的修改
4. 生成并执行新迁移
这次生成的迁移只会包含字段属性修改和新字段添加的操作,不会重复创建表:
python manage.py makemigrations api python manage.py migrate api
为什么之前的方法无效?
- 直接修改模型后
makemigrations,生成的迁移会尝试创建整个表,而数据库中表已存在,因此报错「relationship already exists」。 --fake只是让Django认为迁移已执行,但不会实际修改数据库的字段。--run-syncdb仅适用于没有迁移文件的应用,你的api已经有迁移文件,所以无法使用。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

