How to register users in Django REST framework?

前端 未结 9 1457
说谎
说谎 2020-11-28 17:34

I\'m coding a REST API with Django REST framework. The API will be the backend of a social mobile app. After following the tutorial, I can serialise all my models and I am a

相关标签:
9条回答
  • 2020-11-28 18:05

    All of the answers so far create the user, then update the user's password. This results in two DB writes. To avoid an extra unnecessary DB write, set the user's password before saving it:

    from rest_framework.serializers import ModelSerializer
    
    class UserSerializer(ModelSerializer):
    
        class Meta:
            model = User
    
        def create(self, validated_data):
            user = User(**validated_data)
            # Hash the user's password.
            user.set_password(validated_data['password'])
            user.save()
            return user
    
    0 讨论(0)
  • 2020-11-28 18:06

    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.

    0 讨论(0)
  • 2020-11-28 18:08

    A Python 3, Django 2 & Django REST Framework viewset based implementation:

    File: serializers.py

    from rest_framework.serializers import ModelSerializers
    from django.contrib.auth import get_user_model
    
    UserModel = get_user_model()
    
    class UserSerializer(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'],
                first_name=validated_data['first_name'],
                last_name=validated_data['last_name'],
            )
            return user
    
        class Meta:
            model = UserModel
            fields = ('password', 'username', 'first_name', 'last_name',)
    

    File views.py:

    from rest_framework.viewsets import GenericViewSet
    from rest_framework.mixins import CreateModelMixin
    from django.contrib.auth import get_user_model
    from .serializers import UserSerializer
    
    class CreateUserView(CreateModelMixin, GenericViewSet):
        queryset = get_user_model().objects.all()
        serializer_class = UserSerializer
    

    File urls.py

    from rest_framework.routers import DefaultRouter
    from .views import CreateUserView
    
    router = DefaultRouter()
    router.register(r'createuser', CreateUserView)
    
    urlpatterns = router.urls
    
    0 讨论(0)
  • 2020-11-28 18:16

    I updated Cahlan's answer to support custom user models from Django 1.5 and return the user's ID in the response.

    from django.contrib.auth import get_user_model
    
    from rest_framework import status, serializers
    from rest_framework.decorators import api_view
    from rest_framework.response import Response
    
    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = get_user_model()
    
    @api_view(['POST'])
    def register(request):
        VALID_USER_FIELDS = [f.name for f in get_user_model()._meta.fields]
        DEFAULTS = {
            # you can define any defaults that you would like for the user, here
        }
        serialized = UserSerializer(data=request.DATA)
        if serialized.is_valid():
            user_data = {field: data for (field, data) in request.DATA.items() if field in VALID_USER_FIELDS}
            user_data.update(DEFAULTS)
            user = get_user_model().objects.create_user(
                **user_data
            )
            return Response(UserSerializer(instance=user).data, status=status.HTTP_201_CREATED)
        else:
            return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)
    
    0 讨论(0)
  • 2020-11-28 18:18

    A little late to the party, but might help someone who do not want to write more lines of code.

    We can user the super method to achieve this.

    class UserSerializer(serializers.ModelSerializer):
    
        password = serializers.CharField(
              write_only=True,
        )
    
        class Meta:
           model = User
           fields = ('password', 'username', 'first_name', 'last_name',)
    
        def create(self, validated_data):
            user = super(UserSerializer, self).create(validated_data)
            if 'password' in validated_data:
                  user.set_password(validated_data['password'])
                  user.save()
            return user
    
    0 讨论(0)
  • 2020-11-28 18:19

    Django REST Framework 3 allow override create method in serializers:

    from rest_framework import serializers
    from django.contrib.auth import get_user_model # If used custom user model
    
    UserModel = get_user_model()
    
    
    class UserSerializer(serializers.ModelSerializer):
    
        password = serializers.CharField(write_only=True)
    
        def create(self, validated_data):
    
            user = UserModel.objects.create(
                username=validated_data['username']
            )
            user.set_password(validated_data['password'])
            user.save()
    
            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 permissions
    from rest_framework.generics import CreateAPIView
    from django.contrib.auth import get_user_model # If used custom user model
    
    from .serializers import UserSerializer
    
    
    class CreateUserView(CreateAPIView):
    
        model = get_user_model()
        permission_classes = [
            permissions.AllowAny # Or anon users can't register
        ]
        serializer_class = UserSerializer
    
    0 讨论(0)
提交回复
热议问题