You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:15:16