POST请求创建JuniorUser触发IntegrityError:user_id非空约束违规
问题:创建JuniorUser时触发IntegrityError错误
错误详情
IntegrityError at /accounts/juniorprofile/
null value in column "user_id" of relation "authentication_junioruser" violates not-null constraint
DETAIL: Failing row contains (14, Ms K, Vadim, t, 99999999, , null, , 2022-10-23, , DevOps, , , set(), , null, null).
代码背景
models.py
class JuniorUser(models.Model): """ 关联自定义User模型,扩展为Junior用户的角色信息 """ user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="junior") first_name = models.CharField(max_length=50, blank=False) last_name = models.CharField(max_length=50, blank=False) ... def __str__(self): return str(self.user) if self.user else ''
serializers.py
class JuniorProfileSerializer(serializers.ModelSerializer): location = LocationSerializer(read_only=True, many=True) language = serializers.MultipleChoiceField(choices=LANGUAGE) work_experience = ExperienceSerializer(read_only=True, many=True) education = EducationSerializer(read_only=True, many=True) course = CourseSerializer(read_only=True, many=True) class Meta: model = JuniorUser fields = ['id', 'terms_is_accepted', 'first_name', 'last_name', 'phone_number', 'telegram_nick', 'linkedin', 'location', 'profile_photo', 'date_of_birth', 'specialization', 'hard_skills', 'soft_skills', 'language', 'work_experience', 'education', 'course', 'other_info', 'portfolio_link']
views.py
class ListCreateUserProfile(generics.ListCreateAPIView): queryset = JuniorUser.objects.all() serializer_class = JuniorProfileSerializer
问题原因
JuniorUser模型的user字段是必填的一对一关联(OneToOneField),但当前代码存在两个核心问题:
- 序列化器的
fields列表未包含user字段,无法通过请求传入关联关系; - 视图默认创建逻辑未自动给
user字段赋值,导致插入数据库时user_id为空,触发非空约束错误。
解决方案
场景1:关联当前登录用户(用户创建自己的JuniorProfile)
修改视图类,重写perform_create方法,将当前请求的登录用户绑定到新创建的JuniorUser:
class ListCreateUserProfile(generics.ListCreateAPIView): queryset = JuniorUser.objects.all() serializer_class = JuniorProfileSerializer # 限制仅登录用户可访问 permission_classes = [IsAuthenticated] def perform_create(self, serializer): serializer.save(user=self.request.user)
场景2:允许手动传入user_id(管理员批量创建用户)
修改序列化器,添加user字段以支持传入用户ID:
class JuniorProfileSerializer(serializers.ModelSerializer): location = LocationSerializer(read_only=True, many=True) language = serializers.MultipleChoiceField(choices=LANGUAGE) work_experience = ExperienceSerializer(read_only=True, many=True) education = EducationSerializer(read_only=True, many=True) course = CourseSerializer(read_only=True, many=True) # 新增user字段,允许传入用户ID user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all()) class Meta: model = JuniorUser fields = ['id', 'user', 'terms_is_accepted', 'first_name', 'last_name', 'phone_number', 'telegram_nick', 'linkedin', 'location', 'profile_photo', 'date_of_birth', 'specialization', 'hard_skills', 'soft_skills', 'language', 'work_experience', 'education', 'course', 'other_info', 'portfolio_link']
此时POST请求体中需包含user字段,传入对应用户的ID值。
注意事项
- 场景1必须确保请求已通过认证,避免匿名用户创建关联空的JuniorUser;
- 若用户已存在对应的JuniorUser,会触发一对一关联的唯一性错误,可在视图或序列化器中添加前置校验逻辑。
内容的提问来源于stack exchange,提问作者Vadim Rudenkov
相关产品推荐
相关产品推荐

