如何将登录表单自定义为用户的电子邮件而不是用户的用户名



我正在遵循Django登录教程,完成后我发现登录表单需要用户名和密码,但我想用用户的电子邮件代替用户名。

views.py

@login_required
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})


@login_required
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('profile')

else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)

context = {
'u_form': u_form,
'p_form': p_form
}

return render(request, 'users/profile.html', context)

form .py


class UserRegisterForm(UserCreationForm):
email = forms.EmailField()

class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']


class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()

class Meta:
model = User
fields = ['username', 'email']


class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']

模板

<form class="login100-form validate-form" method="POST">
<span class="login100-form-title p-b-34">
Account Login
</span>
<fieldset class="input100 m-b-20">
{% csrf_token %}
{{ form|crispy }}
</fieldset>
<div class="container-login100-form-btn">
<button class="login100-form-btn" type="submit" style="width: 90%">
Sign in
</button>
</div>
<div class="w-full text-center p-t-27 p-b-100">
<a class="txt2" href="{% url 'password_reset' %}">Forgot Password ?</a>
</div>
</form>

我的问题是如何从用户名更改为用户的电子邮件?

要用email创建Django登录我们必须覆盖Default User,我们可以开始编写模型,但首先你可能想为你的用户创建不同的应用程序(这是一个很好的做法)。

Models.py

class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that is built in.
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # Email & Password are required by default.
def get_full_name(self):
# The user is identified by their email address
return self.email

Django有内置的User Manager方法。为了使我们的自定义用户模型正常工作,我们必须自定义它们。

class UserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user

那么你需要运行迁移。

python manage.py makemigrations
python manage.py migrate

这是你可以关注的帖子:Here

进入models.py,并添加

USERNAME_FIELD = 'email'

从form中移除username

推荐使用django-allauth。它是一个功能强大的用户身份验证工具,您可以将其添加到settings.py:

中,将用户设置为使用email而不是用户名登录。
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_AUTHENTICATION_METHOD='email'

您可以通过两种方式做到这一点。通过使用AbstractUser或AbstractBaseUser

AbstractUser:通过子类化AbstractUser来定义用户类。AbstractUser类具有user中可能需要的所有必要字段(您可以添加更多)。你可以将email设置为用户名字段,并将用户名字段设置为空。如果您对User模型上的现有字段很满意,并且只想删除username字段,请使用此选项。

class User(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []

AbstractBaseUser:通过子类化AbstractBaseUser来定义用户类。它没有现有的字段。如果您想从头开始创建自己的全新User模型,请使用此选项。

class User(AbstractBaseUser):
email = models.EmailField(('email address'), unique=True)
active = models.BooleanField(default=True)  # can login
staff = models.BooleanField(default=False)  # staff user non super
admin = models.BooleanField(default=False)  # superuser
first_name = models.CharField(max_length=30, blank=True, null= True)
last_name = models.CharField(max_length=30, blank=True, null= True)

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []

您需要根据需要编写您的自定义管理器。

您可以创建backend .py

def authenticate(username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
# print(user.username)
return user
except User.DoesNotExist:
return None

class EmailOrUsernameModelBackend(object):
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
# print(user.username)
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

之后,在settings.py

中添加以下代码
AUTHENTICATION_BACKENDS = (
'users.backends.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)

修改views.py

from django.contrib.auth import login as auth_login
def ajax_login(request):
if request.method == 'POST':
username = request.POST.get('email', '').strip()
password = request.POST.get('password', '').strip()
if username and password:
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user, backend='users.backends.EmailOrUsernameModelBackend')
try:
order = Order.objects.filter(user=request.user)
except Order.DoesNotExist:
order = None
if order is not None:
exist_order = True
else:
exist_order = False
data = {'success': True, 'order': exist_order}
else:
data = {'success': False, 'message': 'User is not active'}
else:
data = {'success': False, 'message': 'Invalid username or password'}
return JsonResponse(data)

相关内容

最新更新