Как зарегистрировать пользователей в Django Rest framework?



я кодирую REST API с Django REST framework. API будет бэкендом социального мобильного приложения. После выполнения этого урока я могу сериализовать все свои модели, и я могу создавать новые ресурсы и обновлять их.



Я использую AuthToken для аутентификации.



мой вопрос:



у меня есть /users ресурс, я хочу, чтобы пользователь приложения мог зарегистрироваться. Так что, лучше иметь отдельный ресурс, как /register или разрешить анонимные пользователи для публикации в /users новый ресурс?



кроме того, некоторые рекомендации о разрешениях было бы здорово.

872   8  

8 ответов:

Я пошел вперед и сделал свой собственный пользовательский вид для обработки регистрации, так как мой сериализатор не ожидает, чтобы показать/получить пароль. Я сделал url-адрес отличным от ресурса /users.

мой url conf:

url(r'^users/register', 'myapp.views.create_auth'),

мое мнение:

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

Я могу ошибаться, но не похоже, что вам нужно будет ограничивать разрешения на это представление, так как вам нужны неавторизованные запросы ...

Django REST Framework 3 разрешить переопределить create метод в сериализаторах:

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

также 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

самое простое решение, работающее в 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

нет необходимости в других изменениях, просто убедитесь, что у неавторизованных пользователей есть разрешение на создание нового объекта пользователя.

write_only_fields будет убедиться, что пароли (на самом деле: их хэш мы храним) не отображаются, в то время как перезапись create метод гарантирует, что пароль хранится не в виде открытого текста, а в виде хэша.

я обновил ответ Cahlan для поддержки пользовательских моделей пользователей из Django 1.5 и вернул идентификатор пользователя в ответе.

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)

Я обычно рассматриваю представление пользователя так же, как и любую другую конечную точку API, требующую авторизации, за исключением того, что я просто переопределяю набор разрешений класса представления своим собственным для POST (aka create). Я обычно использую этот шаблон:

from django.contrib.auth import get_user_model
from rest_framework import viewsets
from rest_framework.permissions import AllowAny


class UserViewSet(viewsets.ModelViewSet):
    queryset = get_user_model().objects
    serializer_class = UserSerializer

    def get_permissions(self):
        if self.request.method == 'POST':
            self.permission_classes = (AllowAny,)

        return super(UserViewSet, self).get_permissions()

для хорошей меры, вот сериализатор я обычно использую с ним:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = get_user_model()
        fields = (
            'id',
            'username',
            'password',
            'email',
            ...,
        )
        extra_kwargs = {
            'password': {'write_only': True},
        }

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

    def update(self, instance, validated_data):
        if 'password' in validated_data:
            password = validated_data.pop('password')
            instance.set_password(password)
        return super(UserSerializer, self).update(instance, validated_data)

djangorestframework 3.3.x / Django 1.8.x

@cpury выше предложил использовать . Это, однако, не работает для меня в DRF 3.3.3

на DRF 3.0 the write_only_fields опция на ModelSerializer была перемещена в PendingDeprecation и в DRF 3.2 заменен на более общий extra_kwargs:

extra_kwargs = {'password': {'write_only': True}}

все ответы до сих пор создают пользователя, а затем обновляют пароль пользователя. Это приводит к записи двух БД. Чтобы избежать дополнительной ненужной записи БД, установите пароль пользователя перед его сохранением:

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

немного опоздал на вечеринку, но может помочь кому-то, кто не хочет писать больше строк кода.

мы можем использовать super метод для достижения этой цели.

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

Comments

    Ничего не найдено.