【Django2.0学习笔记】33.发挥邮箱作用

33、发挥邮箱作用

1、邮箱发挥作用

  • 减少垃圾用户
  • 保证账户安全
  • 推送消息(通知)
    在这里插入图片描述

2、引导用户填写邮箱

可从注册的时候要求填写邮箱:
(1)发送邮件,填写验证码
(2)发送验证邮箱链接
(3)直接使用邮箱注册

当然也可以不要求填邮箱

建议:一经绑定,不可解绑
在这里插入图片描述

第一种方式:发送邮件,填写验证码

我们想在注册表单上加多一个验证码字段,点击“发送验证码”,填写上验证码就可以。
修改user/forms.py中的RegForm如下(复制BindEmailForm里面验证码那段代码):
在这里插入图片描述

另外,我们还要让页面有“发送验证码”的按钮,这里是注册页面,所以我们在user/templates/user/register.html中修改如下(从bind_email.html复制过来):
在这里插入图片描述
刷新注册表单的页面
在这里插入图片描述

我们提交注册表单,是在处理方法views.py中的register完成的,加进来验证码对其中的验证数据部分没有产生任何影响,所以我们只需要在form里面进行校验的时候对这个验证码进行处理,

所以我们回到forms.py,处理验证码

处理验证码在BindEmailForm里面我们也做过一定的处理,我们可以拿过来做一下处理,复制 判断验证码是否为空这块def clean_verification_code到RegForm里面。
在这里插入图片描述

另外在BindEmailForm里面,在def __init__(self, *args, **kwargs):这里还传了一个request参数,传这个参数主要是为了获取session,获取到session后就可以获取到发送的验证码是什么,我们发现获取的session里面的key指定是‘bind_email_code’,而我们刚刚发送验证码的地方(views.py中send_verification_code里)这里要保存session,保存验证码到key为‘bind_email_code’的session中,已经写固定了,这样不太好,因为在这个地方是注册发送的验证码而不是绑定邮箱发送的验证码,所以我们要把这个区分对待。
那区分对待的话,我们调用这个处理方法的时候,这里又不能传参数过来,那我们可以考虑参数从前端页面通过GET请求传进来,修改views.py如下:
在这里插入图片描述

添加了send_for之后,我们就有几个地方需要更改了,

绑定邮箱 发送验证码请求这里,data需要加一个‘send_for’字段,修改bind_email.html如下:
在这里插入图片描述
注册的地方,同样的发送验证码这里,data也需要加上‘send_for’字段,修改register.html如下:
在这里插入图片描述

对应的,有些地方就需要更改了,
把forms.py里的BindEmailForm里 判断验证码 和传入request 这块的代码,复制到RegForm里
在这里插入图片描述

那RegForm需要传入request这个参数的话,views.py中register这里,提交请求这里我们就需要把request参数给它传进来
在这里插入图片描述

这样,注册加了验证码 这块,我们就把逻辑实现出来了
测试一下,刷新页面,我们找一个新的邮箱进行注册,可以看到注册验证邮箱这一步已经完成
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

不过这里有一个bug没有处理。
在判断验证码之后,如果成功,session还是保留的,那有时候可能session会重复去使用,这样就可能会有问题,例如反复用同一个验证码在同一个电脑上反复去注册,这是可以的。因此这里就需要改下,需要清session。修改views.py如下:(在 forms.py 中的 RegForm 和 BindEmailForm 两处的 session,分别为‘bind_email_code’‘register_code’,对应的views.py中的registerbind_email方法中,需要清除request.session
在这里插入图片描述

在这里插入图片描述

到这里,大家可能有一个疑问,既然我们注册的时候已经绑定邮箱了,我们还需要进行填写邮箱绑定邮箱操作吗?
这里有一个逻辑,我们一开始用用户名里面有个superuser超级管理员这个用户,我们用代码创建的时候没有写邮箱,所以是没有邮箱的,自然而然就产生了需要填写邮箱这个需求。所以如果不想做单独填写邮箱绑定邮箱的操作,我们可以把没有邮箱的superuser账号的邮箱补上去。

3、修改登录方式

用户名和邮箱均可以登录

在这里插入图片描述

修改forms.py 中的LoginForm:
在这里插入图片描述
刷新页面,我们尝试用用户名登录和用密码登录这两种方式,都能登陆成功
在这里插入图片描述
在这里插入图片描述

4、修改密码

  • 1、登录的情况,修改密码
  • 2、未登录情况,忘记密码
    • 发送验证码到邮箱
    • 修复bug(session未删除)
      在这里插入图片描述

1、登录的情况,修改密码

对应的表单,需要增加一个修改密码的表单,修改forms.py如下:
在这里插入图片描述

# 修改密码的表单
class ChangePasswordForm(forms.Form):
	# 三个字段:旧密码、新密码、再输一遍密码
	old_password = forms.CharField(
		label='旧的密码', 
		widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder': '请输入旧的密码'})
	)
	new_password = forms.CharField(
		label='新的密码', 
		widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder': '请输入新的密码'})
	)
	new_password_again = forms.CharField(
		label='请再次输入新的密码', 
		widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder': '请再次输入新的密码'})
	)

	def __init__(self, *args, **kwargs):	
		if 'user' in kwargs:
			self.user = kwargs.pop('user')
		super(ChangePasswordForm, self).__init__(*args, **kwargs)

	# 验证新的密码是否一致
	def clean(self):
		new_password = self.cleaned_data.get('new_password', '')
		new_password_again = self.cleaned_data.get('new_password_again', '')
		if new_password != new_password_again or new_password == '':
			raise forms.ValidationError('两次输入的密码不一致')
		return self.cleaned_data

	# 验证旧的密码是正确的	
	def clean_old_password(self):
		old_password = self.cleaned_data.get('old_password', '')
		if not self.user.check_password(old_password):
			raise forms.ValidationError('旧的密码错误')
		return old_password

验证旧的密码有两种方法:1、通过user对象的check_password()方法去验证,这里传一个密码进来就可以;2、通过登陆的auth.authenticate,需要username这个对象,实际上是通过验证用户名跟密码是否是一致的,如果一致就返回一个非None的对象,如果密码不正确的话,就返回None。

对应的链接,修改urls.py如下:
在这里插入图片描述

对应的处理方法,修改views.py如下:
其中,密码修改成功之后,应该有其他的处理逻辑,例如修改成功之后登出,让用户再重新登录一遍
在这里插入图片描述

def change_password(request):
	redirect_to = reverse('home')

	if request.method == 'POST':
		form = ChangePasswordForm(request.POST, user=request.user)	# 获取form表单
		if form.is_valid():
			user = request.user
			old_password = form.cleaned_data['old_password']
			new_password = form.cleaned_data['new_password']
			user.set_password(new_password)
			user.save()
			auth.logout(request)
			return redirect(redirect_to)
	else:
		form = ChangePasswordForm()

	context = {}
	context['page_title'] = '修改密码'
	context['form_title'] = '修改密码'
	context['submit_text'] = '修改'
	context['form'] = form
	context['return_back_url'] = redirect_to
	return render(request, 'form.html', context)

对应模板页面调用这个方法,修改user_info.html如下:
在这里插入图片描述
然后在导航栏右侧的下拉菜单那里,加上修改密码这个选项,修改base.html:
在这里插入图片描述
刷新页面
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2、未登录情况,忘记密码

另外,还有个逻辑要处理,我们可能忘记密码,我们需要在表单上加上“忘记密码”对应的选项,找回密码需要怎么操作呢?最直接的方法是我们可以把密码发送到邮箱,但是django没有记录明文的密码,所以忘记密码最好的处理方法是重置密码,重置密码的话就需要验证这个账户是不是本人操作,最好是验证一下邮箱。

增加一个忘记密码的form表单,修改forms.py如下:
在这里插入图片描述

# 忘记密码的表单
class ForgotPasswordForm(forms.Form):
	# 三个字段:邮箱、验证码、新的密码
	email = forms.EmailField(
		label='邮箱',
		widget=forms.EmailInput(attrs={'class':'form-control', 'placeholder': '请输入绑定过的邮箱'})
	)
	verification_code = forms.CharField(
		label='验证码', 
		required=False,
		max_length=20,
		widget=forms.TextInput(
			attrs={'class':'form-control', 'placeholder': '点击“发送验证码”发送到邮箱'}
		)
	)
	new_password = forms.CharField(
		label='新的密码', 
		widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder': '请输入新的密码'})
	)

	def __init__(self, *args, **kwargs):	
		if 'request' in kwargs:
			self.request = kwargs.pop('request')
		super(ForgotPasswordForm, self).__init__(*args, **kwargs)

	# 判断邮箱是否存在
	def clean_email(self):
		email = self.cleaned_data['email'].strip()
		if not User.objects.filter(email=email).exists():
			raise forms.ValidationError('邮箱不存在')
		return email

	# 判断验证码是否为空
	def clean_verification_code(self):
		verification_code = self.cleaned_data.get('verification_code', '').strip()
		if verification_code == '':
			raise forms.ValidationError('验证码不能为空')

		# 判断验证码是否正确
		code = self.request.session.get('forgot_password_code', '')
		verification_code = self.cleaned_data.get('verification_code', '')
		if not (code != '' and code == verification_code):
			raise forms.ValidationError('验证码不正确')

		return self.cleaned_data

修改urls.py:
在这里插入图片描述
修改views.py:
在这里插入图片描述

def forgot_password(request):
	redirect_to = reverse('login')

	if request.method == 'POST':
		form = ForgotPasswordForm(request.POST, request=request) # 获取form表单
		if form.is_valid():	# 验证通过,重置密码
			email = form.cleaned_data['email']
			new_password = form.cleaned_data['new_password']
			user = User.objects.get(email=email)
			user.set_password(new_password)
			user.save()
			# 清除session
			del request.session['forgot_password_code']

			return redirect(redirect_to)
	else:
		form = ForgotPasswordForm()
	context = {}
	context['page_title'] = '重置密码'
	context['form_title'] = '重置密码'
	context['submit_text'] = '重置'
	context['form'] = form
	context['return_back_url'] = redirect_to
	return render(request, 'user/forgot_password.html', context)

重置密码的页面,新增user/templates/user/forgot_password.html(复制bind_email.html,稍作修改):
在这里插入图片描述

处理完之后,我们还缺一个入口,通常是通过登陆这个页面进去。修改login.html如下:
在这里插入图片描述
刷新页面,测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值