Anurag Rana
Anurag Rana

Reputation: 1466

How to add custom user model in admin panel?

I created a custom user model extending AbstractBaseUser class. code is below.

class UserModel(AbstractBaseUser):
    sys_id = models.AutoField(primary_key=True, blank=True)        
    name = models.CharField(max_length=127, null=False, blank=False)    
    email = models.EmailField(max_length=127, unique=True, null=False, blank=False)
    mobile = models.CharField(max_length=10, unique=True, null=False, blank=False)  
    user_type = models.PositiveSmallIntegerField(choices=user_type_choices, null=False, blank=True, help_text="Admin(1)/Institute(2)/Student(3)")  
    access_valid_start = models.DateTimeField(null=True, blank=True)
    access_valid_end = models.DateTimeField(null=True, blank=True)
    created_when = models.DateTimeField(null=True, blank=True )
    created_by = models.BigIntegerField(null=True, blank=True)
    last_updated_when = models.DateTimeField(null=True, blank=True)
    last_updated_by = models.BigIntegerField(null=True, blank=True)
    notes = models.CharField(max_length=2048, null=True, blank=True)
    is_active = models.BooleanField(default=True)
    # this field is required to login super user from admin panel
    is_staff = models.BooleanField(default=True)
    # this field is required to login super user from admin panel
    is_superuser = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = "email"
    # REQUIRED_FIELDS must contain all required fields on your User model, 
    # but should not contain the USERNAME_FIELD or password as these fields will always be prompted for.
    REQUIRED_FIELDS = ['name', 'mobile', 'user_type']

    class Meta:
        app_label = "accounts"
        db_table = "users"

    def __str__(self):
        return self.email

    def get_full_name(self):
        return self.name

    def get_short_name(self):
        return self.name

    # this methods are require to login super user from admin panel
    def has_perm(self, perm, obj=None):
        return self.is_superuser

    # this methods are require to login super user from admin panel
    def has_module_perms(self, app_label):
        return self.is_superuser

Now in my admin panel only 'groups' is available. I want my custom user mode i.e. UserModel to appear in admin panel so that I can add, edit and delete user from admin user interface.
I tried multiple codes from SO, simplest of them is below

from django.contrib.auth.admin import UserAdmin
from accounts.models import UserModel
from django.contrib import admin


class MyUserAdmin(UserAdmin):
    model = UserModel

    fieldsets = UserAdmin.fieldsets + (
            (None, {'fields': ('mobile',)}),
    )

admin.site.register(UserModel, MyUserAdmin)

now I am getting this errors ..
ERRORS:

<class 'accounts.admin.MyUserAdmin'>: (admin.E019) The value of 'filter_horizontal[0]' refers to 'groups', which is not an attribute of 'accounts.UserModel'.
<class 'accounts.admin.MyUserAdmin'>: (admin.E019) The value of 'filter_horizontal[1]' refers to 'user_permissions', which is not an attribute of 'accounts.UserModel'.
<class 'accounts.admin.MyUserAdmin'>: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not an attribute of 'accounts.UserModel'.
<class 'accounts.admin.MyUserAdmin'>: (admin.E108) The value of 'list_display[0]' refers to 'username', which is not a callable, an attribute of 'MyUserAdmin', or an attribute or method on 'accounts.UserModel'.
<class 'accounts.admin.MyUserAdmin'>: (admin.E108) The value of 'list_display[2]' refers to 'first_name', which is not a callable, an attribute of 'MyUserAdmin', or an attribute or method on 'accounts.UserModel'.
<class 'accounts.admin.MyUserAdmin'>: (admin.E108) The value of 'list_display[3]' refers to 'last_name', which is not a callable, an attribute of 'MyUserAdmin', or an attribute or method on 'accounts.UserModel'.
<class 'accounts.admin.MyUserAdmin'>: (admin.E116) The value of 'list_filter[3]' refers to 'groups', which does not refer to a Field.

Please let me know how can I add custom user model successfully to admin UI?

Upvotes: 5

Views: 7264

Answers (3)

Mitch
Mitch

Reputation: 1856

@Anurag Rana your custom UserAdminclass should look like this

from django.contrib.auth.admin import UserAdmin
from accounts.models import UserModel
from django.contrib import admin


class MyUserAdmin(UserAdmin):
    model = UserModel
    list_display = ()  # Contain only fields in your `custom-user-model`
    list_filter = ()  # Contain only fields in your `custom-user-model` intended for filtering. Do not include `groups`since you do not have it
    search_fields = ()  # Contain only fields in your `custom-user-model` intended for searching
    ordering = ()  # Contain only fields in your `custom-user-model` intended to ordering
    filter_horizontal = () # Leave it empty. You have neither `groups` or `user_permissions`
    fieldsets = UserAdmin.fieldsets + (
            (None, {'fields': ('mobile',)}),
    )

admin.site.register(UserModel, MyUserAdmin)

Upvotes: 7

Marcus Lind
Marcus Lind

Reputation: 11450

From the Django Documentation

If your custom user model extends django.contrib.auth.models.AbstractUser, you can use Django’s existing django.contrib.auth.admin.UserAdmin class. However, if your user model extends AbstractBaseUser, you’ll need to define a custom ModelAdmin class. It may be possible to subclass the default django.contrib.auth.admin.UserAdmin; however, you’ll need to override any of the definitions that refer to fields on django.contrib.auth.models.AbstractUser that aren’t on your custom user class.

So basically, if you create a new user model from the AbstractBaseUser instead of AbstractUser you need to create your own custom ModelAdmin class, alternatively if you inherit from UserAdmin (which is what you're currently doing) you need to override and handle any differences.

Upvotes: 14

iklinac
iklinac

Reputation: 15738

You are trying to use UserAdmin but you don't have fields which it refers to

  • groups
  • permissions
  • first name
  • last name
  • username

You should probably need to check UserAdmin class in depth and see what variables you should override

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')}),
)
add_fieldsets = (
    (None, {
        'classes': ('wide',),
        'fields': ('username', 'password1', 'password2'),
    }),
)
form = UserChangeForm
add_form = UserCreationForm
change_password_form = AdminPasswordChangeForm
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',)

Also errors can give you a hint of where something went wrong

Upvotes: 2

Related Questions