Django Rest Framework自定义注册视图(RegisterView)无法返回令牌+用户数据 [英] Django Rest Framework Custom Register View (RegisterView) failing to return token + user data

查看:110
本文介绍了Django Rest Framework自定义注册视图(RegisterView)无法返回令牌+用户数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在django rest框架应用程序中使用allauth和rest_auth.当注册用户时,将返回令牌(密钥),我要实现的目标是在注册后返回令牌+用户数据. 为此,我具有以下序列化器:

I'm using allauth and rest_auth in my django rest framework app. When registering an user a token (key) is returned, what I'm trying to achieve is to return the token + user data after registration. To do so I've the following serializer:

from rest_framework import serializers
from rest_framework.response import Response
from allauth.account import app_settings as allauth_settings
from allauth.utils import email_address_exists
from allauth.account.adapter import get_adapter
from allauth.account.utils import setup_user_email
from kofiapi.api.users.models import User, UserProfile
from rest_framework.authtoken.models import Token
from rest_auth.models import TokenModel

class UserProfileSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserProfile
        fields = ('dob', 'phone', 'receive_newsletter')


class UserSerializer(serializers.HyperlinkedModelSerializer):

    profile = UserProfileSerializer(required=True)

    class Meta:
        model = User
        fields = ('url', 
                  'email', 
                  'first_name', 
                  'last_name',
                  'password',
                  'profile')
        extra_kwargs = {'password': {'write_only': True}}

    def create_token(self, user):
        token, created = Token.objects.get_or_create(user=user)
        return token


    def create(self, validated_data):
        profile_data = validated_data.pop('profile')

        password = validated_data.pop('password')

        user = User(**validated_data)
        user.set_password(password)
        user.save()

        token = self.create_token(user)

        UserProfile.objects.create(user=user, **profile_data)

        return user


    def update(self, instance, validated_data):

        profile_data = validated_data.pop('profile')
        profile = instance.profile

        instance.email = validated_data.get('email', instance.name)
        instance.save()

        profile.dob = profile_data.get('dob', profile.dob)
        profile.phone = profile_data.get('phone', profile.phone)
        profile.receive_newsletter = profile_data.get('receive_newsletter', profile.receive_newsletter)
        profile.save()

        return instance


class TokenSerializer(serializers.ModelSerializer):

    user = serializers.SerializerMethodField()

    class Meta:
        model = TokenModel
        fields = ('key', 'user')

    def get_user(self, instance):
        request = self.context.get('request')
        serializer_context = {
            'request': request,
        }
        return UserSerializer(request.user, context=serializer_context).data

和以下视图:

from rest_framework.permissions import AllowAny
from kofiapi.api.permissions import IsLoggedInUser, IsAdminUser
from rest_framework.viewsets import ModelViewSet
from rest_auth.registration.views import RegisterView
from rest_framework import viewsets

from kofiapi.api.users.models import User
from kofiapi.api.users.serializers import UserSerializer

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

    def get_permissions(self):

        permission_classes = []
        if self.action == 'create':
            permission_classes = [AllowAny]
        elif self.action == 'retrieve' or self.action == 'update' or self.action == 'partial_update':
            permission_classes = [IsLoggedInUser]
        elif self.action == 'list' or self.action == 'destroy':
            permission_classes = [IsAdminUser]
        return [permission() for permission in permission_classes]

class CustomRegisterView(RegisterView):

    def get_response_data(self, user):

        if allauth_settings.EMAIL_VERIFICATION == allauth_settings.EmailVerificationMethod.MANDATORY:
            return {"detail": _("Verification Email Sent")}

        if getattr(settings, 'REST_USE_JWT', False):
            data = {
                'user': user,
                'token': self.token
            }
            return JWTSerializer(data).data
        else:
            return TokenSerializer(user.auth_token, context={"request": self.request}).data

提交与settings相关的消息后出现错误,因此我删除了此部分:

I was getting an error after submission related to settings so I removed this part:

if getattr(settings, 'REST_USE_JWT', False):
                data = {
                    'user': user,
                    'token': self.token
                }
                return JWTSerializer(data).data

但是在提交新用户注册后,我现在遇到以下错误:

but upon submitting a new user for registration I'm getting now the following error:

AttributeError at /api/rest-auth/registration/
Got AttributeError when attempting to get a value for field `email` on serializer `UserSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `AnonymousUser` instance.
Original exception text was: 'AnonymousUser' object has no attribute 'email'.

推荐答案

如果查看rest-auth的源代码,您会发现在注册过程中,它们不会将用户放在任何位置的请求对象中,这就是为什么您尝试从TokenSerializer中的request对象获取用户,它是AnyonymousUser.

If you look at the source code of rest-auth you will see that during registration, they don't put user in the request object anywhere, that's why when you try to fetch the user from request object in your TokenSerializer it is an AnyonymousUser.

您可以做的是像在django登录时一样,将上下文中的用户与请求一起传递到自定义视图中,或在请求对象中进行设置.

What you can do is to pass the user in the context along with the request in your custom view or set it in the request object like django does at the time of login.

这篇关于Django Rest Framework自定义注册视图(RegisterView)无法返回令牌+用户数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆