写点什么

【Django | allauth】重写 allauth 重置密码方法

  • 2022 年 8 月 30 日
    广东
  • 本文字数:2471 字

    阅读完需:约 8 分钟


🤵‍♂️ 个人主页: @计算机魔术师👨‍💻 作者简介:CSDN 内容合伙人,全栈领域优质创作者。


🌐 推荐一款找工作神器网站: 牛客网🎉🎉|笔试题库|面试经验|实习招聘内推 还没账户的小伙伴 速速点击链接跳转牛客网登录注册 开始刷爆题库,速速通关面试吧🙋‍♂️


该文章收录专栏---【Django | 项目开发】从入门到上线 专栏---

一、场景需求

在 allauth 中默认重置密码的方式是用户发送重置密码的请求后,发送重置密码的链接到用户的邮箱里面重置密码,如果使用 QQ 邮箱的 SMTP 服务,一天最多只能发送 50 封邮件,这样是明显不满足需求的,而如果为了实现此功能去部署一台邮件服务器或者申请一个企业邮箱,动辄几千一年的费用实在伤不起。所以在中小型的项目中,有一种折中的方法,即用户通过输入自己的身份证[这里已电话为例]即可重置对应的账号密码。

二、重写表单模型

  • form.py 添加表单模型 (处理手机号)


from django import forms
# 重写重置密码表单class ResetPasswordForm(forms.Form): """ 重置密码表单,需要手机号验证 """
tel = forms.CharField(max_length=20, required=True, label='Telephone')
# 获取电话号码 def clean_identity_tel(self): tel = self.cleaned_data['tel'] print(tel) """ 由于用get获取对象,如果获取不到会报错,所以这里使用filter 获取失败返回空对象列表 在UserProfile中筛选符合条件的用户,返回用户名 """ username = UserProfile.objects.filter(tel=tel) if not username: raise forms.ValidationError("手机号错误!!")
return self.cleaned_data['tel']
def save(self, request, **kwargs): return self.cleaned_data['tel']
复制代码

三、重写 view 视图函数类

allauth 中的重置密码的类视图位于 allauth.account.views.PasswordResetView,我们需要在 views.py 中继承这个类并且重写它的 post 方法。


  • view.py 视图函数


注意!!这里的default_token_generator函数是 allauth 中的form.py的函数,不是django.contib,auth.token的,不然会报 bad token 错误,因为生成token的方法是不一样的(还有邮箱等)


from allauth.account.forms import default_token_generator,SignupForm  # 注意!! token生成实在allauth里面,不是django自带得token生成器from allauth.account.utils import user_pk_to_url_strfrom allauth.account.views import PasswordResetViewfrom django.contrib.auth.decorators import login_requiredfrom django.contrib.auth.models import Userfrom django.http import HttpRequestfrom django.shortcuts import render, get_object_or_404, reverse, redirect, HttpResponseRedirect
from userprofile.forms import UseProfileForm, ResetPasswordFormfrom userprofile.models import UserProfile

# 重写重置密码表单class CustomPasswordResetView(PasswordResetView):
def post(self, request, *args, **kwargs): reset_password_form = ResetPasswordForm(request.POST) if reset_password_form.is_valid():
# 从电话筛选出 用户对象 tel = reset_password_form.clean_identity_tel() # UseProfile 中由于user相同属性的 username username = UserProfile.objects.get(tel=tel) user = User.objects.get(username=username) # 查看传参有无 令牌 token_generator = kwargs.get( "token_generator", default_token_generator) # 没有生成token 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), ) # 在根目录下建立绝对路径(self = request) url = HttpRequest.build_absolute_uri(request, path) # 重定向至修改密码链接 return redirect(url)
else: return render(request, 'account/telephone_error.html', {'content': "电话错误(表单格式错误)"})
# 注意 这里不能加上 login_required 的限制! 不然登录页面 忘记密码就会成功跳转页面!password_reset = CustomPasswordResetView.as_view()
复制代码


  • setting.py 添加配置(重写表单选项)


ACCOUNT_FORMS = ({    'reset_password': 'Userprofile.forms.ResetPasswordForm'})
复制代码

五、配置项目路由

注意!!!: 在 引入 扩展模型应用路由时 allauth 应用 和 userprofile 谁在上方一定要考虑好,不然路由覆盖等会出现页面失效或者报错的情况!!(一般默认 allauth 在上方),这里为了实现密码重置,要让 account/password/reset 不能走 allauth 的注册视图类,又不能修改 allauth 源码,此时我们使用继承并在 项目 路由修改 优先级,优先进去扩展应用模型的 重写密码类。


  • 项目 urls.py


from django.contrib import adminfrom django.urls import path, include
import userprofile.views
urlpatterns = [ path('admin/', admin.site.urls), path('', userprofile.views.profile), # 首页 则为信息页(当未登录 自动跳转到login页) # 注意路由最后 一个 / path('accounts/password/reset/', userprofile.views.password_reset, name='account_reset_password'), path('accounts/', include('allauth.urls')), path('accounts/', include('userprofile.urls'))]
复制代码


  • 效果:


参考文献:Django的objects.get和objects.filter方法详解和区别Python中的*(星号)和**(双星号)完全详解raise 报异常异常用法allauth 密码重置 *as_view()解析


✨谢谢你的阅读,你的点赞和收藏是我创作的最大动力✨
复制代码


用户头像

还未添加个人签名 2022.08.13 加入

还未添加个人简介

评论

发布
暂无评论
【Django | allauth】重写allauth重置密码方法_8月月更_计算机魔术师_InfoQ写作社区