Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Django auth UserAdmin for a custom user model

From the Django.Contrib.Auth docs:

Extending Django’s default User If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you can simply subclass django.contrib.auth.models.AbstractUser and add your custom profile fields. This class provides the full implementation of the default User as an abstract model.

Said and done. I created a new model like below:

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

This shows up in admin almost like Django's standard User. However, the most important difference in admin is that the password-(re)set field is not present, but a normal CharField is displayed instead. Do I really have to override stuff in the admin-config to get this to work? If so, how can I do that in somewhat DRY way (i.e. without copying stuff from the Django source... eww...)?

like image 317
nip3o Avatar asked Feb 21 '13 21:02

nip3o


People also ask

Should you create a custom user model in Django?

It's highly recommended to set up a custom User model when starting a new Django project. Without it, you will need to create another model (like UserProfile ) and link it to the Django User model with a OneToOneField if you want to add new fields to the User model.

What is UserAdmin in Django?

Django uses UserAdmin to render the nice admin look for User model. By just using this in our admin.py -file, we can get the same look for our model. from django.contrib.auth.admin import UserAdmin admin.site.register(MyUser, UserAdmin)


2 Answers

After digging around the Django source code for a while, I found a working soultion. I am not totally happy with this solution, but it seems to work. Feel free to suggest better solutions!


Django uses UserAdmin to render the nice admin look for User model. By just using this in our admin.py-file, we can get the same look for our model.

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

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

  • UserAdmin uses UserChangeForm as the form to be used when modifying the object, which in its turn uses User as its model.
  • UserAdmin defines a formsets-property, later used by UserChangeForm, which does not include your special fields.

So, I created a special change-form which overloads the Meta inner-class so that the change form uses the correct model. I also had to overload UserAdmin to add my special fields to the fieldset, which is the part of this solution I dislike a bit, since it looks a bit 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) 
like image 190
nip3o Avatar answered Sep 22 '22 00:09

nip3o


A simpler solution, admin.py:

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 MyUser model for creation and modification. I'm using Django 1.6.2.

like image 24
cesc Avatar answered Sep 25 '22 00:09

cesc