Django用户创建密码未加密排查:为何未调用UserManager?
问题根源与解决方案
你遇到的核心问题是:Django的ModelSerializer默认不会调用你自定义的UserManager方法,而是直接使用模型的create()方法,跳过了密码加密的逻辑。下面详细拆解原因和修复步骤:
1. 为什么没有调用UserManager?
Django的ModelSerializer默认的create()实现是这样的(简化版):
def create(self, validated_data): return self.model.objects.create(**validated_data)
它直接调用了模型的objects.create(),而不是你自定义的create_user()方法,自然不会触发UserManager里的set_password()加密步骤,导致密码明文存储。
另外,你在UserProfileViewSet里重写的post方法也没必要——ModelViewSet已经自带了标准化的create方法来处理POST请求,自定义post反而容易绕开框架的正确流程。
2. 修复步骤
步骤1:重写Serializer的create方法
修改serializers.py,让它主动调用你自定义的create_user方法:
from rest_framework import serializers from .models import UserProfile class UserProfileSerializer(serializers.ModelSerializer): phone = serializers.CharField(required=True, allow_blank=False) password = serializers.CharField(required=True, allow_blank=False, write_only=True) class Meta: model = UserProfile fields = '__all__' extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): # 调用UserManager的create_user方法,触发密码加密 return UserProfile.objects.create_user( phone=validated_data['phone'], password=validated_data['password'] )
步骤2:移除ViewSet中自定义的post方法
ModelViewSet已经内置了处理POST请求的create方法,完全覆盖了你自定义的post逻辑,而且更符合DRF的规范。修改views.py:
from rest_framework.viewsets import ModelViewSet from .serializers import UserProfileSerializer from .models import UserProfile class UserProfileViewSet(ModelViewSet): serializer_class = UserProfileSerializer queryset = UserProfile.objects.all() # 删掉下面这段自定义的post方法 # def post(self, request): # serializer = self.serializer_class(data=request.data) # serializer.is_valid(raise_exception=True) # serializer.save() # return Response(data=serializer.data, status=HTTP_200_OK)
3. 验证修复效果
创建新用户后,检查数据库的password字段:
- 加密后的密码会以
pbkdf2_sha256$开头(Django默认加密算法),而不是明文密码。 - 同时,UserManager的
_create_user方法会被正确调用,执行user.set_password(password)逻辑。
内容的提问来源于stack exchange,提问作者ncopiy
相关产品推荐
相关产品推荐

