Django REST Framework创建实例校验作者ID为当前登录用户该重写哪个方法
问题解答
核心结论
你需要的校验逻辑可以放在两个位置,根据你的业务场景选择:
- 若需要保留
author作为可提交字段并校验传入值合法性:放在Serializer的validate方法中,属于字段校验范畴,复用性最强 - 若不需要前端传入
author,默认取当前登录用户:放在ViewSet的perform_create方法中,逻辑更简洁安全 - 不推荐重写
ModelViewSet.create()方法:该方法默认封装了参数解析、序列化校验、响应构造全流程,重写容易破坏原有逻辑,非必要不要修改
场景1:保留author可提交字段,校验传入值
序列化器的校验阶段是处理字段合法性的最佳位置,校验失败会直接返回标准化的字段错误响应,不需要你额外处理返回逻辑。
你需要从序列化器的context中获取当前请求对象,代码示例:
# serializers.py class TextSerializer(serializers.ModelSerializer): class Meta: model = Text fields = ['author', 'text'] def validate(self, attrs): # 从context获取当前登录用户 current_user = self.context['request'].user # 校验传入的author是否和当前用户一致 if attrs['author'].id != current_user.id: raise serializers.ValidationError("不能为其他用户创建文本内容") return attrs
场景2:禁止前端传入author,默认取当前用户
这是更安全的实现方式,前端不需要提交author参数,完全由后端赋值,从根源避免传入非法用户ID的问题:
- 先修改序列化器,将
author设为只读字段:
# serializers.py class TextSerializer(serializers.ModelSerializer): class Meta: model = Text fields = ['author', 'text'] read_only_fields = ['author'] # 禁止前端传入修改
- 重写
TextViewSet的perform_create方法,自动赋值当前用户:
# views.py class TextViewSet(viewsets.ModelViewSet): serializer_class = TextSerializer queryset = Text.objects.all() def perform_create(self, serializer): serializer.save(author=self.request.user)
这种场景下不需要额外写校验逻辑,前端根本没有办法传入其他用户的ID,安全性更高。
为什么不推荐放在Serializer.create()里?
create方法的职责是在校验通过后执行实例保存逻辑,不适合放校验代码,校验逻辑要提前到校验阶段处理,避免校验失败还走到了创建逻辑里。
内容的提问来源于stack exchange,提问作者Pavel Shikhov
相关产品推荐
相关产品推荐

