背景:
在开发的时候,安卓前端表示拆包会很麻烦,最好是有http状态码,而不是在包里提供错误信息。而django password validator报错时默认的http状态码都是400,错误信息都是在包里提示的。
解决方案:
根据文档,发现rest framework可以通过APIView自定义报错,于是我编写了如下的代码:
from rest_framework.exceptions import APIException
class MinimumLengthError(APIException):
status_code = 401
default_detail = '密码长度太短,至少8位!'
default_code = 'minimum_length_error'
class UserAttributeSimilarityError(APIException):
status_code = 402
default_detail = '密码和用户信息重复度太高!'
default_code = 'user_attribute_similarity_error'
class CommonPassworError(APIException):
status_code = 403
default_detail = '密码太常见!'
default_code = 'common_password_error'
class NumericPasswordError(APIException):
status_code = 404
default_detail = '密码不能是纯数字的!'
default_code = 'numeric_password_error'
class PasswordResetTokenError(APIException):
status_code= 405
default_detail = 'Token错误'
default_code = 'password_reset_token_error'
其中APIException时可以自定义的报错。其参数status code就是我们想要的http状态码。
接着我们修改django的password validator。将每一个validator的报错替换为我们新修改的异常。
# 修改后
class NumericPasswordValidator:
"""
Validate whether the password is alphanumeric.
"""
def validate(self, password, user=None):
if password.isdigit():
# 在这里修改
raise errors.NumericPasswordError
def get_help_text(self):
return _("Your password can't be entirely numeric.")
这样我们就有可以反馈自定义状态码的password validator了。
接着我们可以将django默认的validator修改为我们自己定义的validator,这个可以在settings里设置。这方面教程很多,就不详细展开了。
另一种方式是,为了在用DRF(Django Rest Framework)的同时可以让MTV模式也可以像原来一样报错,有错误提示,我们可以修改django的validators.py这个文件。
首先我们复制一份到项目里,然后修改validate_password函数:
def validate_password(password, user=None, password_validators=None):
"""
Validate whether the password meets all validator requirements.
If the password is valid, return ``None``.
If the password is invalid, raise ValidationError with all error messages.
"""
if password_validators is None:
password_validators = get_default_password_validators()
for validator in password_validators:
try:
validator.validate(password, user)
except APIException as error:
raise error
这样就会只报一个异常,而不是像原来那样报很多error。
接着需要修改初始化validator的函数:
@functools.lru_cache(maxsize=None)
def get_default_password_validators():
return get_password_validators(settings.REST_PASSWORD_VALIDATORS)
# settings里的REST_PASSWORD_VALIDATORS是我们自己建的validator
这样,我们就大功告成了。
之后在authenticate的时候我们就可以用自己的validators.py里面的validate_password函数。
(新人第一次写博客,请多多包涵)