pythondjangodjango-modelsdjango-admindjango-contrib

Add fields from another model to the admin site


My Profile model has a OneToOne relation with Django's built-in User model.

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    verified = models.BooleanField(default=False)

If I want to change user's password or properties like Active or Superuser I have to do it in one Change User page, and to edit verified property I have to go to another.

Is there any way to merge this:

enter image description here

And this:

enter image description here

Into one form so I can edit everything about a user in one page?

Edit 1:

As you guys suggested the StackedInline approach, let's see how it turns out.

Please first look at Django's default Admin site (first screenshot above):

  1. Everything is grouped in sections and sections have titles.
  2. Look at how the password information is displayed.
  3. There's a link to change the password.

Now I implement the StackedInline solution.

Please note that this is in the admin.py of my myapp:

from django.contrib import admin
from .models import Profile
from django.contrib.auth.models import User

# Register your models here.


class ProfileInline(admin.StackedInline):
    model = Profile

class UserAdmin(admin.ModelAdmin):
    inlines = (ProfileInline, )


admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Now let's look at Admin site:

enter image description here

  1. Everything is scattered. Sections and their titles are gone (Personal info, Permissions, etc).
  2. Password field shows the hashed password. All other information is gone.
  3. There's no link to change the password.

Edit 2:

To solve the problem of Edit 1 I look at the source code of Django (https://github.com/django/django/blob/main/django/contrib/auth/admin.py) and add update my code as below:

class UserAdmin(admin.ModelAdmin):
    inlines = (ProfileInline, )
    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"),
            },
        ),
    )

    filter_horizontal = (
        "groups",
        "user_permissions",
    )
    
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Now I have two sections in the Admin site:

The section on the top shows almost everything (except that the password field is still different and there's no link to change the password and also the verified field is not there) but sections and titles are back.

Then there's this additional and completely unnecessary part:

enter image description here enter image description here

As you can see:

  1. All fields of information about the user is repeated
  2. Look at the password field
  3. Information is not grouped in sections with titles
  4. verified filed appears.

Solution

  • OP can use one of the InlineModelAdmin objects such as StackedInline. This allows one to create inline forms providing one the ability to edit models on the same page as a parent model.

    Adapting for OP's case, it would be something like

    from django.contrib import admin
    
    class ProfileInline(admin.StackedInline):
        model = Profile
    
    class UserAdmin(admin.ModelAdmin):
        inlines = [
            ProfileInline,
        ]
    
    admin.site.register(User, UserAdmin)
    

    Now OP's admin site is set up to edit Profile objects inline from the User detail page.