如何在序列化器 class 上获取经过身份验证的用户进行验证
How to get authenticated user on serializer class for validation
我正在使用 django-rest-framework 开发一个项目。在我的 API 视图中,经过身份验证的用户可以创建其他用户。但是,只有五个。然后,如果一个用户注册了五个用户,我想在达到限制的响应中发送给他。然后,我需要让经过身份验证的用户进入我的序列化程序,但是我找不到将它从我的 ModelViewSet 传递到我的序列化程序的方法。
这是我的代码:
查看:
class ChildUserViewSet(viewsets.ModelViewSet):
serializer_class = ChildUserSerializer
queryset = User.objects.all()
authentication_classes = (
TokenAuthentication,
)
permission_classes = (
IsAuthenticated,
)
def perform_create(self, serializer):
account_group = self.request.user.userprofile.get_account_group
mobile_number = serializer.data.get('mobile_number')
password = serializer.data.get('password')
user = serializer.save()
user.set_password(password)
user.save()
# Generate user profile
UserProfile.objects.create(
user=user,
mobile_number=mobile_number,
user_type=CHILD,
related_account_group=account_group,
)
序列化器:
class ChildUserSerializer(serializers.ModelSerializer):
mobile_number = serializers.CharField()
class Meta:
model = User
fields = (
'first_name',
'last_name',
'email',
'password',
'mobile_number',
)
def validate(self, data):
"""
Check that the start is before the stop.
"""
# Get authenticated user for raise hit limit validation
def validate_email(self, value):
if User.objects.filter(email=value):
raise serializers.ValidationError("This field must be unique.")
return value
def create(self, validated_data):
username = generate_unique_username(
u'{0}{1}'.format(
validated_data['first_name'],
validated_data['last_name'],
)
)
user = User(
username=username,
first_name=validated_data['first_name'],
last_name=validated_data['last_name'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
return user
然后,在我的序列化程序的 def validate(self, data)
函数中,我想获取当前经过身份验证的用户。
如何将 request.user 从我的 API 视图传递到我的序列化程序?
您可以使用 serializer = ChildUserSerializer(data, context={'request': request})
将额外的上下文传递给您的序列化程序。然后,您可以在序列化程序验证方法中通过 request.user
访问经过身份验证的用户。
在您初始化序列化器时的视图中,如
serializer = ChildUserSerializer(data=request.DATA,context={'request':request})
,在函数调用
内的序列化程序中发送包含 request.Then 的上下文
request=self.context['request']
然后就可以访问request.user
.
我找到了一个更简单的方法来完成这个!事实证明,Rest Framework 的 GenericAPIView
基础 class(所有 Rest Framework 的通用 View
classes 都从中继承)includes a function called get_serializer_context()
:
def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
如您所见,返回的 context
对象包含视图接收到的相同 request
对象。然后设置此对象 when the serializer is initialized:
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
因此,要访问发出请求的用户,您只需在序列化程序的 validate_
函数中调用 self.context['request'].user
:
class TemplateSerializer(serializers.ModelSerializer):
def validate_parent(self, value):
print(self.context['request'].user)
return value
class Meta:
model = Template
最棒的是,您不必覆盖 ModelViewSet
中的任何内容,它们可以像您希望的那样保持简单:
class TemplateViewSet(viewsets.ModelViewSet):
serializer_class = TemplateSerializer
permission_classes = [IsAdmin]
在 djangorestframework > 3.2.4 中,rest_framework.generic.GenericAPIView
class 在序列化程序上下文中默认包含 http 请求。
因此在您的序列化程序中,您可以通过以下方式访问它:self.context['request']
和用户 self.context['request'].user
因此您的 ChildUserSerializer 将如下所示:
class ChildUserSerializer(serializers.ModelSerializer):
mobile_number = serializers.CharField()
....
def validate(self, data):
"""
Check that the start is before the stop.
"""
# Get authenticated user for raise hit limit validation
user = self.context['request'].user
# do something with the user here
def validate_email(self, value):
if User.objects.filter(email=value):
raise serializers.ValidationError("This field must be unique.")
return value
...
我正在使用 django-rest-framework 开发一个项目。在我的 API 视图中,经过身份验证的用户可以创建其他用户。但是,只有五个。然后,如果一个用户注册了五个用户,我想在达到限制的响应中发送给他。然后,我需要让经过身份验证的用户进入我的序列化程序,但是我找不到将它从我的 ModelViewSet 传递到我的序列化程序的方法。
这是我的代码:
查看:
class ChildUserViewSet(viewsets.ModelViewSet):
serializer_class = ChildUserSerializer
queryset = User.objects.all()
authentication_classes = (
TokenAuthentication,
)
permission_classes = (
IsAuthenticated,
)
def perform_create(self, serializer):
account_group = self.request.user.userprofile.get_account_group
mobile_number = serializer.data.get('mobile_number')
password = serializer.data.get('password')
user = serializer.save()
user.set_password(password)
user.save()
# Generate user profile
UserProfile.objects.create(
user=user,
mobile_number=mobile_number,
user_type=CHILD,
related_account_group=account_group,
)
序列化器:
class ChildUserSerializer(serializers.ModelSerializer):
mobile_number = serializers.CharField()
class Meta:
model = User
fields = (
'first_name',
'last_name',
'email',
'password',
'mobile_number',
)
def validate(self, data):
"""
Check that the start is before the stop.
"""
# Get authenticated user for raise hit limit validation
def validate_email(self, value):
if User.objects.filter(email=value):
raise serializers.ValidationError("This field must be unique.")
return value
def create(self, validated_data):
username = generate_unique_username(
u'{0}{1}'.format(
validated_data['first_name'],
validated_data['last_name'],
)
)
user = User(
username=username,
first_name=validated_data['first_name'],
last_name=validated_data['last_name'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
return user
然后,在我的序列化程序的 def validate(self, data)
函数中,我想获取当前经过身份验证的用户。
如何将 request.user 从我的 API 视图传递到我的序列化程序?
您可以使用 serializer = ChildUserSerializer(data, context={'request': request})
将额外的上下文传递给您的序列化程序。然后,您可以在序列化程序验证方法中通过 request.user
访问经过身份验证的用户。
在您初始化序列化器时的视图中,如
serializer = ChildUserSerializer(data=request.DATA,context={'request':request})
,在函数调用
内的序列化程序中发送包含 request.Then 的上下文request=self.context['request']
然后就可以访问request.user
.
我找到了一个更简单的方法来完成这个!事实证明,Rest Framework 的 GenericAPIView
基础 class(所有 Rest Framework 的通用 View
classes 都从中继承)includes a function called get_serializer_context()
:
def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
如您所见,返回的 context
对象包含视图接收到的相同 request
对象。然后设置此对象 when the serializer is initialized:
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
因此,要访问发出请求的用户,您只需在序列化程序的 validate_
函数中调用 self.context['request'].user
:
class TemplateSerializer(serializers.ModelSerializer):
def validate_parent(self, value):
print(self.context['request'].user)
return value
class Meta:
model = Template
最棒的是,您不必覆盖 ModelViewSet
中的任何内容,它们可以像您希望的那样保持简单:
class TemplateViewSet(viewsets.ModelViewSet):
serializer_class = TemplateSerializer
permission_classes = [IsAdmin]
在 djangorestframework > 3.2.4 中,rest_framework.generic.GenericAPIView
class 在序列化程序上下文中默认包含 http 请求。
因此在您的序列化程序中,您可以通过以下方式访问它:self.context['request']
和用户 self.context['request'].user
因此您的 ChildUserSerializer 将如下所示:
class ChildUserSerializer(serializers.ModelSerializer):
mobile_number = serializers.CharField()
....
def validate(self, data):
"""
Check that the start is before the stop.
"""
# Get authenticated user for raise hit limit validation
user = self.context['request'].user
# do something with the user here
def validate_email(self, value):
if User.objects.filter(email=value):
raise serializers.ValidationError("This field must be unique.")
return value
...