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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:24:04