django rest框架用密码创建用户

时间:2015-04-20 11:26:42

标签: python django django-rest-framework

使用django-rest-framework 3和django 1.8

我正在尝试使用django-rest-framework ModelViewSerializer创建用户。问题是DRF使用的默认objects.create方法将密码保留为纯文本。

问题是DRF序列化器创建方法使用的是objects.create querysets/#create方法,而不是使用objects.create_user方法。

来自serializers.py第775行的代码

instance = ModelClass.objects.create(**validated_data)

最佳解决方案是什么?我可以覆盖serializer.create方法来使用objects.user_create而不是objects.create,但它感觉不是正确的解决方案。

其余代码:

from django.contrib.auth.models import User
from rest_framework import viewsets

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'email','password')
        write_only_fields = ('password',)


class UserViewSet(viewsets.ModelViewSet):   
    queryset = User.objects.all()
    serializer = UserSerializer()

4 个答案:

答案 0 :(得分:14)

您可以在UserSerilizer中覆盖create

class UserSerializer(serializers.ModelSerializer):
    # ....

    def create(self, validated_data):
        user = User.objects.create_user(**validated_data)
        return user

其他解决方案可以覆盖ViewSet类中的perform_create,也可以在视图集类中编写自己的create方法

class UserViewSet(viewsets.ModelViewSet): 
    def create(self, request, format=None):
        # create user here
        # do not call seriailzer.save()
@freethebees发表评论后,

更新:,覆盖perform_create也有效,所以这里是代码段:

class UserViewSet(viewsets.ModelViewSet, mixins.CreateModelMixin): 
    def perform_create(self, serializer):
        # use User.objects.create_user to create user
        pass

注意: 这个答案给出了3个解决方案,选择一个你认为最符合你需求和项目生态系统的解决方案

注意2 我个人更喜欢在create(第二个代码段)中覆盖UserViewSet,因为您只需返回自定义Response(例如,在登录后返回用户个人资料)

答案 1 :(得分:5)

在序列化程序中验证密码还有更好的选择

from django.contrib.auth.hashers import make_password

class UserSerializer(serializers.ModelSerializer):
    def validate_password(self, value: str) -> str:
        return make_password(value)

答案 2 :(得分:2)

除了@ aliva的答案,你错过了serializers.Modelserializer.create()中的功能(这可能是非常好的保存,例如处理多对多关系),有一种方法可以保持这个

通过使用user.set_password()方法,也可以正确设置密码,例如:

class UserSerializer(serializers.ModelSerializer):

    def create(self, validated_data):
        user = super().create(validated_data)
        user.set_password(validated_data['password']
        user.save()
        return user

这有利于保持超类的功能,但是对数据库的额外写入的缺点。决定哪种权衡对你来说更重要: - )。

答案 3 :(得分:0)

一个完整的示例,它支持POSTPUT / PATCH,而没有其他SQL UPDATE语句。

class MyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = '__all__'

    def create(self, validated_data):
        if "password" in validated_data:
            from django.contrib.auth.hashers import make_password
            validated_data["password"] = make_password(validated_data["password"])
        return super().create(validated_data)

    def update(self, instance, validated_data):
        if "password" in validated_data:
            from django.contrib.auth.hashers import make_password
            validated_data["password"] = make_password(validated_data["password"])
        return super().update(instance, validated_data)