Как зарегистрировать пользователей в Django Rest framework?
я кодирую REST API с Django REST framework. API будет бэкендом социального мобильного приложения. После выполнения этого урока я могу сериализовать все свои модели, и я могу создавать новые ресурсы и обновлять их.
Я использую AuthToken для аутентификации.
мой вопрос:
у меня есть /users ресурс, я хочу, чтобы пользователь приложения мог зарегистрироваться. Так что, лучше иметь отдельный ресурс, как /register или разрешить анонимные пользователи для публикации в /users новый ресурс?
кроме того, некоторые рекомендации о разрешениях было бы здорово.
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
все ответы до сих пор создают пользователя, а затем обновляют пароль пользователя. Это приводит к записи двух БД. Чтобы избежать дополнительной ненужной записи БД, установите пароль пользователя перед его сохранением:
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