Django Admin报错:incidentreport_incidentperson.id列不存在求助
解决Django中IncidentPerson表缺失id列的ProgrammingError问题
问题描述
在事故报告系统中,仅IncidentPerson表在访问Django Admin时抛出错误:
ProgrammingError at /admin/incidentreport/incidentperson/ column incidentreport_incidentperson.id does not exist LINE 1: SELECT "incidentreport_incidentperson"."id", "incidentreport...
对应的模型代码如下:
class IncidentPerson(models.Model): GENDER = ( (1, 'Female'), (2, 'Male'), ) INVOLVEMENT = ( (1, 'Pedestrian'), (2, 'Witness'), (3, 'Passenger'), (4, 'Driver'), ) ID_PRESENTED = ( (1, "Driver's License"), (2, 'Government'), (3, 'Passport'), (4, 'School Id'), (5, 'Others'), ) INJURY = ( (1, "Fatal"), (2, 'Minor'), (3, 'Not Injured'), (4, 'Serious'), ) DRIVER_ERROR = ( (1, "Bad Overtaking"), (2, 'Bad Turning'), (3, 'Fatigued / Asleep'), (4, 'Inattentive'), (5, 'No Signal'), (6, 'Too Close'), (7, 'Too Fast'), (8, 'Using Cellphone'), ) ALCOHOL_DRUGS = ( (1, "Alcohol Suspected"), (2, 'Drugs suspected'), ) SEATBELT_HELMET = ( (1, "Seat belt/Helmet Worn"), (2, 'Not worn'), (3, 'Not worn correctly'), ) incident_general = models.ManyToManyField(IncidentGeneral, blank=True, null=True) incident_first_name = models.CharField(max_length=250, blank=True) incident_middle_name = models.CharField(max_length=250, blank=True) incident_last_name = models.CharField(max_length=250, blank=True) incident_age = models.CharField(max_length=250, blank=True) incident_gender = models.PositiveSmallIntegerField(choices=GENDER, blank=True, null=True) incident_address = models.CharField(max_length=250, blank=True) incident_involvement = models.PositiveSmallIntegerField(choices=INVOLVEMENT, blank=True, null=True) incident_id_presented = models.PositiveSmallIntegerField(choices=ID_PRESENTED, blank=True, null=True) incident_id_number = models.CharField(max_length=250, blank=True) incident_injury = models.PositiveSmallIntegerField(choices=INJURY, blank=True, null=True) incident_driver_error = models.PositiveSmallIntegerField(choices=DRIVER_ERROR, blank=True, null=True) incident_alcohol_drugs = models.PositiveSmallIntegerField(choices=ALCOHOL_DRUGS, blank=True, null=True) incident_seatbelt_helmet = models.PositiveSmallIntegerField(choices=SEATBELT_HELMET, blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
问题原因
Django默认会给未显式定义主键的模型自动添加id字段(类型为AutoField),但该字段未在数据库表中创建,大概率是迁移文件生成或执行过程中出现异常,导致表结构与模型定义不一致。
解决方案
方案1:重新生成并应用迁移(推荐,适用于无重要数据的场景)
- 查看应用的迁移记录:
python manage.py showmigrations incidentreport - 删除
incidentreport应用下migrations文件夹中除__init__.py外的所有迁移文件。 - 登录数据库,执行以下操作:
- 删除
incidentreport_incidentperson表 - 删除
django_migrations表中所有app字段为incidentreport的记录
- 删除
- 重新生成迁移文件:
python manage.py makemigrations incidentreport - 应用迁移:
python manage.py migrate incidentreport
方案2:显式添加主键字段
在IncidentPerson模型中手动添加主键字段:
class IncidentPerson(models.Model): id = models.AutoField(primary_key=True) # 新增主键定义 # 其余字段和选项保持不变 GENDER = ( (1, 'Female'), (2, 'Male'), ) # ... 剩余模型代码
然后执行迁移命令:
python manage.py makemigrations incidentreport python manage.py migrate incidentreport
方案3:手动修改数据库表结构(适用于生产环境有重要数据的场景)
- 使用数据库客户端(如psql、MySQL Workbench)连接数据库,执行对应SQL添加
id主键:- PostgreSQL:
ALTER TABLE incidentreport_incidentperson ADD COLUMN id SERIAL PRIMARY KEY; - MySQL:
ALTER TABLE incidentreport_incidentperson ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY;
- PostgreSQL:
- 让Django标记该迁移为已完成:
python manage.py migrate --fake incidentreport
注意事项
- 操作数据库前务必备份数据,避免数据丢失。
- 生产环境中优先选择方案3,避免删除表造成数据损失。
内容的提问来源于stack exchange,提问作者kimski
相关产品推荐
相关产品推荐

