我在Django 1.5项目中有一个自定义用户,它使用email
字段作为用户名:
class MyUser(AbstractUser):
my_custom_field = models.CharField(max_length=20, blank=True, null=True)
USERNAME_FIELD = 'email'
MyUser._meta.get_field_by_name('email')[0]._unique = True
MyUser.REQUIRED_FIELDS.remove('email')
如果我尝试对用户进行身份验证,请执行以下操作:
auth_user = authenticate(username=email, password=password)
login(request, auth_user)
我明白了:
Traceback:
File "/Users/user/dev/proj/app/core/views.py" in post
39. login(request, auth_user)
File "/Users/user/.virtualenvs/proj/lib/python2.7/site-packages/django/contrib/auth/__init__.py" in login
92. request.session[BACKEND_SESSION_KEY] = user.backend
File "/Users/user/.virtualenvs/proj/lib/python2.7/site-packages/django/utils/functional.py" in inner
203. return func(self._wrapped, *args)
Exception Type: AttributeError at /signup
Exception Value: 'AnonymousUser' object has no attribute 'backend'
我应该如何验证自定义用户?
答案 0 :(得分:4)
我的自定义模型未在其明显需要的自定义管理器中实现create_user()
。
这是完整的工作代码:
from django.contrib.auth.models import AbstractUser, BaseUserManager
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractUser):
some_custom_field = models.CharField(max_length=20, blank=True, null=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
MyUser._meta.get_field_by_name('email')[0]._unique = True
MyUser.REQUIRED_FIELDS.remove('email')
Django 1.5“自定义用户”的实现是令人厌恶的。
答案 1 :(得分:1)
Django文档说的是
如果您对Django的用户模型完全满意并且您只想添加一些其他配置文件信息,您可以简单地继承django.contrib.auth.models.AbstractUser并添加您的自定义配置文件字段
因此,AbstractUser的想法是仅在需要向用户模型添加一些额外字段而不创建像Django 1.5之前的单独数据库表时才使用它。
但是当你需要不同的功能时(比如使用电子邮件作为用户名,这可能意味着你不需要用户名字段),更好的方法是扩展AbstractBaseUser类并设置你需要的所有字段。这样设置USERNAME_FIELD='email'
将无需编写自定义create_user()方法。