使用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()
答案 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)
一个完整的示例,它支持POST
和PUT
/ 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)