我试图通过使用View
类实现重置密码视图。实际上,我遇到了一个令人讨厌的错误。
我有三个实施意见:
UserResetPasswordView
在这里用户输入电子邮件并将请求发送到他/她的电子邮件UserResetPasswordRequestSentView
此处显示电子邮件已发送的消息UserResetPasswordConfirm
在上面的2个视图后,此视图让用户更改密码。
在将用户重定向到UserResetPasswordRequestSentView
后,将向用户的电子邮件发送一封电子邮件,以访问用户更改他/她的密码。
因此用户将被重定向到包含用于设置新密码输入的UserResetPasswordConfirm
。
以下是我的urls.py
脚本:
urlpatterns = [
path(
route='reset-password',
view=views.UserResetPasswordView.as_view(),
name='reset',
),
path(
route='reset-password-request-sent',
view=views.UserResetPasswordRequestSentView.as_view(),
name='reset_sent',
),
path(
route='reset-password-confirm/<uidb64>/<token>',
view=views.UserResetPasswordConfirm.as_view(),
name='reset_confirm',
),
]
这是UserResetPasswordView
视图:
class UserResetPasswordView(View):
def get(self, request: HttpRequest) -> HttpResponse:
reset_password_form: ResetPasswordForm = ResetPasswordForm()
return render(
request=request,
template_name='reset/reset.html',
context={
'reset_password_form': reset_password_form,
},
)
def post(self, request: HttpRequest) -> Union[HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponse]:
reset_password_form: ResetPasswordForm = ResetPasswordForm(request.POST or None)
if (reset_password_form.is_valid()):
cd = reset_password_form.cleaned_data
user = get_user_model().objects.filter(Q(email=cd['email'])).first()
if (user):
subject = 'درخواست بازنشانی رمز ورود'
message = render_to_string(
template_name='email/template_reset_password.html',
context={
'user': user,
'domain': get_current_site(request=request).domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
'protocol': 'https' if request.is_secure() else 'http',
}
)
send_mail(
subject,
message,
'settings.EMAIL_HOST_USER',
[cd['email']],
fail_silently=False
)
return redirect(to=reverse('reset_sent'))
else:
return redirect(to=reverse('reset'))
return render(
request=request,
template_name='reset/reset.html',
context={
'reset_password_form': reset_password_form,
},
)
这是用户可以设置新密码的表单(UserResetPasswordConfirm
):
class UserResetPasswordConfirm(View):
def get(self, request: HttpRequest, uidb64, token) -> HttpResponse:
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user_obj = User.objects.get(pk=uid)
except:
user_obj = None
if (user_obj is not None and account_activation_token.check_token(user_obj, token)):
form: ResetPasswordConfirmForm = ResetPasswordConfirmForm()
else:
messages.error(
request=request,
message='توکن شما منقضی شده است',
)
return render(
request=request,
template_name='reset/reset-confirm.html',
context={
'form': form,
},
)
def post(self, request: HttpRequest, uidb64, token) -> Union[HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponse]:
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user_obj = User.objects.get(pk=uid)
except:
user_obj = None
if (user_obj is not None and account_activation_token.check_token(user_obj, token)):
form: ResetPasswordConfirmForm = ResetPasswordConfirmForm(request.POST or None)
if (form.is_valid()):
cd = form.cleaned_data
if (cd['new_password'] != cd['con_new_password']):
form.add_error(
field='new_password',
error='رمز ورود شما با یکدیگر مطابقت ندارد',
)
else:
user_obj.set_password(raw_password=cd['new_password'])
user_obj.save()
return redirect(to=reverse('reset_complete'))
else:
form.add_error(
field='new_password',
error='رمز ورود شما با یکدیگر مطابقت ندارد',
)
return render(
request=request,
template_name='reset/reset-confirm.html',
context={
'form': form,
},
)
else:
messages.error(
request=request,
message='توکن شما منقضی شده است',
)
return render(
request=request,
template_name='reset/reset-confirm.html',
context={
'form': form,
},
)
这是form
,包含为用户设置新密码的输入:
{% extends "base.html" %}
{% load static %}
{% block title %}
<title>
تنظیم رمز ورود جدید
</title>
{% endblock %}
{% block body %}
<div class="container text-center mt-5">
<form class="form-inline" action="{% url 'reset_confirm' %}" method="post">
{% csrf_token %}
<div class="row">
<h6 class="text-info mt-2">رمز ورود جدید حداقل بین 8 تا 64 کاراکتر (ترکیب حروف و اعداد)</h6>
<div class="field">
<p class="control has-icons-left">
{{ form.new_password }}
<span class="icon is-small is-left">
<i style="color: #1F2330;" class="fas fa-lock"></i>
</span>
</p>
</div>
<h6 class="text-info mt-2">تایید مجدد رمز ورود جدید</h6>
<div class="field">
<p class="control has-icons-left">
{{ form.con_new_password }}
<span class="icon is-small is-left">
<i style="color: #1F2330;" class="fas fa-lock"></i>
</span>
</p>
</div>
</div>
<div class="row">
<div class="col">
<button style="width: 150px;" id="set_pass" type="submit" class="btn btn-info text-dark">ارسال درخواست</button>
</div>
</div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
jQuery(function($){
$(document).ajaxSend(function() {
$('spinner-border').fadeIn(580);
var loading_tag = '<div class="spinner-border"></div>  لطفا صبر کنید';
$('#set_pass').html(loading_tag);
});
$('#set_pass').click(function() {
$.ajax({
type: 'GET',
success: function(data) {
console.log(data);
}
}).done(function() {
setTimeout(function() {
$('.spinner-border').fadeOut(500);
}, 700);
});
});
});
</script>
{% endblock %}
在这里,用户应该打开通过电子邮件发送的链接,但每次我试图将用户重定向到UserResetPasswordConfirm
,django都会显示此错误:
如果你能帮助我,我将非常感激。
1条答案
按热度按时间jecbmhm31#
使用
uidb64
和token
渲染 *,因此:然后在视图中使用这些来确定URL:
注意:
redirect(…)
[Django-doc]通常会使用视图的名称和kwargs(可选),所以不要使用**reverse(…)
[Django-doc]。因此,您可能需要将redirect(redirect('reset_complete'))
重写为redirect('reset_complete')
。注意:直接子类化
View
类通常是 * 不 * 必要的。在这种情况下,你的视图看起来像一个FormView
**[Django-doc]。通过使用FormView
而不是简单的View
,您通常不必实现大量样板代码。