8👍
why don’t you use django’s built-in PasswordChangeForm (django.contrib.auth.forms).
If you like the way it works just use this from, or you can create a new one that inherits 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': 'Το συνθηματικό δε μπορεί να είναι κενό'})
I will provide later an example of the clean and save methods
see here for more details
7👍
You can see the Change Password section of following documentation for this. How to change password in Django.
It works like this:
-
Navigation to your project where
manage.py
file lies -
$ python manage.py shell
-
Execute the following:
from django.contrib.auth.models import User u = User.objects.get(username__exact='john') u.set_password('new password') u.save()
You will have to make a formset and you will perform this action at submission of the form.
You can also use the simple manage.py
command:
manage.py changepassword *username*
Just enter the new password twice.
For second part of your question (User cannot choose old password), you can create a table in which you will store user’s old password. When user will enter new password, you can check this in that table whether he can choose it or not. Django has a function check_password which is used to compare two passwords.
- [Django]-Django: ValidationError using is_authenticated and logout when authenticating from an external source
- [Django]-Django – ManyToMany as hidden fields?
- [Django]-Django: need help with keeping apps from depending on one another
- [Django]-Django flush query caches
4👍
Easy peasy, if you
from django.contrib.auth.forms import PasswordChangeForm
Then
class MyChangeFormPassword(PasswordChangeForm):
pass
On your view
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)
On your template
<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>
And your post
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 will do everything for you, crazy isn’t? You could write your own rules on the MyChangeFormPassword overwriting the parent methods, but this is a great aproach,
I am writing this for Django 3.
3👍
Since you are using you custom user model a nice way to implement the functionality is to create a new form 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.
You can define clean()
to check that both passwords match or not, and also the new password entered is not same as the old password.
If you don’t want the user to use a password they have used before an option would be
- Create a new field (if you want to store these passwords as plain strings)
- Create a model containing hashed previous passwords (for better security).
According to your models you are not encrypting passwords so option 1 is good for you. In case you want to encrypt you can choose sha256 for it, library is passlib; just search google.
To implement option 1 just add a field to your model and whenever password is changed, append the old password to this field contents. You can either use a CharField
but its maximum length is only 255 instead you can choose textfield
, for your model it would be like:
class Members(models.Model):
#rest fields..
old_passwords=models.TextField(blank=True,default='')
Now when saving ChangePassword use the cleaned data to update the member password:
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..
The code is just to help you understand what you need to do, you have to do thing your own way!
- [Django]-Django 2 upgrade lost filter_horizontal functionality
- [Django]-Facebook Connect API error 191 with Django-socialregistration
- [Django]-Login and registration form on one page with Django
1👍
IN urls.py
path('password-reset/', views.ChangePassword.as_view(), name='password-reset'),
Password change form:
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
In 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})
In 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>
$("#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>
- [Django]-When does Django's custom model field method to_python get anything other than an instance?
0👍
actually you can use Django forms , they have built-in form called"PasswordChangeForm" and you can import it from "django.contrib.auth.forms"
but for me i always like to use a pure html form and build my views.py function step by step like the following example :
html form :
<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>
and here is views.py function :
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)
i hope this helpful.
- [Django]-Django with django-nose: two identical settings files with different behavior in running test command
- [Django]-How can I rename an uploaded file on Django before sending it to amazon s3 bucket?
- [Django]-Remove the decimal part of a floating-point number in django?
- [Django]-Django-Userena: adding extra non-null fields to a user's profile
- [Django]-Import parent module from submodule
-1👍
if you take a look at https://github.com/django/django/blob/master/django/contrib/auth/views.py
you will notice that
password_reset
takes a named parameter called
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):
thus with urls.py like…
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 will be called for URLs matching ‘/accounts/password/reset’ with the keyword argument template_name = ‘my_templates/password_reset.html’.
i strongly recommend you to go through the following link
http://garmoncheg.blogspot.com.au/2012/07/django-resetting-passwords-with.html
- [Django]-Named JSON array in Django REST Framework
- [Django]-Django 2 upgrade lost filter_horizontal functionality
- [Django]-Django OAuth Toolkit "resource-owner password based" grant type
- [Django]-Easiest way to write a Python program with access to Django database functionality