Django Rest Framework如何传递外键值创建关联User的Profile对象
问题原因
你出现的非空约束报错是因为Profile模型的username_id外键字段是必填主键,你当前的序列化器没有包含该字段,保存实例时也没有传入对应的用户实例,导致数据库写入时该字段为空触发约束。另外你的代码还有两处可优化的细节:
- 外键字段命名不规范:Django会自动为外键字段追加
_id后缀作为数据库实际存储字段名,你命名为username_id会导致数据库实际字段变为username_id_id,可读性很差 - DateTimeField的default参数错误:
default=timezone.now()加了括号会在项目启动时就固定时间,不会随创建时间动态更新,需要去掉括号传入函数本身
解决方案
方案1:不修改现有模型字段命名,直接调整视图逻辑
修改后的views.py代码如下:
from django.contrib.auth.models import User from rest_framework import status from rest_framework.response import Response @api_view(['POST']) def profile_create(request, pk): # 校验目标用户是否存在 try: target_user = User.objects.get(pk=pk) except User.DoesNotExist: return Response({"detail": "目标用户不存在"}, status=status.HTTP_404_NOT_FOUND) # 校验该用户是否已经创建过Profile if Profile.objects.filter(username_id=target_user).exists(): return Response({"detail": "该用户已关联Profile,不可重复创建"}, status=status.HTTP_400_BAD_REQUEST) serializer = ProfileCreateSerializer(data=request.data) if serializer.is_valid(): # 保存时传入外键对应的用户实例,DRF会自动处理外键关联 serializer.save(username_id=target_user) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
方案2:优化模型命名后调整逻辑(推荐)
第一步修改models.py:
class Profile(models.Model): # 外键字段重命名为user,可读性更高 user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True) phone_number = PhoneNumberField(blank=True, null=True) image_url = models.ImageField(blank=True, null=True) address = models.CharField(max_length=30) # 去掉default里的括号,传入函数本身实现动态时间 update = models.DateTimeField('Updated at', default=timezone.now) def __str__(self): return self.user.username
第二步修改views.py的保存逻辑:
# 其余逻辑和方案1一致,仅修改save时传入的参数名 serializer.save(user=target_user)
额外优化建议
如果你的场景是让登录用户创建自己的Profile,不需要从URL传递用户ID,可以直接取request.user避免越权操作,视图示例:
@api_view(['POST']) def profile_create(request): if not request.user.is_authenticated: return Response({"detail": "请先登录后操作"}, status=status.HTTP_401_UNAUTHORIZED) if Profile.objects.filter(user=request.user).exists(): return Response({"detail": "您已创建过个人资料"}, status=status.HTTP_400_BAD_REQUEST) serializer = ProfileCreateSerializer(data=request.data) if serializer.is_valid(): serializer.save(user=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
内容的提问来源于stack exchange,提问作者Lucky Fated
相关产品推荐
相关产品推荐

