所以我最近尝试使用djoser,我想使用电子邮件而不是用户名来登录。
Djoser:http://djoser.readthedocs.io/en/latest/index.html
然后我尝试自定义令牌创建/登录以在serializers.py
中从用户名更改为电子邮件原始
class TokenCreateSerializer(serializers.Serializer):
password = serializers.CharField(
required=False, style={'input_type': 'password'}
)
default_error_messages = {
'invalid_credentials': constants.INVALID_CREDENTIALS_ERROR,
'inactive_account': constants.INACTIVE_ACCOUNT_ERROR,
}
def __init__(self, *args, **kwargs):
super(TokenCreateSerializer, self).__init__(*args, **kwargs)
self.user = None
self.fields[User.USERNAME_FIELD] = serializers.CharField(
required=False
)
def validate(self, attrs):
self.user = authenticate(
username=attrs.get(User.USERNAME_FIELD),
password=attrs.get('password')
)
self._validate_user_exists(self.user)
self._validate_user_is_active(self.user)
return attrs
def _validate_user_exists(self, user):
if not user:
self.fail('invalid_credentials')
def _validate_user_is_active(self, user):
if not user.is_active:
self.fail('inactive_account')
被修改
class TokenCreateSerializer(serializers.Serializer):
password = serializers.CharField(
required=False, style={'input_type': 'password'}
)
default_error_messages = {
'invalid_credentials': constants.INVALID_CREDENTIALS_ERROR,
'inactive_account': constants.INACTIVE_ACCOUNT_ERROR,
}
def __init__(self, *args, **kwargs):
super(TokenCreateSerializer, self).__init__(*args, **kwargs)
self.user = None
self.fields[User.EMAIL_FIELD] = serializers.EmailField(
required=False
)
def validate(self, attrs):
self.user = authenticate(
email=attrs.get(User.EMAIL_FIELD),
password=attrs.get('password')
)
self._validate_user_exists(self.user)
self._validate_user_is_active(self.user)
return attrs
def _validate_user_exists(self, user):
if not user:
self.fail('invalid_credentials')
def _validate_user_is_active(self, user):
if not user.is_active:
self.fail('inactive_account')
但我得到的结果是这个
{
"non_field_errors": [
"Unable to login with provided credentials."
]
我确实尝试了其他方法,但都有相同的结果。有没有办法使用电子邮件进行身份验证而不是用户名?
答案 0 :(得分:6)
Djoser
使用authenticate
中的django.contrib.auth
方法。默认情况下,AUTHENTICATION_BACKENDS
设置为使用django.contrib.auth.backends.ModelBackend
,它将尝试使用默认管理器get_by_natural_key
方法获取用户模型,该方法可以:
def get_by_natural_key(self, username):
return self.get(**{self.model.USERNAME_FIELD: username})
您可以查看source code。
我的方法是增强django的UserManager
,假设您的User
模型是AbstractUser
的子类,尝试通过电子邮件或用户名获取用户,例如这样:
from django.contrib.auth.models import UserManager
from django.db.models import Q
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
return self.get(
Q(**{self.model.USERNAME_FIELD: username}) |
Q(**{self.model.EMAIL_FIELD: username})
)
在User
模型
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
...
objects = CustomUserManager()
您现在应该可以使用电子邮件或用户名登录
答案 1 :(得分:1)
我一直在寻找这个问题的答案,并且遇到了这个话题!
一切正常,但后来我找到了一个更简单的解决方案:
DJOSER = {
'LOGIN_FIELD': 'email'
}
我不知道,也许有人会需要它!