Like many others, I'm trying to configure my Django app to use the email as the username field. I have some existing user accounts that I migrated to a custom user model successfully, though right now the custom model is identical to the Django user model:
像其他许多人一样,我正在试图配置我的Django应用程序以使用电子邮件作为用户名字段。我已经成功地将一些现有的用户帐户迁移到自定义用户模型中,尽管现在自定义模型与Django用户模型相同:
# accounts/models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
Anytime I try to set the USERNAME_FIELD
to email
, I get an error that the USERNAME_FIELD
cannot be included in REQUIRED_FIELDS
, as well as the error that it must be unique. (side note: email isn't required for the base User, so I don't understand the first error)
每当我试图将USERNAME_FIELD设置为电子邮件时,我都会遇到一个错误,即USERNAME_FIELD不能包含在REQUIRED_FIELDS中,也不能包含它必须惟一的错误。(附注:基本用户不需要电子邮件,所以我不理解第一个错误)
Is there any way to get this functionality while subclassing AbstractUser?
在子类化AbstractUser时,有什么方法可以获得这个功能吗?
Or do I just need to subclass AbstractBaseUser
and specify every field, in the manner of this example?
或者我只需要子类AbstractBaseUser并以本例的方式指定每个字段?
If it's the latter, how would I go about making sure I define the exact same fields as the Django User model? I don't want to lose the users I have or cause issues with mismatched fields.
如果是后者,我该如何确保定义与Django用户模型完全相同的字段?我不想失去我拥有的用户,也不想因为不匹配字段而引起问题。
It seems silly to have to go all the way to fully specifying a custom model just to use an email address as the username, so maybe I'm missing something here. If there was a way to ensure unique fields in the Django User model, I don't think this would be an issue.
为了使用电子邮件地址作为用户名,必须完全指定自定义模型,这似乎很愚蠢,所以这里可能漏掉了一些东西。如果有一种在Django用户模型中确保惟一字段的方法,我不认为这是一个问题。
1 个解决方案
#1
1
As Django doc says:
Django医生说:
If the changes you need are purely behavioral, and don’t require any change to what is stored in the database, you can create a proxy model based on User.
如果您需要的更改是纯行为的,并且不需要对数据库中存储的内容进行任何更改,那么您可以基于用户创建代理模型。
Since you want to substitute it with a custom User
model:
因为您想用自定义用户模型替换它:
For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.
例如,在某些网站上,使用电子邮件地址作为标识符而不是用户名更有意义。
You'll need to implement your own User
model by subclassing AbstractBaseUser
. Here is a sample code with django premissions included as well:
您需要通过子类化AbstractBaseUser来实现自己的用户模型。下面是django预任务的示例代码:
class User(AbstractBaseUser, PermissionsMixin):
"""
A class implementing a fully featured User model with admin-compliant
permissions.
Email and password are required. Other fields are optional.
"""
email = models.EmailField(
_('Email Address'), unique=True,
error_messages={
'unique': _("A user with that email already exists."),
}
)
username = models.CharField(
_('Username'), max_length=30, unique=True, blank=True, null=True,
help_text=_('30 characters or fewer. Letters, digits and _ only.'),
validators=[
validators.RegexValidator(
r'^\w+$',
_('Enter a valid username. This value may contain only '
'letters, numbers and _ character.'),
'invalid'
),
],
error_messages={
'unique': _("The username is already taken."),
}
)
is_staff = models.BooleanField(
_('Staff Status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.')
)
is_active = models.BooleanField(
_('Active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.')
)
date_joined = models.DateTimeField(_('Date Joined'), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'email'
class Meta(object):
verbose_name = _('User')
verbose_name_plural = _('Users')
abstract = False
def get_full_name(self):
"""
Returns email instead of the fullname for the user.
"""
return email_to_name(self.email)
def get_short_name(self):
"""
Returns the short name for the user.
This function works the same as `get_full_name` method.
It's just included for django built-in user comparability.
"""
return self.get_full_name()
def __str__(self):
return self.email
def email_user(self, subject, message, from_email=None, **kwargs):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email], **kwargs)
#1
1
As Django doc says:
Django医生说:
If the changes you need are purely behavioral, and don’t require any change to what is stored in the database, you can create a proxy model based on User.
如果您需要的更改是纯行为的,并且不需要对数据库中存储的内容进行任何更改,那么您可以基于用户创建代理模型。
Since you want to substitute it with a custom User
model:
因为您想用自定义用户模型替换它:
For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.
例如,在某些网站上,使用电子邮件地址作为标识符而不是用户名更有意义。
You'll need to implement your own User
model by subclassing AbstractBaseUser
. Here is a sample code with django premissions included as well:
您需要通过子类化AbstractBaseUser来实现自己的用户模型。下面是django预任务的示例代码:
class User(AbstractBaseUser, PermissionsMixin):
"""
A class implementing a fully featured User model with admin-compliant
permissions.
Email and password are required. Other fields are optional.
"""
email = models.EmailField(
_('Email Address'), unique=True,
error_messages={
'unique': _("A user with that email already exists."),
}
)
username = models.CharField(
_('Username'), max_length=30, unique=True, blank=True, null=True,
help_text=_('30 characters or fewer. Letters, digits and _ only.'),
validators=[
validators.RegexValidator(
r'^\w+$',
_('Enter a valid username. This value may contain only '
'letters, numbers and _ character.'),
'invalid'
),
],
error_messages={
'unique': _("The username is already taken."),
}
)
is_staff = models.BooleanField(
_('Staff Status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.')
)
is_active = models.BooleanField(
_('Active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.')
)
date_joined = models.DateTimeField(_('Date Joined'), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'email'
class Meta(object):
verbose_name = _('User')
verbose_name_plural = _('Users')
abstract = False
def get_full_name(self):
"""
Returns email instead of the fullname for the user.
"""
return email_to_name(self.email)
def get_short_name(self):
"""
Returns the short name for the user.
This function works the same as `get_full_name` method.
It's just included for django built-in user comparability.
"""
return self.get_full_name()
def __str__(self):
return self.email
def email_user(self, subject, message, from_email=None, **kwargs):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email], **kwargs)