Django DRF单请求为单个候选人添加多个关联技能解决多实例赋值报错
问题原因
你的报错是默认ModelSerializer仅支持单次创建一条CandidateSkill关联记录导致的:skills是单外键字段,只能关联单个Skill实例,当请求传入多个技能ID时,默认序列化逻辑无法将多个实例赋值给该字段,因此触发错误。
解决方案
1. 调整序列化器,支持批量接收技能ID并重写创建逻辑
from rest_framework import serializers from jobs.models import Skill from .models import CandidateSkill class CandidateSkillSerializer(serializers.ModelSerializer): # 接收多个技能ID的列表字段,仅写入用 skills = serializers.ListField( child=serializers.PrimaryKeyRelatedField(queryset=Skill.objects.all()), write_only=True ) # 只读字段,返回关联的技能名称用于展示 skill_name = serializers.StringRelatedField(source='skills', read_only=True) class Meta: model = CandidateSkill fields = ["id", "candidate", "skills", "skill_name"] def create(self, validated_data): # 取出校验通过的技能列表和候选人ID skill_list = validated_data.pop('skills') candidate = validated_data['candidate'] # 批量生成关联记录 skill_objs = [ CandidateSkill(candidate=candidate, skills=skill_item) for skill_item in skill_list ] # 批量写入数据库,提升性能 CandidateSkill.objects.bulk_create(skill_objs) # 返回第一条创建的记录(可根据需求调整返回逻辑) return skill_objs[0]
2. 调整视图,支持批量创建后返回全量关联技能
from rest_framework import generics, status from rest_framework.response import Response from .models import CandidateSkill from .serializers import CandidateSkillSerializer class CandidateSkillList(generics.ListCreateAPIView): serializer_class = CandidateSkillSerializer queryset = CandidateSkill.objects.all() def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) # 查询当前候选人的所有关联技能返回 candidate = serializer.validated_data['candidate'] candidate_skills = self.get_queryset().filter(candidate=candidate) return Response( self.get_serializer(candidate_skills, many=True).data, status=status.HTTP_201_CREATED )
3. (可选)模型层添加联合唯一约束,避免重复插入相同关联
class CandidateSkill(models.Model): candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE,related_name="skills",) skills = models.ForeignKey("jobs.Skill", on_delete=models.CASCADE) class Meta: # 确保同一个候选人不会重复关联同一个技能 constraints = [ models.UniqueConstraint(fields=['candidate', 'skills'], name='unique_candidate_skill') ]
请求示例
发送POST请求到接口时,请求体格式如下即可实现单请求批量添加关联技能:
{ "candidate": 1, "skills": [2, 3, 5, 8] }
以上示例将为ID为1的候选人关联ID为2、3、5、8的四个技能。
内容的提问来源于stack exchange,提问作者Muhammad Shehzad
相关产品推荐
相关产品推荐

