How to register users in Django REST framework?
Django REST Framework 3 allow override create
method in serializers:
from rest_framework import serializersfrom django.contrib.auth import get_user_model # If used custom user modelUserModel = get_user_model()class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True) def create(self, validated_data): user = UserModel.objects.create_user( username=validated_data['username'], password=validated_data['password'], ) return user class Meta: model = UserModel # Tuple of serialized model fields (see link [2]) fields = ( "id", "username", "password", )
Serialized fields for classes inherited from ModelSerializer
must be declared patently in Meta
for Django Rest Framework v3.5 and newest.
File api.py:
from rest_framework import permissionsfrom rest_framework.generics import CreateAPIViewfrom django.contrib.auth import get_user_model # If used custom user modelfrom .serializers import UserSerializerclass CreateUserView(CreateAPIView): model = get_user_model() permission_classes = [ permissions.AllowAny # Or anon users can't register ] serializer_class = UserSerializer
I went ahead and made my own custom view for handling registration since my serializer doesn't expect to show/retrieve the password. I made the url different from the /users resource.
My url conf:
url(r'^users/register', 'myapp.views.create_auth'),
My view:
@api_view(['POST'])def create_auth(request): serialized = UserSerializer(data=request.DATA) if serialized.is_valid(): User.objects.create_user( serialized.init_data['email'], serialized.init_data['username'], serialized.init_data['password'] ) return Response(serialized.data, status=status.HTTP_201_CREATED) else: return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)
I may be wrong, but it doesn't seem like you'll need to limit permissions on this view since you'd want unauthenticated requests ...
The simplest solution, working in DRF 3.x:
class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('id', 'username', 'password', 'email', 'first_name', 'last_name') write_only_fields = ('password',) read_only_fields = ('id',) def create(self, validated_data): user = User.objects.create( username=validated_data['username'], email=validated_data['email'], first_name=validated_data['first_name'], last_name=validated_data['last_name'] ) user.set_password(validated_data['password']) user.save() return user
No need for other changes, just make sure that unauthenticated users have the permission to create a new user object.
write_only_fields
will make sure passwords (actually: their hash we store) are not displayed, while the overwritten create
method ensures that the password is not stored in clear text, but as a hash.