My custom user model:
我的自定义用户模型:
class MyUser(AbstractBaseUser):
username = models.CharField(unique=True,max_length=30)
email = models.EmailField(unique=True,max_length=75)
is_staff = models.IntegerField(default=False)
is_active = models.IntegerField(default=False)
date_joined = models.DateTimeField(default=None)
# Use default usermanager
objects = UserManager()
USERNAME_FIELD = 'email'
Is there a way to specify multiple USERNAME_FIELD
? Something like ['email','username']
so that users can login via email as well as username ?
有没有办法指定多个USERNAME_FIELD?像''email','username'这样的东西,以便用户可以通过电子邮件和用户名登录?
5 个解决方案
#1
7
The USERNAME_FIELD
setting does not support a list. You could create a custom authentication backend that tries to look up the user on the 'email' or 'username' fields.
USERNAME_FIELD设置不支持列表。您可以创建一个自定义身份验证后端,尝试在“电子邮件”或“用户名”字段中查找用户。
from django.db.models import Q
class UsernameOrEmailBackend(object):
def authenticate(self, username=None, password=None, **kwargs):
try:
# Try to fetch the user by searching the username or email field
user = MyUser.objects.get(Q(username=username)|Q(email=username))
if user.check_password(password):
return user
except MyUser.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user (#20760).
MyUser().set_password(password)
Then, in your settings.py
set AUTHENTICATION_BACKENDS
to your authentication backend:
然后,在您的settings.py中将AUTHENTICATION_BACKENDS设置为您的身份验证后端:
AUTHENTICATION_BACKENDS = ('path.to.UsernameOrEmailBackend,)\
Note that this solution isn't perfect. For example, password resets would only work with the field specified in your USERNAME_FIELD
setting.
请注意,此解决方案并不完美。例如,密码重置仅适用于USERNAME_FIELD设置中指定的字段。
#2
6
We can do that by implementing our own Email authentication backend.
我们可以通过实现自己的电子邮件身份验证后端来实现。
You can do something like below:
您可以执行以下操作:
Step-1 Substite the custom User model in settings:
步骤1在设置中替换自定义用户模型:
Since we would not be using Django's default User
model for authentication, we need to define our custom MyUser
model in settings.py
. Specify MyUser
as the AUTH_USER_MODEL
in the project's settings.
由于我们不会使用Django的默认用户模型进行身份验证,因此我们需要在settings.py中定义自定义MyUser模型。在项目设置中将MyUser指定为AUTH_USER_MODEL。
AUTH_USER_MODEL = 'myapp.MyUser'
Step-2 Write the logic for the custom authentication backend:
步骤2编写自定义身份验证后端的逻辑:
To write our own authentication backend, we need to implement atleast two methods i.e. get_user(user_id)
and authenticate(**credentials)
.
要编写我们自己的身份验证后端,我们需要实现至少两种方法,即get_user(user_id)和authenticate(**凭证)。
from django.contrib.auth import get_user_model
from django.contrib.auth.models import check_password
class MyEmailBackend(object):
"""
Custom Email Backend to perform authentication via email
"""
def authenticate(self, username=None, password=None):
my_user_model = get_user_model()
try:
user = my_user_model.objects.get(email=username)
if user.check_password(password):
return user # return user on valid credentials
except my_user_model.DoesNotExist:
return None # return None if custom user model does not exist
except:
return None # return None in case of other exceptions
def get_user(self, user_id):
my_user_model = get_user_model()
try:
return my_user_model.objects.get(pk=user_id)
except my_user_model.DoesNotExist:
return None
Step-3 Specify the custom authentication backend in settings:
步骤3在设置中指定自定义身份验证后端:
After writing the custom authentication backend, specify this authentication backend in the AUTHENTICATION_BACKENDS
setting.
编写自定义身份验证后端后,在AUTHENTICATION_BACKENDS设置中指定此身份验证后端。
AUTHENTICATION_BACKENDS
contains the list of authentication backends to be used. Django tries authenticating across all of its authentication backends. If the first authentication method fails, Django tries the second one, and so on, until all backends have been attempted.
AUTHENTICATION_BACKENDS包含要使用的身份验证后端列表。 Django尝试对其所有身份验证后端进行身份验证。如果第一个身份验证方法失败,Django会尝试第二个身份验证方法,依此类推,直到尝试了所有后端。
AUTHENTICATION_BACKENDS = (
'my_app.backends.MyEmailBackend', # our custom authentication backend
'django.contrib.auth.backends.ModelBackend' # fallback to default authentication backend if first fails
)
If authentication via MyEmailBackend
fails i.e user could not be authenticated via email
, then we use the Django's default authentication ModelBackend
which will try to authenticate via username
field of MyUser
model.
如果通过MyEmailBackend进行身份验证失败,即用户无法通过电子邮件进行身份验证,那么我们将使用Django的默认身份验证ModelBackend,它将尝试通过MyUser模型的用户名字段进行身份验证。
#3
2
No, you cannot have more than one field defined in USERNAME_FIELD
.
不,您不能在USERNAME_FIELD中定义多个字段。
One option would be to write your own custom login to check for both fields yourself. https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
一种选择是编写自己的自定义登录以自行检查这两个字段。 https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
i.e. change the backend to your own. AUTHENTICATION_BACKENDS
then write an authenticate method and check the username on both fields in the DB.
即将后端更改为您自己的。然后,AUTHENTICATION_BACKENDS编写一个验证方法并检查数据库中两个字段的用户名。
PS you may want to use unique_together
on your model so you don't run into problems.
PS你可能想在你的模型上使用unique_together,这样你就不会遇到问题。
Another option would be to use the actual field username
to store both string and email.
另一种选择是使用实际字段用户名来存储字符串和电子邮件。
#4
0
Unfortunately, not out-of-the box.
不幸的是,不是开箱即用的。
The auth contrib module asserts that the USERNAME_FIELD value is mono-valued.
auth contrib模块断言USERNAME_FIELD值是单值的。
See https://github.com/django/django/search?q=USERNAME_FIELD
请参阅https://github.com/django/django/search?q=USERNAME_FIELD
If you want to have a multi-valued USERNAME_FIELD, you will either have to write the corresponding logic or to find a package that allow it.
如果您想拥有一个多值USERNAME_FIELD,您将需要编写相应的逻辑或找到允许它的包。
#5
0
If your USERNAME_FIELD is username
and the user logs in with email
, maybe you can write a code that fetches the username
using the provided email
and then use that username
along with the password
to authenticate.
如果您的USERNAME_FIELD是用户名并且用户使用电子邮件登录,则可能您可以编写使用提供的电子邮件获取用户名的代码,然后使用该用户名和密码进行身份验证。
#1
7
The USERNAME_FIELD
setting does not support a list. You could create a custom authentication backend that tries to look up the user on the 'email' or 'username' fields.
USERNAME_FIELD设置不支持列表。您可以创建一个自定义身份验证后端,尝试在“电子邮件”或“用户名”字段中查找用户。
from django.db.models import Q
class UsernameOrEmailBackend(object):
def authenticate(self, username=None, password=None, **kwargs):
try:
# Try to fetch the user by searching the username or email field
user = MyUser.objects.get(Q(username=username)|Q(email=username))
if user.check_password(password):
return user
except MyUser.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user (#20760).
MyUser().set_password(password)
Then, in your settings.py
set AUTHENTICATION_BACKENDS
to your authentication backend:
然后,在您的settings.py中将AUTHENTICATION_BACKENDS设置为您的身份验证后端:
AUTHENTICATION_BACKENDS = ('path.to.UsernameOrEmailBackend,)\
Note that this solution isn't perfect. For example, password resets would only work with the field specified in your USERNAME_FIELD
setting.
请注意,此解决方案并不完美。例如,密码重置仅适用于USERNAME_FIELD设置中指定的字段。
#2
6
We can do that by implementing our own Email authentication backend.
我们可以通过实现自己的电子邮件身份验证后端来实现。
You can do something like below:
您可以执行以下操作:
Step-1 Substite the custom User model in settings:
步骤1在设置中替换自定义用户模型:
Since we would not be using Django's default User
model for authentication, we need to define our custom MyUser
model in settings.py
. Specify MyUser
as the AUTH_USER_MODEL
in the project's settings.
由于我们不会使用Django的默认用户模型进行身份验证,因此我们需要在settings.py中定义自定义MyUser模型。在项目设置中将MyUser指定为AUTH_USER_MODEL。
AUTH_USER_MODEL = 'myapp.MyUser'
Step-2 Write the logic for the custom authentication backend:
步骤2编写自定义身份验证后端的逻辑:
To write our own authentication backend, we need to implement atleast two methods i.e. get_user(user_id)
and authenticate(**credentials)
.
要编写我们自己的身份验证后端,我们需要实现至少两种方法,即get_user(user_id)和authenticate(**凭证)。
from django.contrib.auth import get_user_model
from django.contrib.auth.models import check_password
class MyEmailBackend(object):
"""
Custom Email Backend to perform authentication via email
"""
def authenticate(self, username=None, password=None):
my_user_model = get_user_model()
try:
user = my_user_model.objects.get(email=username)
if user.check_password(password):
return user # return user on valid credentials
except my_user_model.DoesNotExist:
return None # return None if custom user model does not exist
except:
return None # return None in case of other exceptions
def get_user(self, user_id):
my_user_model = get_user_model()
try:
return my_user_model.objects.get(pk=user_id)
except my_user_model.DoesNotExist:
return None
Step-3 Specify the custom authentication backend in settings:
步骤3在设置中指定自定义身份验证后端:
After writing the custom authentication backend, specify this authentication backend in the AUTHENTICATION_BACKENDS
setting.
编写自定义身份验证后端后,在AUTHENTICATION_BACKENDS设置中指定此身份验证后端。
AUTHENTICATION_BACKENDS
contains the list of authentication backends to be used. Django tries authenticating across all of its authentication backends. If the first authentication method fails, Django tries the second one, and so on, until all backends have been attempted.
AUTHENTICATION_BACKENDS包含要使用的身份验证后端列表。 Django尝试对其所有身份验证后端进行身份验证。如果第一个身份验证方法失败,Django会尝试第二个身份验证方法,依此类推,直到尝试了所有后端。
AUTHENTICATION_BACKENDS = (
'my_app.backends.MyEmailBackend', # our custom authentication backend
'django.contrib.auth.backends.ModelBackend' # fallback to default authentication backend if first fails
)
If authentication via MyEmailBackend
fails i.e user could not be authenticated via email
, then we use the Django's default authentication ModelBackend
which will try to authenticate via username
field of MyUser
model.
如果通过MyEmailBackend进行身份验证失败,即用户无法通过电子邮件进行身份验证,那么我们将使用Django的默认身份验证ModelBackend,它将尝试通过MyUser模型的用户名字段进行身份验证。
#3
2
No, you cannot have more than one field defined in USERNAME_FIELD
.
不,您不能在USERNAME_FIELD中定义多个字段。
One option would be to write your own custom login to check for both fields yourself. https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
一种选择是编写自己的自定义登录以自行检查这两个字段。 https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
i.e. change the backend to your own. AUTHENTICATION_BACKENDS
then write an authenticate method and check the username on both fields in the DB.
即将后端更改为您自己的。然后,AUTHENTICATION_BACKENDS编写一个验证方法并检查数据库中两个字段的用户名。
PS you may want to use unique_together
on your model so you don't run into problems.
PS你可能想在你的模型上使用unique_together,这样你就不会遇到问题。
Another option would be to use the actual field username
to store both string and email.
另一种选择是使用实际字段用户名来存储字符串和电子邮件。
#4
0
Unfortunately, not out-of-the box.
不幸的是,不是开箱即用的。
The auth contrib module asserts that the USERNAME_FIELD value is mono-valued.
auth contrib模块断言USERNAME_FIELD值是单值的。
See https://github.com/django/django/search?q=USERNAME_FIELD
请参阅https://github.com/django/django/search?q=USERNAME_FIELD
If you want to have a multi-valued USERNAME_FIELD, you will either have to write the corresponding logic or to find a package that allow it.
如果您想拥有一个多值USERNAME_FIELD,您将需要编写相应的逻辑或找到允许它的包。
#5
0
If your USERNAME_FIELD is username
and the user logs in with email
, maybe you can write a code that fetches the username
using the provided email
and then use that username
along with the password
to authenticate.
如果您的USERNAME_FIELD是用户名并且用户使用电子邮件登录,则可能您可以编写使用提供的电子邮件获取用户名的代码,然后使用该用户名和密码进行身份验证。