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

如何使用APIView的update方法更新自定义User模型字段

问题描述

我正尝试编写APIView的update方法,用来修改自定义AbstractUser模型中的字段。查了APIView的官方文档和相关示例,但大多要么是一对一关联的「profile」模型,要么需要写序列化器——我觉得用户模型不需要序列化器(如果我错了请指正)。现在不确定怎么给用户模型实现对应的update方法。

我要从前端更新自定义User模型里的referred_count和tokens字段,模型代码如下:

users/models.py

class User(AbstractUser):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    username = None
    first_name = models.CharField(max_length=100, default="unknown")
    last_name = models.CharField(max_length=100, default="unknown", blank=True)
    profile_pic = models.CharField(max_length=200, default="unknown")
    premium = models.BooleanField(default=False)
    referred_count = models.IntegerField(default=0)
    tokens = models.IntegerField(default=0)

    email = models.EmailField(unique=True, db_index=True)
    secret_key = models.CharField(max_length=255, default=get_random_secret_key)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    objects = UserManager()

    class Meta:
        swappable = "AUTH_USER_MODEL"

我的users/api.py里的UpdateFields视图类update方法还没正确实现:

users/api.py

class UpdateFields(ApiAuthMixin, ApiErrorsMixin, APIView):
    def update(self, request, *args, **kwargs):
        # update various user fields based on request.data
        # I am not sure what should go inside here.
        return request.user.update(request, *args, **kwargs)

希望前端发送如下格式的JSON,通过UpdateFields APIView用PATCH方式更新这些字段:

{
  "tokens": 100,
  "referred_count": 12
}

我的users/urls.py配置如下:

users/urls.py

urlpatterns = [
    path("me/", UserMeApi.as_view(), name="me"),
    path("update/", UpdatePremium.as_view(), name="update"),
]

解决方案

首先纠正你的认知:即便是自定义User模型,使用序列化器依然是DRF推荐的最佳实践。序列化器能帮你做数据校验、字段过滤,还能统一API输入输出格式,避免直接操作模型字段带来的安全风险(比如前端恶意修改premium、secret_key这类敏感字段)。

下面分两种方式实现:

方式一:使用序列化器(推荐)

1. 编写User序列化器

在users/serializers.py中创建序列化器,只暴露允许更新的字段:

from rest_framework import serializers
from .models import User

class UserPartialUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['referred_count', 'tokens']

2. 完善UpdateFields视图的update方法

修改users/api.py:

from rest_framework.response import Response
from rest_framework import status
from .serializers import UserPartialUpdateSerializer

class UpdateFields(ApiAuthMixin, ApiErrorsMixin, APIView):
    def patch(self, request, *args, **kwargs):
        # 获取当前登录用户
        user = request.user
        # partial=True允许部分字段更新
        serializer = UserPartialUpdateSerializer(user, data=request.data, partial=True)
        # 校验数据,不合法直接抛出异常
        serializer.is_valid(raise_exception=True)
        # 保存更新
        serializer.save()
        # 返回更新后的数据
        return Response(serializer.data, status=status.HTTP_200_OK)
    
    # 兼容PUT方法(全量更新),直接复用PATCH逻辑
    def update(self, request, *args, **kwargs):
        return self.patch(request, *args, **kwargs)

3. 修正URL配置

注意urls.py里的视图类名错误,改成UpdateFields.as_view():

urlpatterns = [
    path("me/", UserMeApi.as_view(), name="me"),
    path("update/", UpdateFields.as_view(), name="update"),
]

方式二:不使用序列化器(不推荐)

如果坚持不使用序列化器,需要手动做数据校验和字段过滤,避免安全风险:

from rest_framework.response import Response
from rest_framework import status

class UpdateFields(ApiAuthMixin, ApiErrorsMixin, APIView):
    def patch(self, request, *args, **kwargs):
        user = request.user
        # 定义允许更新的字段白名单
        allowed_fields = ['referred_count', 'tokens']
        # 过滤请求数据,只保留白名单内的字段
        update_data = {k: v for k, v in request.data.items() if k in allowed_fields}
        
        # 手动校验数据类型必须是整数
        for field, value in update_data.items():
            if not isinstance(value, int):
                return Response(
                    {field: "必须是整数类型"},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # 更新并保存用户字段
        for field, value in update_data.items():
            setattr(user, field, value)
        user.save()
        
        # 返回更新后的字段
        return Response({
            'referred_count': user.referred_count,
            'tokens': user.tokens
        }, status=status.HTTP_200_OK)

注意事项

  • 确保ApiAuthMixin已正确处理用户认证,保证只有登录用户能修改自己的字段。
  • 优先使用序列化器,它能处理大部分数据校验和安全问题,代码更简洁易维护。
  • 如果需要实现增量更新(比如tokens增加N而不是直接设置为某个值),可以在序列化器的update方法里自定义逻辑,或者在视图中单独处理。

内容的提问来源于stack exchange,提问作者Tyler Kim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:25:25