Django中在GenericViewSet内创建用户并存储加密密码的实现
完善Django ViewSet实现用户创建与密码哈希存储
我来帮你搞定这个DetailedUserViewSet的创建逻辑,核心要记住:绝对不能直接把明文密码存进数据库,Django已经给我们准备好了安全处理密码哈希的方式。
完整的ViewSet代码实现
from rest_framework import status from rest_framework.response import Response from django.contrib.auth import get_user_model from rest_framework.mixins import CreateModelMixin from rest_framework.viewsets import GenericViewSet from rest_framework.permissions import AllowAny # 用get_user_model获取用户模型,适配自定义用户模型的场景 User = get_user_model() class DetailedUserViewSet(CreateModelMixin, GenericViewSet): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = (AllowAny,) # 原有的__init__方法没有自定义逻辑,完全可以删掉 def create(self, request, *args, **kwargs): # 先用Serializer验证请求数据,比直接操作request.data更安全规范 serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) validated_data = serializer.validated_data # 把密码从验证数据里单独拎出来,后续单独处理哈希 password = validated_data.pop('password') # 创建用户实例,但先不处理密码 user = User.objects.create(**validated_data) # 调用set_password方法处理密码哈希,这是Django官方推荐的安全方式 user.set_password(password) user.save() # 组装成功响应数据返回 response_data = { 'message': 'User created successfully', 'user': serializer.data } return Response(response_data, status=status.HTTP_201_CREATED)
关键细节说明
- 移除多余的
__init__方法:你原代码里的__init__只是单纯调用父类方法,没有任何自定义逻辑,留着反而冗余,直接删掉就好。 - 用Serializer做数据校验:通过
serializer.is_valid()验证请求数据,能自动处理字段格式校验、必填项检查等,比直接取request.data更符合DRF的开发规范。 set_password的核心作用:这个方法会按照Django配置的PASSWORD_HASHERS(默认是PBKDF2哈希算法)对明文密码进行加密处理,处理后的哈希值才会存入数据库,彻底避免明文存储的安全风险。- 适配自定义用户模型:使用
get_user_model()获取用户模型,而不是直接导入默认User,这样就算以后换成自定义用户模型,这段代码也不用修改。
额外小提示
如果你的UserSerializer里包含password字段,一定要把它的write_only属性设为True,防止在返回的响应中泄露哈希后的密码:
class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True) class Meta: model = get_user_model() fields = ('id', 'email', 'username', 'password') # 根据你的实际需求调整字段
内容的提问来源于stack exchange,提问作者zennn
相关产品推荐
相关产品推荐

