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:
Password is visible and not hashed and no link to change password form.
Comparing to what it looks like on a default Django project:
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.
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