Django:如何验证 AbstractBaseUser?
Django: How do I authenticate an AbstractBaseUser?
我已经为 AbstractBaseUser 创建了一个模型,但正在努力验证它。
这是我的模型:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.password_validation import validate_password
from uuid import uuid4
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, is_staff=False, is_superuser=False, **other_fields):
if not email:
raise ValueError('Email address must be specified')
if not password:
raise ValueError('Password must be specified')
user = self.model(
email=self.normalize_email(email),
is_staff=is_staff,
is_superuser=is_superuser,
**other_fields
)
validate_password(password)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password, **other_fields):
return self._create_user(email, password, False, False, **other_fields)
def create_superuser(self, email, password, **other_fields):
return self._create_user(email, password, True, True, **other_fields)
class CustomUser(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid4(), editable=False, unique=True)
email = models.EmailField(max_length=254, unique=True)
is_superuser = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_premium = models.BooleanField(default=False)
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
display_name = models.CharField(max_length=40)
date_of_birth = models.DateField()
currency = models.CharField(max_length=3)
date_joined = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
REQUIRED_FIELDS = ['first_name', 'display_name', 'date_of_birth', 'currency']
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
objects = CustomUserManager()
def get_full_name(self):
return ("%s %s" % (self.first_name, self.last_name)) if self.last_name != '' else self.first_name
def get_short_name(self):
return self.first_name
def __str__(self):
return "%s %s - %s" % (self.first_name, self.last_name, self.email)
这是我的观点:
from django.contrib.auth import authenticate
from django.http import HttpResponse
def user_login(request):
user = authenticate(request, email=request.POST['email'], password=request.POST['password'])
if user is not None:
login(request, user)
else:
HttpResponse("Invalid email/password pair", status=401)
return HttpResponse()
而且,在我的 settings.py 中,我有以下内容:
AUTH_USER_MODEL = 'myapp.CustomUser'
问题是,每当我发送创建用户并向 user_login
发送请求时,authenticate
方法总是 returns None
,从而触发 HttpResponseBadRequest
。请求中的电子邮件与数据库中的内容匹配,密码与我用来创建用户的密码匹配(我花了比我愿意承认的时间更长的时间使用 print
语句来验证)。
有什么我遗漏的吗? AbstractBaseUsers 是否需要额外的身份验证?
Iain Shelvington 的评论让我找到了答案。
我用来测试身份验证的测试是通过将用户直接保存到数据库来创建用户,如下所示:
from .models import CustomUser
user_data = generate_user()
CustomUser(**user_data).save()
因为用户被直接保存到数据库中,所以它的密码从未经过哈希处理。
我需要像这样创建用户:
from Django.test import Client
from .models import CustomUser
user_data = generate_user()
client = Client()
client.post('/endpoint/used/to/create/user', user_data)
我已经为 AbstractBaseUser 创建了一个模型,但正在努力验证它。
这是我的模型:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.password_validation import validate_password
from uuid import uuid4
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, is_staff=False, is_superuser=False, **other_fields):
if not email:
raise ValueError('Email address must be specified')
if not password:
raise ValueError('Password must be specified')
user = self.model(
email=self.normalize_email(email),
is_staff=is_staff,
is_superuser=is_superuser,
**other_fields
)
validate_password(password)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password, **other_fields):
return self._create_user(email, password, False, False, **other_fields)
def create_superuser(self, email, password, **other_fields):
return self._create_user(email, password, True, True, **other_fields)
class CustomUser(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid4(), editable=False, unique=True)
email = models.EmailField(max_length=254, unique=True)
is_superuser = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_premium = models.BooleanField(default=False)
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
display_name = models.CharField(max_length=40)
date_of_birth = models.DateField()
currency = models.CharField(max_length=3)
date_joined = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
REQUIRED_FIELDS = ['first_name', 'display_name', 'date_of_birth', 'currency']
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
objects = CustomUserManager()
def get_full_name(self):
return ("%s %s" % (self.first_name, self.last_name)) if self.last_name != '' else self.first_name
def get_short_name(self):
return self.first_name
def __str__(self):
return "%s %s - %s" % (self.first_name, self.last_name, self.email)
这是我的观点:
from django.contrib.auth import authenticate
from django.http import HttpResponse
def user_login(request):
user = authenticate(request, email=request.POST['email'], password=request.POST['password'])
if user is not None:
login(request, user)
else:
HttpResponse("Invalid email/password pair", status=401)
return HttpResponse()
而且,在我的 settings.py 中,我有以下内容:
AUTH_USER_MODEL = 'myapp.CustomUser'
问题是,每当我发送创建用户并向 user_login
发送请求时,authenticate
方法总是 returns None
,从而触发 HttpResponseBadRequest
。请求中的电子邮件与数据库中的内容匹配,密码与我用来创建用户的密码匹配(我花了比我愿意承认的时间更长的时间使用 print
语句来验证)。
有什么我遗漏的吗? AbstractBaseUsers 是否需要额外的身份验证?
Iain Shelvington 的评论让我找到了答案。
我用来测试身份验证的测试是通过将用户直接保存到数据库来创建用户,如下所示:
from .models import CustomUser
user_data = generate_user()
CustomUser(**user_data).save()
因为用户被直接保存到数据库中,所以它的密码从未经过哈希处理。
我需要像这样创建用户:
from Django.test import Client
from .models import CustomUser
user_data = generate_user()
client = Client()
client.post('/endpoint/used/to/create/user', user_data)