Django Пользовательское представление реестра Rest Framework (RegisterView) не возвращает токен + данные пользователя - PullRequest
0 голосов
/ 05 мая 2020

Я использую allauth и rest_auth в моем django приложении rest framework. При регистрации пользователя возвращается токен (ключ), и я пытаюсь вернуть токен + данные пользователя после регистрации. Для этого у меня есть следующий сериализатор:

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, поэтому я удалил эту часть :

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

но при отправке нового пользователя для регистрации я получаю следующую ошибку:

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'.

1 Ответ

1 голос
/ 07 мая 2020

Если вы посмотрите исходный код rest-auth, вы увидите, что во время регистрации они нигде не помещают пользователя в объект запроса, поэтому, когда вы пытаетесь получить пользователя из объекта request в вашем TokenSerializer это AnyonymousUser.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...