Django向PostgreSQL联合主键表插入数据报错:无exercise_muscle.id列
问题描述
我在PostgreSQL中手动创建了仅包含exercise_id和muscle_id两列的关联表,建表语句如下:
create table if not exists exercise_muscle( exercise_id INT not null, muscle_id INT not null, primary key (exercise_id, muscle_id), foreign key (exercise_id) references exercise(exercise_id), foreign key (muscle_id) references muscle(muscle_id) );
使用以下Django模型向该表插入数据时:
class ExerciseMuscle(models.Model): exercise = models.ForeignKey('Exercise', on_delete=models.CASCADE) muscle = models.ForeignKey('Muscle', on_delete=models.CASCADE) class Meta: db_table = 'exercise_muscle' unique_together = ('exercise', 'muscle')
出现报错,提示尝试返回不存在的exercise_muscle.id列,报错信息:
django.db.utils.ProgrammingError: column exercise_muscle.id does not exist LINE 1: ...xercise_id", "muscle_id") VALUES (1, 1) RETURNING "exercise_...
通过Django dbshell确认表结构正常,表信息如下:
\d exercise_muscle Table "public.exercise_muscle" Column | Type | Collation | Nullable | Default -------------+---------+-----------+----------+--------- exercise_id | integer | | not null | muscle_id | integer | | not null | Indexes: "exercise_muscle_pkey" PRIMARY KEY, btree (exercise_id, muscle_id) Foreign-key constraints: "exercise_muscle_muscle_id_fkey" FOREIGN KEY (muscle_id) REFERENCES muscle(muscle_id)
确认PostgreSQL表中不存在id列,需解决该问题。
解决方法
Django默认会给每个模型自动添加自增id主键字段,但此表使用复合主键(exercise_id+muscle_id),需在模型中显式指定复合主键,阻止Django自动生成id列。
方式一:标记字段为复合主键
修改模型类,将两个外键字段都设置primary_key=True:
class ExerciseMuscle(models.Model): exercise = models.ForeignKey('Exercise', on_delete=models.CASCADE, primary_key=True) muscle = models.ForeignKey('Muscle', on_delete=models.CASCADE, primary_key=True) class Meta: db_table = 'exercise_muscle' # 复合主键自带唯一性,unique_together可保留或删除 unique_together = ('exercise', 'muscle')
方式二:使用CompositePrimaryKey(Django 4.2+)
若Django版本为4.2及以上,可直接用CompositePrimaryKey定义复合主键,语义更清晰:
from django.db import models class ExerciseMuscle(models.Model): exercise = models.ForeignKey('Exercise', on_delete=models.CASCADE) muscle = models.ForeignKey('Muscle', on_delete=models.CASCADE) class Meta: db_table = 'exercise_muscle' primary_key = models.CompositePrimaryKey('exercise', 'muscle')
注意事项
- 修改模型后无需执行
makemigrations和migrate,表结构已手动创建完成,只需保证模型与表结构匹配即可。 - 确保
Exercise和Muscle模型的主键字段与关联的外键字段对应(默认id字段也可正常关联)。
内容的提问来源于stack exchange,提问作者dani r
相关产品推荐
相关产品推荐

