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
and the following view:
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
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'.
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
.
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.