像许多其他人一样,我正在尝试配置我的Django应用程序以将电子邮件用作用户名字段。我有一些现有的用户帐户,我成功迁移到自定义用户模型,虽然现在自定义模型与Django用户模型相同:
# accounts/models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
我尝试将USERNAME_FIELD
设置为email
的任何时候,都会收到USERNAME_FIELD
无法包含REQUIRED_FIELDS
的错误,以及必须包含的错误独一无二。 (旁注:基本用户不需要电子邮件,因此我不理解第一个错误)
在继承AbstractUser时是否有任何方法可以获得此功能?
或者我只需要子类化AbstractBaseUser
并以example的方式指定每个字段?
如果是后者,我将如何确保定义与Django User模型完全相同的字段?我不想失去我拥有的用户或导致不匹配字段的问题。
为了使用电子邮件地址作为用户名,必须一直完全指定自定义模型似乎很愚蠢,所以也许我在这里遗漏了一些东西。如果有一种方法可以确保Django User模型中的唯一字段,我认为这不是问题。
答案 0 :(得分:3)
正如Django doc所说:
如果您需要的更改纯属行为,并且不需要对数据库中存储的内容进行任何更改,则可以基于用户创建代理模型。
由于您希望将其替换为自定义User
模型:
例如,在某些网站上,使用电子邮件地址作为识别令牌而不是用户名更有意义。
您需要通过继承User
来实现自己的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)