Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Password field is visible and not encrypted in Django admin site

So to use email as username I override the build-in User model like this (inspired by Django source code)

models.py

class User(AbstractUser):
    username = None
    email = models.EmailField(unique=True)
    objects = UserManager()
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.email

admin.py

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {"fields": ("email", "password")}),
        (("Personal info"), {"fields": ("first_name", "last_name")}),
        (
            ("Permissions"),
            {
                "fields": (
                    "is_active",
                    "is_staff",
                    "is_superuser",
                    "groups",
                    "user_permissions",
                ),
            },
        ),
        (("Important dates"), {"fields": ("last_login", "date_joined")}),
    )
    add_fieldsets = (
        (
            None,
            {
                "classes": ("wide",),
                "fields": ("email", "password1", "password2"),
            },
        ),
    )
    list_display = ("email", "is_active", "is_staff", "is_superuser")
    list_filter = ("is_active", "is_staff", "is_superuser")
    search_fields = ("email",)
    ordering = ("email",)
    filter_horizontal = ("groups", "user_permissions",)

But this is how it looks like when I go to Admin site to change a user:

enter image description here

Password is visible and not hashed and no link to change password form.

Comparing to what it looks like on a default Django project:

enter image description here

Password is not visible and there's a link to change password form

So clearly I'm missing something but I can't figure out what it is.

like image 524
Omid Shojaee Avatar asked Jan 30 '26 04:01

Omid Shojaee


2 Answers

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.

like image 111
Gonçalo Peres Avatar answered Feb 01 '26 21:02

Gonçalo Peres


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

like image 30
Achuth Varghese Avatar answered Feb 01 '26 19:02

Achuth Varghese