需求

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快的多!

还有很多没有很清楚,令牌这块还没有学透,等我解决了连接第三方应用登陆再来记录令牌的应用。

最后编辑:2022年03月20日 ©著作权归作者所有