Django 用户模型中的多个 USERNAME_FIELD
Multiple USERNAME_FIELD in django 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'
有没有办法指定多个 USERNAME_FIELD
?类似于 ['email','username']
这样用户可以通过电子邮件和用户名登录 ?
USERNAME_FIELD
设置不支持列表。您可以创建一个 custom authentication backend 来尝试在 'email' 或 'username' 字段中查找用户。
from django.db.models import Q
from django.contrib.auth import get_user_model
MyUser = get_user_model()
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)
然后,在您的 settings.py
中将 AUTHENTICATION_BACKENDS
设置为您的身份验证后端:
AUTHENTICATION_BACKENDS = ('path.to.UsernameOrEmailBackend,)\
请注意,此解决方案并不完美。例如,密码重置仅适用于 USERNAME_FIELD
设置中指定的字段。
很遗憾,不是开箱即用的。
auth contrib 模块断言 USERNAME_FIELD 值是单值的。
见https://github.com/django/django/search?q=USERNAME_FIELD
如果你想要多值USERNAME_FIELD,你要么自己写相应的逻辑,要么找一个允许的包。
不,您不能在 USERNAME_FIELD
中定义多个字段。
一种选择是编写您自己的自定义登录名以自行检查这两个字段。 https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
即将后端更改为您自己的。 AUTHENTICATION_BACKENDS
然后编写一个身份验证方法并检查数据库中两个字段上的用户名。
PS 你可能想在你的模型上使用 unique_together
这样你就不会 运行 遇到问题。
另一种选择是使用实际字段 username
来存储字符串和电子邮件。
我们可以通过实现自己的电子邮件身份验证后端来做到这一点。
您可以执行如下操作:
Step-1 在设置中替换自定义用户模型:
由于我们不会使用 Django 的默认 User
模型进行身份验证,因此我们需要在 settings.py
中定义我们的自定义 MyUser
模型。在项目设置中将 MyUser
指定为 AUTH_USER_MODEL
。
AUTH_USER_MODEL = 'myapp.MyUser'
Step-2 编写自定义认证后端逻辑:
要编写我们自己的身份验证后端,我们需要至少实现两个方法,即 get_user(user_id)
和 authenticate(**credentials)
。
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 在设置中指定自定义认证后端:
编写自定义身份验证后端后,在 AUTHENTICATION_BACKENDS
设置中指定此身份验证后端。
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
)
如果通过 MyEmailBackend
的身份验证失败,即用户无法通过 email
进行身份验证,那么我们将使用 Django 的默认身份验证 ModelBackend
,它将尝试通过 username
进行身份验证MyUser
模型的字段。
如果您的 USERNAME_FIELD 是 username
并且用户使用 email
登录,也许您可以编写代码来使用提供的 [=11] 获取 username
=] 然后使用 username
和 password
进行身份验证。
REQUIRED_FIELDS = []
你可以定义多个 username_fields
我的自定义用户模型:
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'
有没有办法指定多个 USERNAME_FIELD
?类似于 ['email','username']
这样用户可以通过电子邮件和用户名登录 ?
USERNAME_FIELD
设置不支持列表。您可以创建一个 custom authentication backend 来尝试在 'email' 或 'username' 字段中查找用户。
from django.db.models import Q
from django.contrib.auth import get_user_model
MyUser = get_user_model()
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)
然后,在您的 settings.py
中将 AUTHENTICATION_BACKENDS
设置为您的身份验证后端:
AUTHENTICATION_BACKENDS = ('path.to.UsernameOrEmailBackend,)\
请注意,此解决方案并不完美。例如,密码重置仅适用于 USERNAME_FIELD
设置中指定的字段。
很遗憾,不是开箱即用的。
auth contrib 模块断言 USERNAME_FIELD 值是单值的。
见https://github.com/django/django/search?q=USERNAME_FIELD
如果你想要多值USERNAME_FIELD,你要么自己写相应的逻辑,要么找一个允许的包。
不,您不能在 USERNAME_FIELD
中定义多个字段。
一种选择是编写您自己的自定义登录名以自行检查这两个字段。 https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
即将后端更改为您自己的。 AUTHENTICATION_BACKENDS
然后编写一个身份验证方法并检查数据库中两个字段上的用户名。
PS 你可能想在你的模型上使用 unique_together
这样你就不会 运行 遇到问题。
另一种选择是使用实际字段 username
来存储字符串和电子邮件。
我们可以通过实现自己的电子邮件身份验证后端来做到这一点。
您可以执行如下操作:
Step-1 在设置中替换自定义用户模型:
由于我们不会使用 Django 的默认 User
模型进行身份验证,因此我们需要在 settings.py
中定义我们的自定义 MyUser
模型。在项目设置中将 MyUser
指定为 AUTH_USER_MODEL
。
AUTH_USER_MODEL = 'myapp.MyUser'
Step-2 编写自定义认证后端逻辑:
要编写我们自己的身份验证后端,我们需要至少实现两个方法,即 get_user(user_id)
和 authenticate(**credentials)
。
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 在设置中指定自定义认证后端:
编写自定义身份验证后端后,在 AUTHENTICATION_BACKENDS
设置中指定此身份验证后端。
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
)
如果通过 MyEmailBackend
的身份验证失败,即用户无法通过 email
进行身份验证,那么我们将使用 Django 的默认身份验证 ModelBackend
,它将尝试通过 username
进行身份验证MyUser
模型的字段。
如果您的 USERNAME_FIELD 是 username
并且用户使用 email
登录,也许您可以编写代码来使用提供的 [=11] 获取 username
=] 然后使用 username
和 password
进行身份验证。
REQUIRED_FIELDS = []
你可以定义多个 username_fields