How do I inline edit a django user profile in the admin interface?
Asked Answered
S

4

23

If you want to store extra information about a user (django.contrib.auth.models.User) in Django you can use the nifty AUTH_PROFILE_MODULE to plug in a "profile" model. Each user then gets a profile. It's all described here:

Now, let's say I have created an application called accounts with a model called UserProfile and registered it as the profile model for my users. How do I inline the editing of the profile in the admin interface for editing users (or vice versa)?

Salomon answered 3/8, 2010 at 20:46 Comment(1)
Just a note for new readers, AUTH_PROFILE_MODULE was deprecated around 8 years ago: code.djangoproject.com/ticket/15937Aristarchus
S
18

Well, it turns out that this is quite easy, once you know how to do it. This is my myapp/accounts/admin.py:

from django.contrib import admin
from myapp.accounts.models import UserProfile
from django.contrib.auth.models import User

class UserProfileInline(admin.StackedInline):
    model = UserProfile
    max_num = 1
    can_delete = False

class AccountsUserAdmin(admin.UserAdmin):
    inlines = [UserProfileInline]

# unregister old user admin
admin.site.unregister(User)
# register new user admin that includes a UserProfile
admin.site.register(User, AccountsUserAdmin)

The default admin.UserAdmin ModelAdmin class for users is unregistered and a new one specifying an inline UserProfile is registered in its place. Just thought I should share.

Salomon answered 3/8, 2010 at 20:49 Comment(2)
How are you handling the password form link? Just these changes breaks it since it was only meant to be seen from the change form after a user with a name and password is added.Hexaemeron
The above is almost correct, the proper way which also does the 'password form link' is to extend the custom UserAdmin as opposed using admin.ModelAdmin - try: from django.contrib.auth.admin import UserAdmin then class UserProfileAdmin(UserAdmin):Verla
S
34

I propse a slightly improved version of André's solution as it breaks the list view in /admin/auth/user/:

from django.contrib import admin
from member.models import UserProfile
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin

class UserProfileInline(admin.StackedInline):
 model = UserProfile
 max_num = 1
 can_delete = False

class UserAdmin(AuthUserAdmin):
 inlines = [UserProfileInline]

# unregister old user admin
admin.site.unregister(User)
# register new user admin
admin.site.register(User, UserAdmin)
Saddletree answered 23/1, 2011 at 12:26 Comment(2)
Any ideas of how to move the UserProfileInline to the top :?Benefield
This feature has been requested multiple times, code.djangoproject.com/ticket/4848 is the oldest one. It's not yet implemented.Saddletree
S
18

Well, it turns out that this is quite easy, once you know how to do it. This is my myapp/accounts/admin.py:

from django.contrib import admin
from myapp.accounts.models import UserProfile
from django.contrib.auth.models import User

class UserProfileInline(admin.StackedInline):
    model = UserProfile
    max_num = 1
    can_delete = False

class AccountsUserAdmin(admin.UserAdmin):
    inlines = [UserProfileInline]

# unregister old user admin
admin.site.unregister(User)
# register new user admin that includes a UserProfile
admin.site.register(User, AccountsUserAdmin)

The default admin.UserAdmin ModelAdmin class for users is unregistered and a new one specifying an inline UserProfile is registered in its place. Just thought I should share.

Salomon answered 3/8, 2010 at 20:49 Comment(2)
How are you handling the password form link? Just these changes breaks it since it was only meant to be seen from the change form after a user with a name and password is added.Hexaemeron
The above is almost correct, the proper way which also does the 'password form link' is to extend the custom UserAdmin as opposed using admin.ModelAdmin - try: from django.contrib.auth.admin import UserAdmin then class UserProfileAdmin(UserAdmin):Verla
A
17

I propose another improvement to Robert's solution:

from django.contrib import admin
from member.models import UserProfile
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin

class UserProfileInline(admin.StackedInline):
   model = UserProfile
   max_num = 1
   can_delete = False

class UserAdmin(AuthUserAdmin):
   def add_view(self, *args, **kwargs):
      self.inlines = []
      return super(UserAdmin, self).add_view(*args, **kwargs)

   def change_view(self, *args, **kwargs):
      self.inlines = [UserProfileInline]
      return super(UserAdmin, self).change_view(*args, **kwargs)

# unregister old user admin
admin.site.unregister(User)
# register new user admin
admin.site.register(User, UserAdmin)

Without this change to UserAdmin, the custom UserProfileInline section will show up on the "add user" screen, which is just supposed to ask for the username and password. And if you change any of the profile data on that screen (away from the defaults) before you save, you'll get a "duplicate key" database error.

Adara answered 26/4, 2012 at 23:28 Comment(2)
Completely resolved my problem here: #20214862 Thank you! You'd think this User/UserProfile admin setup would be part of the django documentation.Azotic
Thanks a lot! Finally I get this to behave as it should hahaLaodicea
P
0

You have to consider the add and change form. OTherwise you will get a user cannot be None error when trying to create a user. The following has been tested and works in 1.3:

class TeamInline(admin.StackedInline):
  model = Team
  fk_name = 'user'
  max_num = 1
  can_delete = False

class TeamUserAdmin(UserAdmin):
  list_display = ('username', 'email', 'company', 'expertise', 'contact_email', 'contact_phone', 'twitter', 'facebook', 'last_login_short', 'options')
  list_select_related = True

  def add_view(self, *args, **kwargs):
    self.inline_instances = []
    return super(TeamUserAdmin, self).add_view(*args, **kwargs)

  def change_view(self, *args, **kwargs):
    self.inline_instances.append(TeamInline(self.model, self.admin_site))
    return super(TeamUserAdmin, self).change_view(*args, **kwargs)
Pollard answered 27/9, 2012 at 2:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.