我正在使用Django内置身份验证。可以通过django登录表单中的用户名和密码登录用户。但我希望用户也能够使用电子邮件ID和密码登录。
登录表单仅具有用户名字段。我们能否使用此登录字段输入电子邮件ID或用户名并验证用户身份。
这是我的django登录视图
class LoginForm(generic.CreateView):
print("login")
form_class = LoginForm
template_name = "feed/SignUp.html"
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
UserModel = get_user_model()
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('')
else:
print(form.errors)
我的想法与我们可以通过用户名或电子邮件登录GitHub帐户一样。我应该怎么做才能做到这一点?
答案 0 :(得分:0)
您可以检查用户名输入是否为带有以下内容的电子邮件:
from django.core.validators import validate_email
try:
validate_email(username_field) # If it's a valid email
username = User.objects.get(email=username_field).username # Get username with email
authenticate(username=username, password=password_field) # Authenticate that user
except:
# It's a username, so do the normal authentication
答案 1 :(得分:0)
您可能必须扩展用户模型并添加电子邮件作为字段。此外,您必须更新Manager才能完成工作。
以下代码段仅供您参考。
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
class UserManager(BaseUserManager):
"""
Override auth.models.UserManager by extending BaseUserManager.
We changed _create_user method to take email as username.
"""
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
"""
Override Django default User model class by extending AbstractBaseUser.
"""
email = models.EmailField(_('email address'), blank=False, unique=True, error_messages={ 'unique': _("A user with that email already exists."),})
is_active = models.BooleanField(_('active'), default=True)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def clean(self):
super(User, self).clean()
self.email = self.__class__.objects.normalize_email(self.email)
def encode_uid(self):
return urlsafe_base64_encode(force_bytes(self.pk))
您可能必须重写AbstractBaseUser的get_user_name和其他方法。
答案 2 :(得分:0)
使用Django的内置用户模型,我们必须通过覆盖authenticate
here的ModelBackend
方法并添加您的AUTHENTICATION_BACKENDS
中settings.py
的自定义后端路径。
# project/app/backends.py
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
class EmailAuthBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None or password is None:
return
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=username) # try with email
except UserModel.DoesNotExist:
try:
user = UserModel.objects.get(username=username) # or username
except UserModel.DoesNotExist:
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
# project/settings.py
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend', # default
'app.backends.EmailAuthBackend', # custom
]
# remember to override the login redirect url or it defaults to accounts/profile/
LOGIN_REDIRECT_URL = '/'
文档:https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#authentication-backends
通过这种方式,您仍然可以访问父类的get_user
和其余方法,而无需重新实现它们。