Changing password in Django Admin
Solution 1
Put this in your UserChangeForm:
password = ReadOnlyPasswordHashField(label=("Password"),
help_text=("Raw passwords are not stored, so there is no way to see "
"this user's password, but you can change the password "
"using <a href=\"../password/\">this form</a>."))
Solution 2
password = ReadOnlyPasswordHashField(label= ("Password"),
help_text= ("Raw passwords are not stored, so there is no way to see "
"this user's password, but you can change the password "
"using <a href=\"../password/\">this form</a>."))
There is change in the href, for previous versions of django you can use
<a href=\"/password/\">this form</a>
.
For django 1.9+
<a href=\"../password/\">this form</a>
Solution 3
I added this method to my UserAdmin
class:
def save_model(self, request, obj, form, change):
# Override this to set the password to the value in the field if it's
# changed.
if obj.pk:
orig_obj = models.User.objects.get(pk=obj.pk)
if obj.password != orig_obj.password:
obj.set_password(obj.password)
else:
obj.set_password(obj.password)
obj.save()
You can the show the password field normally, but admins will only see the hashed password. If they alter it, the new value is then hashed and save.
This adds a single query to each time you save a user via the admin. It should generally not be an issue, since most systems don't have admins intensively editing users.
Solution 4
You can also do like this, in this way you just have to write over the field password and once you will save it, it will create the hash for it :
class UserModelAdmin(admin.ModelAdmin):
"""
User for overriding the normal user admin panel, and add the extra fields added to the user
"""
def save_model(self, request, obj, form, change):
user_database = User.objects.get(pk=obj.pk)
# Check firs the case in which the password is not encoded, then check in the case that the password is encode
if not (check_password(form.data['password'], user_database.password) or user_database.password == form.data['password']):
obj.password = make_password(obj.password)
else:
obj.password = user_database.password
super().save_model(request, obj, form, change)
Thomas
Updated on October 23, 2021Comments
-
Thomas over 2 years
I recently created the admin.py based in the Django Project Document:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser
But I really missed the functionality that allow the administrator the possibility to change the users passwords. How is possible to add this functionality? I just copied and pasted the code the is in the link above.
from django import forms from django.contrib import admin from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import ReadOnlyPasswordHashField from customauth.models import MyUser class UserCreationForm(forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password.""" password1 = forms.CharField(label='Password', widget=forms.PasswordInput) password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) class Meta: model = MyUser fields = ('email', 'date_of_birth') def clean_password2(self): # Check that the two password entries match password1 = self.cleaned_data.get("password1") password2 = self.cleaned_data.get("password2") if password1 and password2 and password1 != password2: raise forms.ValidationError("Passwords don't match") return password2 def save(self, commit=True): # Save the provided password in hashed format user = super(UserCreationForm, self).save(commit=False) user.set_password(self.cleaned_data["password1"]) if commit: user.save() return user class UserChangeForm(forms.ModelForm): """A form for updating users. Includes all the fields on the user, but replaces the password field with admin's password hash display field. """ password = ReadOnlyPasswordHashField() class Meta: model = MyUser def clean_password(self): # Regardless of what the user provides, return the initial value. # This is done here, rather than on the field, because the # field does not have access to the initial value return self.initial["password"] class MyUserAdmin(UserAdmin): # The forms to add and change user instances form = UserChangeForm add_form = UserCreationForm # The fields to be used in displaying the User model. # These override the definitions on the base UserAdmin # that reference specific fields on auth.User. list_display = ('email', 'date_of_birth', 'is_admin') list_filter = ('is_admin',) fieldsets = ( (None, {'fields': ('email', 'password')}), ('Personal info', {'fields': ('date_of_birth',)}), ('Permissions', {'fields': ('is_admin',)}), ('Important dates', {'fields': ('last_login',)}), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'date_of_birth', 'password1', 'password2')} ), ) search_fields = ('email',) ordering = ('email',) filter_horizontal = () # Now register the new UserAdmin... admin.site.register(MyUser, MyUserAdmin) # ... and, since we're not using Django's builtin permissions, # unregister the Group model from admin. admin.site.unregister(Group)
[UPDATE - Added Information] I changed the following information but I still seeing just the password (crypted) in a read-only field. How is possible to add a link to change the password?
fieldsets = ( ('Permissions', {'fields': ('is_active', 'is_admin','password')}), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'password')} ), )