Django Rest Framework 自定义注册视图 (RegisterView) 未能 return 令牌 + 用户数据
Django Rest Framework Custom Register View (RegisterView) failing to return token + user data
我在我的 django rest 框架应用程序中使用 allauth 和 rest_auth。注册用户时,令牌(密钥)是 returned,我想要实现的是在注册后 return 令牌 + 用户数据。
为此,我有以下序列化器:
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'.
如果您查看 rest-auth
的源代码,您会发现在注册期间,他们不会将用户放入请求对象中的任何地方,这就是为什么当您尝试从 [=11] 获取用户时=] 对象在你的 TokenSerializer
它是一个 AnyonymousUser
。
您可以做的是在自定义视图中将用户与请求一起传递到上下文中,或者像 django 在登录时所做的那样将其设置在请求对象中。
我在我的 django rest 框架应用程序中使用 allauth 和 rest_auth。注册用户时,令牌(密钥)是 returned,我想要实现的是在注册后 return 令牌 + 用户数据。 为此,我有以下序列化器:
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'.
如果您查看 rest-auth
的源代码,您会发现在注册期间,他们不会将用户放入请求对象中的任何地方,这就是为什么当您尝试从 [=11] 获取用户时=] 对象在你的 TokenSerializer
它是一个 AnyonymousUser
。
您可以做的是在自定义视图中将用户与请求一起传递到上下文中,或者像 django 在登录时所做的那样将其设置在请求对象中。