Python DRF使用序列化程序验证正文并序列化响应
我在django中有以下视图,它登录用户并在用户数据使用序列化程序序列化后发回响应Python DRF使用序列化程序验证正文并序列化响应,python,django,django-rest-framework,Python,Django,Django Rest Framework,我在django中有以下视图,它登录用户并在用户数据使用序列化程序序列化后发回响应 @api_view(['POST']) def sign_in(request): username = request.data['username'] password = request.data['password'] user = authenticate(username=username, password=password) if user is not None
@api_view(['POST'])
def sign_in(request):
username = request.data['username']
password = request.data['password']
user = authenticate(username=username, password=password)
if user is not None:
update_last_login(None, user) # update the user's last login date
serializer = UserSignInSerializer(user)
return Response(serializer.data)
return Response('Invalid login credentials', status=401)
这个视图中我不喜欢的是直接从主体中提取用户名和密码的方式。我想使用相同的序列化程序来检查主体是否有效。这是可能的还是我必须创建一个新的序列化程序来验证请求?以下是现有的序列化程序:
class UserSignInSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email', 'username', 'profile']
您可以从django rest框架使用。这是一个很好的代码,您可以从中使用。下面我给大家举一个例子:
class LoginSerializer(serializers.Serializer):
username = serializers.CharField(required=False, allow_blank=True)
password = serializers.CharField(style={'input_type': 'password'})
def authenticate(self, **kwargs):
return authenticate(self.context['request'], **kwargs)
def _validate_username(self, username, password):
user = None
if username and password:
user = self.authenticate(email=email, password=password)
else:
msg = _('Must include "username" and "password".')
raise exceptions.ValidationError(msg)
return user
def validate(self, attrs):
username = attrs.get('username')
password = attrs.get('password')
user = self._validate_username(username, password)
if user:
if not user.is_active:
msg = _('User account is disabled.')
raise exceptions.ValidationError(msg)
else:
msg = _('Unable to log in with provided credentials.')
raise exceptions.ValidationError(msg)
attrs['user'] = user
return attrs
并在视图中使用此序列化程序:
@api_view(['POST'])
def sign_in(request):
serializer = LoginSerializer(data=request.data, context={'request': request})
if serializer.is_valid():
user = serializer.validated_data['user']
update_last_login(None, user) # update the user's last login date
u_serializer = UserSignInSerializer(user)
return Response(u_serializer.data)
return Response(serializer.errors, status=401)
那么答案就是创建一个新的序列化程序?这是否意味着我必须为每个视图创建两个序列化程序?一个用于req,一个用于res?您可以在一个序列化程序中实现它。但是您需要将first_name last name etc设置为只读字段和密码只读字段。但依我看,这样一来,代码就不会干净,一个序列化程序承载了所有。但是有两个具有两个不同目的的序列化程序对我来说似乎更好。这样,您可以保持登录信息和用户信息的不同,并在不影响其他信息的情况下更改其中任何一个。您所说的
是什么意思?这难道不意味着我必须为我拥有的每个视图创建两个序列化器吗?您上面的视图使用两个序列化器。如果req主体包含与responseWell不同的数据,那么我可能必须对所有视图执行此操作,如果请求和响应完全不同,那么最好有两个序列化器。但通常使用一个序列化程序。在这种情况下,正如我前面所说,您可以将它们放在一个。但对于更干净的代码,我使用了两个序列化程序。