Django:从密码重置邮件中获取POST参数origin_page
解决Django密码重置邮件中获取origin_page参数的问题
我懂你现在的困扰:默认的Django密码重置视图不会把表单里的origin_page参数传递到邮件模板的上下文里,所以直接在password_reset_email.html里用request.POST.origin_page肯定拿不到值。咱们通过自定义密码重置视图就能搞定这个问题,具体步骤如下:
1. 自定义PasswordResetView,把origin_page传入邮件上下文
在你的accounts/views.py里创建一个继承自Django原生PasswordResetView的自定义视图,重写form_valid方法来捕获表单提交的origin_page,并把它添加到邮件的上下文变量中:
from django.contrib.auth.views import PasswordResetView class CustomPasswordResetView(PasswordResetView): template_name = 'accounts/password_reset_form.html' email_template_name = 'accounts/password_reset_email.html' subject_template_name = 'accounts/password_reset_subject.txt' success_url = 'done/' def form_valid(self, form): # 从POST请求里取出origin_page参数,默认值为空字符串 origin_page = self.request.POST.get('origin_page', '') # 将参数加入邮件上下文,这样模板就能直接调用 self.extra_email_context = {'origin_page': origin_page} return super().form_valid(form)
2. 更新urls.py,替换默认的密码重置视图
把原来urlpatterns里的auth_views.password_reset替换成咱们刚写的自定义视图:
from django.contrib.auth import views as auth_views from django.urls import path from . import views app_name = 'accounts' urlpatterns = [ path('login/', auth_views.login, {'template_name': 'accounts/login.html'}, name='login'), path('logout/', auth_views.logout, name='logout'), # 替换成自定义视图 path('password_reset/', views.CustomPasswordResetView.as_view(), name='password_reset'), path('password_reset/done/', auth_views.PasswordResetDoneView.as_view( template_name='accounts/password_reset_done.html'), name='password_reset_done'), path('reset/<uidb64>/<token>/', auth_views.password_reset_confirm, {'template_name': 'accounts/password_reset_confirm.html', 'post_reset_redirect': '/accounts/reset/done/'}, name='password_reset_confirm'), path('reset/done/', auth_views.PasswordResetCompleteView.as_view( template_name='accounts/password_reset_complete.html'), name='password_reset_complete') ]
3. 修改邮件模板,使用传递过来的origin_page变量
现在你可以在accounts/password_reset_email.html里直接用origin_page变量了,不用再依赖request.POST:
{% autoescape off %} To initiate the password reset process for your {{ user.get_username }} account, click the link below: {{ protocol }}://{{ domain }}{% url 'accounts:password_reset_confirm' uidb64=uid token=token %}?origin_page={{ origin_page }} ... Sincerely, The Team {% endautoescape %}
4. (可选)完成重置后自动跳转到origin_page
如果你希望用户完成密码重置后直接跳转到指定的origin_page,还可以继续自定义后续的视图:
第一步:自定义PasswordResetConfirmView,保存origin_page到会话
from django.contrib.auth.views import PasswordResetConfirmView class CustomPasswordResetConfirmView(PasswordResetConfirmView): template_name = 'accounts/password_reset_confirm.html' success_url = '/accounts/reset/done/' def dispatch(self, request, *args, **kwargs): # 从URL参数里取出origin_page,存入会话 origin_page = request.GET.get('origin_page', '/') request.session['origin_page'] = origin_page return super().dispatch(request, *args, **kwargs)
第二步:自定义PasswordResetCompleteView,读取会话并跳转
from django.contrib.auth.views import PasswordResetCompleteView from django.shortcuts import redirect class CustomPasswordResetCompleteView(PasswordResetCompleteView): template_name = 'accounts/password_reset_complete.html' def get(self, request, *args, **kwargs): # 从会话取出origin_page,完成后跳转,默认跳转到首页 origin_page = request.session.pop('origin_page', '/') return redirect(origin_page)
第三步:更新urls.py里对应的路径
urlpatterns = [ # ... 其他路由保持不变 path('reset/<uidb64>/<token>/', views.CustomPasswordResetConfirmView.as_view(), name='password_reset_confirm'), path('reset/done/', views.CustomPasswordResetCompleteView.as_view(), name='password_reset_complete'), ]
这样整个流程就闭环了:用户从带origin_page参数的密码重置页面进入,提交表单后参数被传递到邮件链接,点击链接后参数存入会话,完成重置后自动跳转到目标页面。
内容的提问来源于stack exchange,提问作者E-Kami
相关产品推荐
相关产品推荐

