'Value of 'list_display[2]' refers to 'first_name', which is not a callable, an attribute of 'UserAdmin', or an attribute on 'authentication.User'
I am trying to add following code to admin.py to make sure that user's password created from django admin will be hashed.
from django.contrib import admin
from .models import *
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
class UserAdmin(DjangoUserAdmin):
pass
# Register your models here.
admin.site.register(User, UserAdmin)
But when i try i got following:
<class 'authentication.admin.UserAdmin'>: (admin.E108) The value of 'list_display[2]' refers to 'first_name', which is not a callable, an attribute of 'UserAdmin', or an attribute or method on 'authentication.User'.
The User model looks like this
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = models.CharField(max_length=255, unique=True, db_index=True)
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
balance = models.FloatField(default=0.0)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def __str__(self):
return self.email
def tokens(self):
"""" Метод получения токена """
refresh = RefreshToken.for_user(self)
return {
'refresh': str(refresh),
'access': str(refresh.access_token)
}
def has_delete_permission(self, *args, **kwargs):
return True if self.is_staff is True else False
Solution 1:[1]
You make use of the UserAdmin, but in the UserAdmin [GitHub], this works with fields like first_name, last_name, etc. that are not defined on your custom User model.
@admin.register(User) class UserAdmin(admin.ModelAdmin): # … fieldsets = ( (None, {'fields': ('username', 'password')}), (_('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')}), ) # … list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups') search_fields = ('username', 'first_name', 'last_name', 'email') ordering = ('username',) filter_horizontal = ('groups', 'user_permissions',) # …
You will thus have to rewrite the fieldsets, list_display, and search_fields such that these no longer mention the first_name and last_name fields. You can of course also alter you User model to include these fields, but right now there is simply a mismatch between the UserAdmin and your User model.
Furthermore as, @AbdulAzizBarkat says, this model admin also has a form and add_form, which will include these fields as well.
Solution 2:[2]
I came up with following code of admin.py
from django.contrib import admin
from .models import *
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.forms import ModelForm
class UserCreationForm(ModelForm):
class Meta:
model = User
fields = ('email',)
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["password"])
if commit:
user.save()
return user
class UserAdmin(DjangoUserAdmin):
# The forms to add and change user instances
add_form = UserCreationForm
list_display = ("email",)
ordering = ("email",)
fieldsets = (
(
None, {
'fields': (
'email',
'password',
'first_name',
'last_name',
'balance',
'is_verified',
'is_active',
'is_staff'
)
}
),
)
add_fieldsets = (
(
None, {
'classes': ('wide',),
'fields': (
'email',
'password',
'first_name',
'last_name',
'is_superuser',
'is_staff',
'is_active',
'is_verified'
)
}
),
)
filter_horizontal = ()
# Register your models here.
admin.site.register(User, UserAdmin)
Solution 3:[3]
Though the question is old, I am answering the question so that it will help others. In the user model that extends the AbstractBaseUser, a method should be added with the name of the field to display in the class that extends admin.ModelAdminadmin as:
@admin.display(ordering='user__first_name')
def first_name(self):
return self.user.first_name
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Alex Nikitin |
| Solution 3 | Bashir M. Saad |
