如何在Django REST框架中注册用户?

我使用Django REST框架编写了一个REST API。 该API将成为社交移动应用程序的后端。 遵循教程后,我可以序列化所有模型,并可以创build新资源并进行更新。

我正在使用AuthToken进行身份validation。

我的问题是:

一旦我有/users资源,我希望应用程序用户能够注册。 那么,拥有一个像/register这样的独立资源还是允许匿名用户向/users一个新资源会更好?

另外,一些关于权限的指导会很好。

我继续做了我自己的自定义视图来处理注册,因为我的序列化程序不期望显示/检索密码。 我做了不同于/用户资源的url。

我的urlconf:

 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) 

我可能是错的,但似乎并不需要限制这个视图的权限,因为你想要未经身份validation的请求…

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 

最简单的解决scheme,使用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 

不需要进行其他更改,只需确保未经身份validation的用户有权创build新的用户对象。

write_only_fields将确保密码(实际上是:我们存储的哈希)不被显示,而覆盖的create方法确保密码不是以明文forms存储,而是以散列forms存储。

我更新了Cahlan的答案,以支持来自Django 1.5的自定义用户模型,并在响应中返回用户的ID。

 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(又名创build)覆盖视图类的权限集。 我通常使用这种模式:

 from django.contrib.auth import get_user_model from rest_framework import viewsets 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

上面的@cpurybuild议使用write_only_fields选项。 然而,这在3.3.3的DRF中并不适用

在DRF 3.0中 , write_only_fields上的write_only_fields选项已被移至PendingDeprecation,并在DRF 3.2中被replace为更通用的extra_kwargs:

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

到目前为止所有的答案创build用户,然后更新用户的密码。 这导致了两个数据库写入。 为避免多余的数据库写入,请在保存之前设置用户的密码:

 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