Using Django auth UserAdmin for User User Model

From the Django.Contrib.Auth docs :

Djangos default user extension If you are completely satisfied with the Djangos User model and just want to add additional profile information, you can simply subclass django.contrib.auth.models.AbstractUser and add your own profile fields. This class provides a complete default user implementation as an abstract model.

He said and did. I created a new model as shown below:

 class MyUser(AbstractUser): some_extra_data = models.CharField(max_length=100, blank=True) 

This appears in admins almost as a Django User standard. However, the most important difference between the administrator is that the set password- (re) field is absent, but a regular CharField is displayed instead. Do I need to override things in admin-config to make this work? If so, how can I do this in a somewhat dry way (i.e., without copying material from a Django source ... eww ...)?

+55
django django-models django-admin django-authentication django-custom-user
Feb 21
source share
4 answers

After digging around the Django source code, I found a working soul. I'm not quite happy with this solution, but it seems to work. Feel free to suggest the best solutions!




Django uses UserAdmin to visualize nice admin behavior for the User model. Just using this in our admin.py -file, we can get the same approach to our model.

 from django.contrib.auth.admin import UserAdmin admin.site.register(MyUser, UserAdmin) 

However, this in itself is probably not a good solution, since Django Admin will not display any of your custom fields. There are two reasons for this:

  • UserAdmin uses UserChangeForm as the form that will be used to modify the object, which in turn uses User as its model.
  • UserAdmin defines formsets -property, later used by UserChangeForm , which does not include your custom fields.

So, I created a special change form that overloads the Meta inner class so that the change form uses the correct model. I also had to overload UserAdmin to add my custom fields to the field set that is part of this solution. I don't like the beat as it looks a little ugly. Feel free to suggest improvements!

 from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import UserChangeForm class MyUserChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = MyUser class MyUserAdmin(UserAdmin): form = MyUserChangeForm fieldsets = UserAdmin.fieldsets + ( (None, {'fields': ('some_extra_data',)}), ) admin.site.register(MyUser, MyUserAdmin) 
+83
Feb 21 '13 at 22:55
source share

Nico's answer was extremely useful, but I found that Django still refers to the User model when creating a new user.

Ticket # 19353 refers to this problem.

To fix this, I had to make a few additions to admin.py

admin.py:

 from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import UserChangeForm, UserCreationForm from main.models import MyUser from django import forms class MyUserChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = MyUser class MyUserCreationForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = MyUser def clean_username(self): username = self.cleaned_data['username'] try: MyUser.objects.get(username=username) except MyUser.DoesNotExist: return username raise forms.ValidationError(self.error_messages['duplicate_username']) class MyUserAdmin(UserAdmin): form = MyUserChangeForm add_form = MyUserCreationForm fieldsets = UserAdmin.fieldsets + ( (None, {'fields': ('extra_field1', 'extra_field2',)}), ) admin.site.register(MyUser, MyUserAdmin) 
+43
Jul 05 '13 at 21:04 on
source share

A simpler solution:

 from django.contrib.auth.admin import UserAdmin from main.models import MyUser class MyUserAdmin(UserAdmin): model = MyUser fieldsets = UserAdmin.fieldsets + ( (None, {'fields': ('some_extra_data',)}), ) admin.site.register(MyUser, MyUserAdmin) 

Django will correctly reference the MyUser model for creation and modification. I am using Django 1.6.2.

+26
Apr 14 '14 at 15:08
source share

The cesc answer did not work for me when I tried to add a custom field to the creation form. Perhaps this has changed from 1.6.2? In any case, I found adding a field to both fields, and add_fieldsets did the trick.

 ADDITIONAL_USER_FIELDS = ( (None, {'fields': ('some_additional_field',)}), ) class MyUserAdmin(UserAdmin): model = MyUser add_fieldsets = UserAdmin.add_fieldsets + ADDITIONAL_USER_FIELDS fieldsets = UserAdmin.fieldsets + ADDITIONAL_USER_FIELDS admin.site.register(MyUser, MyUserAdmin) 
+1
Aug 15 '17 at 20:38 on
source share



All Articles