django rest framework crear usuario con contraseña

Usando django-rest-framework 3 y django 1.8

Estoy tratando de crear un usuario usando el ModelViewSerializer de django-rest-framework. El problema es que el método predeterminado de objects.create utilizado por DRF deja la contraseña como texto simple.

El problema es que el método de creación de serializador DRF está utilizando objects.create querysets / # create method en lugar de usar el método objects.create_user .

código de serializers.py línea 775

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

¿Cuál es la mejor solución para esto? Puedo anular el método serializer.create para usar objects.user_create en lugar de objects.create pero no parece la solución correcta.

rest de codigo:

 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() 

puede anular la create en UserSerilizer:

 class UserSerializer(serializers.ModelSerializer): # .... def create(self, validated_data): user = User.objects.create_user(**validated_data) return user 

otras soluciones pueden ser sobreescribir a perform_create en la clase ViewSet o puede escribir su propio método de create en su clase de conjunto de vistas

 class UserViewSet(viewsets.ModelViewSet): def create(self, request, format=None): # create user here # do not call seriailzer.save() 

ACTUALIZACIÓN: después de que @freethebees comentó, anular perform_create también funciona, así que aquí está el fragmento de código:

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

NOTA : esta respuesta ofrece 3 soluciones, elija la que crea que mejor se adapta a sus necesidades y al ecosistema de su proyecto

NOTA 2 Personalmente prefiero anular la create en UserViewSet (segundo fragmento de código) porque allí puede simplemente devolver su Response personalizada (por ejemplo, devolver el perfil de usuario después de iniciar sesión)

Incluso hay una mejor opción para validar la contraseña en el serializador

 from django.contrib.auth.hashers import make_password class UserSerializer(serializers.ModelSerializer): def validate_password(self, value: str) -> str: return make_password(value) 

Además de la respuesta de @ aliva en la que se pierden las funcionalidades de los serializers.Modelserializer.create() (lo que podría ser bastante bueno de conservar, por ejemplo, el manejo de relaciones de muchos a muchos), hay una manera de mantener esto.

Al usar el método user.set_password() , la contraseña también se puede configurar correctamente, como:

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

Esto tiene la ventaja de mantener la funcionalidad de la súper clase, pero la desventaja de una escritura adicional en la base de datos. Decida qué compensación es más importante para usted :-).