【问题标题】:How to customize Django confirmation form and view in password request如何自定义 Django 确认表单并在密码请求中查看
【发布时间】:2019-10-06 02:30:33
【问题描述】:

我正在尝试使用我自己的模板而不是自定义 Django 管理 auth_view 在 Django 1.6 中实现重置密码,我主要遵循本教程;https://ruddra.com/posts/implementation-of-forgot-reset-password-feature-in-django/。我已经设法自定义重置密码页面和发送用于重置密码的电子邮件,但是当我尝试使用没有 Django 管理表单的 PasswordResetConfirm() 类时,发送重置链接的确认页面是空白的(有效) .简而言之,当单击重置密码的电子邮件链接时,网页是空白的,但顶部的标题是确认,因此代码中的某些内容被阻止或丢失。我尝试了许多教程,但没有任何效果。我已将 URL 中的 /rest/.. 更改为 account/reset,它与电子邮件中的链接匹配,现在可用于访问 PasswordResetConfirmView(),但它会呈现错误 'SetPasswordForm' object has no attribute 'set_cookie' ,如何在 Django 1.6 中解决这个问题?我还注意到我无法在 Django 1.6 中导入许多教程使用的 update_session_auth_hash,它似乎存在于 Django 1.7 及更高版本中。相反,我在本教程中尝试使用密码哈希 PBKDF2PasswordHasher、SHA1PasswordHasher; https://apimirror.com/django~1.9/topics/auth/passwords 但我不确定它是否与 SetPasswordForm 中关于 set_cookies 的属性错误有关。

我尝试在应用程序之后的设置中的 INSTALLED_APPS 中放置“django.contrib.admin”,这会将用于在确认步骤中更改密码的自定义 Django 管理表单“拔出”到空白页面,顶部有文本确认.我还更改了模板 password_reset_confirm.html

In views.py, following from linked tutorial

class PasswordResetConfirmView(FormView):
 template_name = "registration/password_reset_confirm.html"
 success_url = 'registration/password_reset_complete.html'
 form_class = SetPasswordForm


 def post(self, request, uidb64=None, token=None, *arg, **kwargs):
    """
    View that checks the hash in a password reset link and presents a
    form for entering a new password.
    """
    UserModel = get_user_model()
    form = self.form_class(request.POST)
    assert uidb64 is not None and token is not None  # checked by URLconf
    try:
        uid = urlsafe_base64_decode(uidb64)
        user = UserModel._default_manager.get(pk=uid)
    except (TypeError, ValueError, OverflowError,UserModel.DoesNotExist):
          user = None

    if user is not None and default_token_generator.check_token(user, 
    token):
        if form.is_valid():
            new_password= form.cleaned_data['new_password2']
            user.set_password(new_password)
            user.save()
            messages.success(request, 'Password has been reset.')
            return self.form_valid(form)
        else:

          messages.error(request, 'Password reset has not been   
          unsuccessful.')
          return self.form_invalid(form)
    else:
        messages.error(request,'The reset password link is no longevalid.')
        return self.form_invalid(form)```


In urls.py


url(r'^account/password_reset/', ResetPasswordRequestView.as_view(), 
name="reset_password"),
url(r'^account/password/reset/done/', ResetPasswordRequestView.as_view(), 
name="reset_password_done"),
url(r'^reset/(?P<uidb64>[0-9A-Za-z]+)/(?P<token>.+)/$', 
PasswordResetConfirmView.as_view(),name='password_reset_confirm'),

# changed url to
url(r'^account/reset/(?P<uidb64>[0-9A-Za-z]+)/(?P<token>.+)/$', 
PasswordResetConfirmView.as_view(),name='password_reset_confirm'),
# which matches email link
{{ protocol }}://{{ domain }}/account/reset/{{ uid }}/{{ token }}/ 

In password_reset_confirm.html in the Registration folder

{% extends 'base.html' %}



{% block title %}Enter new password{% endblock %}
{% block content %}
<h1>Set a new password!</h1>
<form method="POST">
 {% csrf_token %}
 {{ form.as_p }}
 <input type="submit" value="Change my password">
</form>
{% endblock %}

# in forms.py from tutorial, works in the tutorial example but yields 
 # an Attribute error that the form doesn't have set_cookies  
 # after disconnecting from Djando Admin confirmation forms used in the 
 #tutorial
class SetPasswordForm(forms.Form):

# """
#
#A form that lets a user change set their password without entering the old
# password
# """
error_messages = {
    'password_mismatch': ("The two password fields didn't match."),
    }
new_password1 = forms.CharField(label=("New password"),
                                widget=forms.PasswordInput)
new_password2 = forms.CharField(label=("New password confirmation"),
                                widget=forms.PasswordInput)

def clean_new_password2(self):
    password1 = self.cleaned_data.get('new_password1')
    password2 = self.cleaned_data.get('new_password2')
    if password1 and password2:
        if password1 != password2:
            raise forms.ValidationError(
                self.error_messages['password_mismatch'],
                code='password_mismatch',
                )
    return password2

【问题讨论】:

    标签: python django


    【解决方案1】:

    我已经设法解决了我的问题。如果有人遇到同样的问题,我做了以下;

    教程示例有效,但即使在模板 password_reset_confirm.py 中删除了所有与 Django 管理 (admin) 相关的标签后,管理视图仍显示(即使在运行 manage.py syncdb 并折腾并启动新的 sql-db 之后) ,所以我在 Registration 文件夹中使用了一个名为 test_reset_confirm.html 的新模板,其中包含原始 password_reset_confirm.py 中的表单相关代码部分(中间部分),并通过添加 enctype = multipart/form-data; 来填写表单信息; 和密码字段中的信息 在 views.py 中,我按照本教程中的示例 9 将 PasswordResetConfirmView 从类更改为函数; https://www.programcreek.com/python/example/54414/django.contrib.auth.forms.SetPasswordForm;

     def PasswordResetConfirmView(request, uidb64=None, token=None,
                           token_generator=default_token_generator,
                           post_reset_redirect=None,current_app=None):
        """
       View that checks the hash in a password reset link and presents a
       form for entering a new password.
    """
    UserModel = get_user_model()
    form = SetPasswordForm(request.POST)
    template_name='registration/test_reset_confirm.html'
    assert uidb64 is not None and token is not None  # checked by URLconf
    
    try:
        uid = urlsafe_base64_decode(uidb64)
        user = UserModel._default_manager.get(pk=uid)
    except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
        user = None
    
    if user is not None and token_generator.check_token(user, token):
        validlink = True
        if request.method == 'POST':
            form = SetPasswordForm(request.POST)
            if form.is_valid():
                print request.POST,'request.POST'
                print form.cleaned_data,'form.cleaned_data'
    
                new_password= form.cleaned_data['new_password2']
    
                user.set_password(new_password)
                user.save()
                #form.save()
                messages.add_message(request, messages.SUCCESS, 'Your password has now been    changed and you can login on any system site!',fail_silently=True)
    
                return HttpResponseRedirect(post_reset_redirect)
    
    
    else:
        form = SetPasswordForm()
    
    c = {"form":form}
    c.update(csrf(request))
    
    return TemplateResponse(request, template_name, c,
                            current_app=current_app)
    
    # Setpasswordform in forms.py
    
    class SetPasswordForm(forms.Form):
     new_password1 = forms.CharField(widget=forms.PasswordInput)
     new_password2 = forms.CharField(widget=forms.PasswordInput)
    
     error_messages = {
        'password_mismatch': ("The two password fields didn't match."),
        }
    
    
     class Meta:
         model = User
         fields = ('password',)
     def __init__(self,*args, **kwargs):
        super(SetPasswordForm, self).__init__(*args, **kwargs)
    
        def clean(self):
            cleaned_data = super(SetPasswordForm, self).clean()
    
            return cleaned_data
    

    【讨论】:

    • 使用此代码重置密码后。当我单击电子邮件中的密码重置链接时,它正在打开密码确认页面。有什么方法可以在重置后显示一次无效链接的消息。?
    猜你喜欢
    • 2020-01-11
    • 2023-02-13
    • 2017-03-13
    • 2021-07-16
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多