如何在Django 1.9中实现密码更改表单

时间:2016-02-07 17:41:18

标签: python django django-users

我的python项目的url在这里: https://github.com/abylikhsanov/social

我正在尝试实施密码更改表单,因此用户可以更改其密码。我该如何实现它?应用程序应跟踪以前的密码,不应允许用户使用以前使用的密码。另外,我想实现重置密码功能。

7 个答案:

答案 0 :(得分:4)

为什么不使用django的内置PasswordChangeForm(django.contrib.auth.forms)。

如果你喜欢它的工作方式,只需使用它,或者你可以创建一个继承PasswordChangeForm的新的

    class PasswordChangeCustomForm(PasswordChangeForm):
        error_css_class = 'has-error'
        error_messages = {'password_incorrect':
                  "Το παλιό συνθηματικό δεν είναι σωστό. Προσπαθείστε   ξανά."}
        old_password = CharField(required=True, label='Συνθηματικό',
                      widget=PasswordInput(attrs={
                        'class': 'form-control'}),
                      error_messages={
                        'required': 'Το συνθηματικό δε μπορεί να είναι κενό'})

        new_password1 = CharField(required=True, label='Συνθηματικό',
                      widget=PasswordInput(attrs={
                        'class': 'form-control'}),
                      error_messages={
                        'required': 'Το συνθηματικό δε μπορεί να είναι κενό'})
        new_password2 = CharField(required=True, label='Συνθηματικό (Επαναλάβατε)',
                      widget=PasswordInput(attrs={
                        'class': 'form-control'}),
                      error_messages={
                        'required': 'Το συνθηματικό δε μπορεί να είναι κενό'})

稍后我将提供一个清理和保存方法的例子

有关详细信息,请参阅here

答案 1 :(得分:2)

您可以看到以下文档的更改密码部分。 How to change password in Django。 它的工作原理如下:

  1. 导航到manage.py文件所在的项目

  2. $ python manage.py shell

  3. 执行以下操作:

    from django.contrib.auth.models import User
    u = User.objects.get(username__exact='john')
    u.set_password('new password')
    u.save()
    
  4. 您必须制作一个表单集,然后在提交表单时执行此操作。

    您还可以使用简单的manage.py命令:

    manage.py changepassword *username*

    只需输入两次新密码即可。

    对于问题的第二部分(用户无法选择旧密码),您可以创建一个表,用于存储用户的旧密码。当用户输入新密码时,您可以在该表中检查是否可以选择。 Django有一个函数check_password,用于比较两个密码。

答案 2 :(得分:2)

由于您使用自定义用户模型,实现该功能的一个好方法是创建一个新表单ChangePassword

class ChangePassword(forms.Form):
      old_password=forms.PasswordField()
      new_password=forms.PasswordField()
      reenter_password=forms.PasswordField()
      def clean(self):
          new_password=self.cleaned_data.get('new_password')
          reenter_password=self.cleaned_data.get('reenter_password')
          #similarly old_password
         if new_password and new_password!=reenter_password or new_password==old_password:
                #raise error
         #get the user object and check from old_password list if any one matches with the new password raise error(read whole answer you would know) 
         return self.cleaned_data #don't forget this.

您可以定义clean()以检查两个密码是否匹配,并且输入的新密码与旧密码不同。

如果您不希望用户使用他们在选项之前使用的密码

  1. 创建一个新字段(如果要将这些密码存储为纯字符串)
  2. 创建包含哈希先前密码的模型(为了更好的安全性)。
  3. 根据您的型号,您不加密密码,因此选项1对您有好处。如果你想加密你可以为它选择sha256,库是passlib;只是搜索谷歌。

    要实现选项1,只需在模型中添加一个字段,每当更改密码时,将旧密码附加到此字段内容。您可以使用CharField,但其最大长度仅为255,而您可以选择textfield,对于您的模型,它将是:

    class Members(models.Model):
           #rest fields..
           old_passwords=models.TextField(blank=True,default='')
    

    现在,在保存ChangePassword时,请使用已清理的数据更新成员密码:

    def change_password(request):
             if request.method=='POST':
                form=ChangePassword(request.POST)
                if form.is_valid():
                      new_pass=form.cleaned_data['new_password']
                      #get the current user object as user
                      if user.old_password=='':
                             #it's first time user is changing password
                             #populate our Members old_password_field
                             user.old_password=user.password
                      else:         
                             user.old_password=user.old_password+','+user.password
                      user.password=new_password 
                      user.save()
                      #do whatever you want to do man..
    

    代码只是为了帮助您了解您需要做什么,您必须以自己的方式做事!

答案 3 :(得分:2)

如果容易的话,

from django.contrib.auth.forms import PasswordChangeForm


然后

class MyChangeFormPassword(PasswordChangeForm):
    pass

您认为

def get(self, request):
    instance_user = get_object_or_404(User, id=int(user_id))
    form_edit_password = MyChangeFormPassword(instance_user)
    context={'form_edit_password': form_edit_password}

    return render(request, self.template_name, context)

在您的模板上

<div class="col-lg-4">
   {{form_edit_password.old_password}}
</div>
<div class="col-lg-4">
   {{form_edit_password.new_password1}}
</div>
<div class="col-lg-4">
  {{form_edit_password.new_password2}}
</div>

您的帖子

form_edit_password = ChangePasswordForm(user, data=put)
if form_edit_password.is_valid():
    form_edit_password.save()
    return self.__succes_response(_('Password updated'))
else:
    return self.__error_response([form_edit_password])

Django会为您做所有事情,不是吗?您可以在MyChangeFormPassword上编写自己的规则,以覆盖父方法,但这是一个很好的方法,

我正在为Django 3编写此代码。

答案 4 :(得分:0)

如果你看看https://github.com/django/django/blob/master/django/contrib/auth/views.py 您会注意到

password_reset
采用名为
template_name的命名参数

def password_reset(request, is_admin_site=False, 
        template_name='registration/password_reset_form.html',
        email_template_name='registration/password_reset_email.html',
        password_reset_form=PasswordResetForm, 
        token_generator=default_token_generator,
        post_reset_redirect=None):

因此与urls.py一样......

from django.conf.urls.defaults import *
from django.contrib.auth.views import password_reset
urlpatterns = patterns('',
 (r'^/accounts/password/reset/$', password_reset, {'template_name': 'my_templates/password_reset.html'}),
 ...

django.contrib.auth.views.password_reset 将针对与&#39; / accounts / password / reset&#39; 匹配的网址与关键字参数< strong> template_name =&#39; my_templates / password_reset.html&#39;。

我强烈建议您浏览以下链接 http://garmoncheg.blogspot.com.au/2012/07/django-resetting-passwords-with.html

答案 5 :(得分:0)

在urls.py

path('password-reset/', views.ChangePassword.as_view(), name='password-reset'),

密码更改表格:

class MyPasswordChangeForm(PasswordChangeForm):
    def __init__(self, user, *args, **kwargs):
        self.user = user
        super().__init__(user, *args, **kwargs)
        self.fields['old_password'].widget.attrs.update({'class': 'form-control', 'placeholder': "Old Password"})
        self.fields['new_password1'].widget.attrs.update({'class': 'form-control', 'placeholder': "New Password"})
        self.fields['new_password2'].widget.attrs.update({'class': 'form-control', 'placeholder': "New Password"})

    def save(self, commit=True):
        password = self.cleaned_data["new_password1"]
        self.user.set_password(password)
        if commit:
            self.user.save()
        return self.user

在views.py中:

from django.views.generic import TemplateView
from django.contrib.auth.mixins import LoginRequiredMixin

class ChangePassword(LoginRequiredMixin,TemplateView):

    def get(self, request, *args, **kwargs):
        form_class = MyPasswordChangeForm
        form = self.form_class(self.request.user)
        return render(request, 'password.html',{'form': form,})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # Important!
            return render(request, 'password.html', {'form': form, 'password_changed': True})
        else:
            return render(request, 'password.html', {'form': form, 'password_changed': False})

在password.html中:

    <div id='PasswordChnageForm'>
        <form method="post" action="{% url 'password-reset' %}">
        {% csrf_token %}
            {% for field in form %}
                    {{ field }}
                    {% if field.help_text %}
                        <small style="display: none">{{ field.help_text }}</small>
                    {% endif %}
                    {% for error in field.errors %}
                        <p style="color: red">{{ error }}</p>
                    {% endfor %}
    
            {% endfor %}
                <input type="submit" name="save" value="Save" >
         </form>
    </div>
    <script src="{% static 'web_admin/js/jquery-3.4.1.min.js' %}"></script>
    <script>
        $("#CallPasswordChangeButton").on('click', function (e) {
            e.preventDefault(); // avoid to execute the actual submit of the form.
            var form = $('#PasswordChnageForm');
            $.ajax({
                type: 'Post',
                url: "{% url 'password-reset' %}",
                data: form.serialize(),
                success: function (data) {
                    $('#password_change').empty().html(data);
                }
            });
        });
    </script>

答案 6 :(得分:0)

实际上你可以使用 Django 表单,它们有一个名为“PasswordChangeForm”的内置表单,你可以从“django.contrib.auth.forms”中导入它

但对我来说,我总是喜欢用静态的 html 表单来做每件事,并通过我的手一步一步地构建我的 views.py 函数。

这是我的例子:

html 表单:

<div class="col-md-6">

    <form method="POST">
        {% csrf_token %}

    <div class="form-group">
        <label for="exampleInputPassword1">Old Password</label>
        <input type="password" name="q_Old_Password" class="form-control" id="exampleInputPassword1" placeholder="Password">
    </div>


    <div class="form-group">
        <label for="NewPassword">New Password</label>
        <input type="password" name="q_new_Password" class="form-control" id="NewPassword" placeholder="Password">
    </div>


    <div class="form-group">
        <label for="ConfirmNewPassword">Confirm New Password</label>
        <input type="password" name="q_confirm_new_Password" class="form-control" id="ConfirmNewPassword" placeholder="Password">
    </div>

    <button type="submit" class="btn btn-primary">Submit</button>
    </form>
</div>

这里是 views.py 函数:

from django.contrib.auth.models import User
from django.contrib.auth import update_session_auth_hash

def change_password(request):

    if request.method == 'POST':
        old_password = request.POST.get("q_Old_Password")
        new_password = request.POST.get("q_new_Password")
        confirmed_new_password = request.POST.get("q_confirm_new_Password")

        if old_password and new_password and confirmed_new_password:
            if request.user.is_authenticated:
                user = User.objects.get(username= request.user.username)
                if not user.check_password(old_password):
                    messages.warning(request, "your old password is not correct!")
                else:
                    if new_password != confirmed_new_password:
                        messages.warning(request, "your new password not match the confirm password !")
                    
                    elif len(new_password) < 8 or new_password.lower() == new_password or \
                         new_password.upper() == new_password or new_password.isalnum() or \
                         not any(i.isdigit() for i in new_password):
                        messages.warning(request, "your password is too weak!")

                    

                    else:
                        user.set_password(new_password)
                        user.save()
                        update_session_auth_hash(request, user)

                        messages.success(request, "your password has been changed successfuly.!")

                        return redirect('dashboard_namespace:home')

        else:
            messages.warning(request, " sorry , all fields are required !")
 


    context = {

    }
    return render(request, "pages/users_accounts/change_password.html", context)

我希望这有帮助。