[Django]-Password field is visible and not encrypted in Django admin site

2👍

✅

You are not able to see the password in hashed state because the password field is a CharField which renders it as normal text field. In Django’s admin side there’s a field called ReadOnlyPasswordHashField in django.contrib.auth.forms which renders the password field to be in hashed state with password change link.

Django’s UserAdmin uses different form classes for user creation and updation.

    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm

To edit user details UserAdmin uses form = UserChangeForm(source code) where the password field is set as ReadOnlyPasswordHashField(source code).

class UserChangeForm(forms.ModelForm):
    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="{}">this form</a>.'
        ),
    )

So, Just by inheriting from UserAdmin from django.contrib.auth.admin would make the password to be in hashed state with all the other essentials as seen in default admin site for users.

OR

you could simply import UserChangeForm from django.contrib.auth.forms and set form = UserChangeForm in custom UserAdmin

from django.contrib.auth.forms import UserChangeForm,AdminPasswordChangeForm

# code

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    # code
    form = UserChangeForm
    change_password_form = AdminPasswordChangeForm
    # code

6👍

It’s likely that the Django Admin look problem has to do with inheritance. More precisely, change the class to inherit from UserAdmin.

from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin

class UserAdmin(DefaultUserAdmin):

Doing this will make it look closer to the default Django project.


The problem of the password not being encrypted is likely because it’s not encrypted in the database. OP has this question and that’s not a problem of the Django Admin.


Notes:

  • I also use AbstractUser when wanting to remove username.

  • Since this current question doesn’t have enough info to answer the problem of the pwd being hashed, I’ll leave that to OP’s other question.

1👍

Django Documentation clearly explains how to do this by Customizing authentication in Django

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError

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 ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().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
    disabled password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = MyUser
        fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')


class UserAdmin(BaseUserAdmin):
    # 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',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    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, UserAdmin)

0👍

One way is to define a custom fieldset for the UserAdmin in admin.py.

fieldsets = (
    (None, {"fields": ("username")}),
    (_("Personal info"), {"fields": ("first_name", "last_name", "email")}),
    (
        _("Permissions"),
        {
            "fields": (
                "is_active",
                "is_staff",
                "is_superuser",
                "groups",
                "user_permissions",
            ),
        },
    ),
    (_("Important dates"), {"fields": ("last_login", "date_joined")}),
)

-1👍

For context, I’m using Django 4.2.4 and python 3.10.12

Well, here was what I did:

class CustomUserAdmin(UserAdmin):
# Customize the display of fields for the user model
list_display = ('username', 'email', 'is_staff', 'is_active')

Then:

admin.site.register(MyUser, CustomUserAdmin)

This will make sure that every time you create a user in the admin page, you’ll be forced to write the username and the password (and it’s confirmation) before you add other details like shown below.

Create User Django admin

Leave a comment