需求
django-allauth本身就有重置密码的功能,我需要做的是根据用户的身份证号码和工号跳转到重置密码页面,重置密码完成后能够发送一篇邮件给用户提醒密码重置成功。
网上很多是关于邮箱验证的重置密码,但都不是我需要的,调试了两天allauth源代码,终于实现了重置密码后发送邮件的功能!
ps:我的项目时采用allauth的account来实现用户的第三方登陆的。
邮箱配置
settings.py:
EMAIL_USE_SSL = True
EMAIL_HOST = 'smtp.qq.com' # 如果是 163 改成 smtp.163.com
EMAIL_PORT = 465
EMAIL_HOST_USER = '邮箱' # 帐号
EMAIL_HOST_PASSWORD = '邮箱的验证码' # 密码
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
开启服务后在EMAIL_HOST_PASSWORD 填入验证码后才能用该账号给其他邮箱发送信息。
前端
改写这3个HTML的代码,注意:<font color="red">一定一定一定不要改动action里面的url代码!!!</font>当然,自己写视图的例外。
继承视图
先看看account里面的urls,py关于密码重置的url
根据url找到重置密码中用到的视图类,然后继承视图类,在各个函数里print一个标识数字,大概知道用到哪些函数,判断在哪里写发送邮件的代码。(不要忘记把url添加在自己的项目里面哦!)
最后我继承了PasswordResetView,PasswordResetFromKeyView这两个类
1 PasswordResetView
class CustomPasswordResetView(PasswordResetView):
def post(self, request, *args, **kwargs):
ID_number = request.POST['ID_number']
try:
user = User.objects.get(username=request.POST['username'])
true_profile = get_object_or_404(UserProfile, user=user)
user_profile = UserProfile.objects.get(ID_number=ID_number)
if true_profile == user_profile:
token_generator = kwargs.get("token_generator", default_token_generator)
temp_key = token_generator.make_token(user)
path = reverse("account_reset_password_from_key", kwargs=dict(uidb36=user_pk_to_url_str(user), key=temp_key))
return redirect(path)
except:
messages.add_message(request, messages.ERROR, '信息填写错误!')
return redirect('CustomPasswordResetView')
def get(self, request, *args, **kwargs):
return render(request, 'account/password_reset.html')
验证过程是通过身份证号码找到用户,再比对用户username与填写的username是否一致,一致时,即跳转到重置密码的页面。
token_generator = kwargs.get("token_generator", default_token_generator)
kwargs.get(),第一个参数是kwargs里的值,第二个参数是缺省值。(目前这一块还没很深入的了解清楚)获取令牌生成器。
temp_key = token_generator.make_token(user)
创建一个令牌
然后将令牌传递到PasswordResetFromKeyView类中。
这时已经能够成功修改密码了!但是还没有实现修改密码后发送信息提醒用户密码已经修改了。2 PasswordResetFromKeyView
通过逐个调试里面的函数,发现form_valid()这个函数是在修改完密码时执行的,所以将这个函数赋值过来覆盖原来的form_valid()函数。
class PasswordResetFromKeyViewNew(PasswordResetFromKeyView):
def form_valid(self, form):
form.save()
adapter = get_adapter(self.request)
if self.reset_user and app_settings.LOGIN_ATTEMPTS_LIMIT:
# User successfully reset the password, clear any
# possible cache entries for all email addresses.
for email in self.reset_user.emailaddress_set.all():
from_email = None
subject = '一滴账号重置密码通知'
text_content = '您好!您在一滴平台上重置了密码,若该操作若非本人操作,请立即联系技术部部门进行处理!.文本'
html_content = '<p>您好!您在一滴平台上重置了密码,若该操作若非本人操作,请立即联系技术部部门进行处理!.HTML</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [email])
msg.attach_alternative(html_content, "text/html")
msg.send()
adapter._delete_login_attempts_cached_email(
self.request, email=email.email
)
adapter.add_message(
self.request,
messages.SUCCESS,
"account/messages/password_changed.txt",
)
if app_settings.LOGIN_ON_PASSWORD_RESET:
return perform_login(
self.request,
self.reset_user,
email_verification=app_settings.EMAIL_VERIFICATION,
)
return super(PasswordResetFromKeyView, self).form_valid(form)
password_reset_from_key = PasswordResetFromKeyViewNew.as_view()
在删除电子邮件缓存之前将提醒邮件发送到用户邮箱当中。
https://code.ziqiangxuetang.com/django/django-send-email.html
补充知识
*args表示任何多个无名参数,它是一个tuple
**kwargs表示关键字参数,它是一个dict
总结
看源码改代码是非常头疼的,调试的时候要细心细心细心!!!用print比debug快的多!
还有很多没有很清楚,令牌这块还没有学透,等我解决了连接第三方应用登陆再来记录令牌的应用。