0

I've added a plan field to my custom Account class, but cannot get it to show on the individual account page in the django admin. It shows correctly in table of all accounts in the list view (as denoted by list_display), but does not show on each individual account page.

Here's my Account model:

class Account(AbstractUser):
    PLANS = (
        ("free", "free"),
        ("pro", "pro")
    )

    plan = models.CharField(max_length=10, choices=PLANS, default="free")

    def __str__(self) -> str:
        return self.first_name

And my admin file:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from accounts.models import Account
from subscribers.models import Subscriber


class SubscriberInline(admin.TabularInline):
    model = Subscriber
    extra = 0


class AccountAdmin(UserAdmin):
    inlines = [SubscriberInline, ]
    list_display = ("first_name", "plan", "email")
    # fields = ("first_name", "plan", "email")


admin.site.register(Account, AccountAdmin)

Why does this happen?

Is the problem related to the custom Account class which inherits from the AbstractUser model? I thought to add fields to the AccountAdmin class, but that just returns the below error:

ERRORS:
<class 'accounts.admin.AccountAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.

The plan field also doesn't show in the admin panel when trying to create a new account (mind you, neither do most of the other fields as it only asks for the username, password1 and password2 fields, and the option to add new subscribers to the table, but other fields like first_name etc can be edited in the admin after creation).

Thanks

UPDATE: Adding user @bdbd's suggested changes seems to not make a difference to the admin area - am I adding this incorrectly? Here's my admin.py after adding @bdbd's changes:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from accounts.models import Account
from subscribers.models import Subscriber

from django.contrib.auth.forms import UserChangeForm
from django import forms

PLANS = (
        ("free", "free"),
        ("pro", "pro")
)


class MyAccountChangeForm(UserChangeForm):
    plan = forms.ChoiceField(choices=PLANS)


class SubscriberInline(admin.TabularInline):
    model = Subscriber
    extra = 0


class AccountAdmin(UserAdmin):
    form = MyAccountChangeForm
    inlines = [SubscriberInline, ]
    list_display = ("first_name", "plan", "email")

    # @todo: bug! plan field not showing in django admin on individual account pages


admin.site.register(Account, AccountAdmin)

UPDATE 2: Screenshots of admin area:

account list page correctly showing plan column

no plan on individual account page 1

no plan on individual account page 2

no plan on individual account page 3

no plan on individual account page 4

sytech
  • 29,298
  • 3
  • 45
  • 86
user8758206
  • 2,106
  • 4
  • 22
  • 45
  • You need to override the form based on `UserAdmin` and add your field – Brian Destura Jul 31 '21 at 13:02
  • 1
    Maybe consider not subclassing `UserAdmin`? There appears to be a conflict with how you're trying to use this. Instead, create your own `AccountAdmin` class that does not subclass from `UserAdmin`. Then register both `UserAdmin` and `AccountAdmin` separately. – sytech Aug 03 '21 at 04:41
  • @sytech thank you - that seems to have done the job! Extending from `admin.ModelAdmin` instead of `UserAdmin` and adding `list_display = ("first_name", "email", "date_joined", "username", 'password', 'plan')` seems to display all the fields (even those not in `list_display`) although in a jumbled form. I assume I can fix this by googling how the Django Admin customised display works. Thanks for solving this – user8758206 Aug 03 '21 at 19:38
  • Glad to hear @user8758206 -- I've provided this as an answer if you'd like to vote/accept it if it is useful or answers your question. – sytech Aug 03 '21 at 19:58
  • 1
    Just curious, aside from the weird things not working, what's wrong with using `UserAdmin`? @sytech – Brian Destura Aug 03 '21 at 23:53
  • 1
    @bdbd there's nothing that is necessarily wrong with subclassing `UserAdmin` alone, but the problem is there's a conflict between how `UserAdmin` defines its form/fieldsets and how OP is configuring their form/fields (you can't use `fieldsets` and `fields` together). Instead resolving this conflict, it's probably easier to just define a new Admin class. In most cases, I expect an admin to inherit from `admin.ModelAdmin` or an ABC Admin intended to be subclassed. In general, it would be wise to avoid subclassing a third-party admin class you don't control, as such conflicts can arise. – sytech Aug 06 '21 at 00:32

2 Answers2

2

You should not extend from UserAdmin. Instead, you should create your own model admin class which extends from admin.ModelAdmin.

Then you should register your model separately.

class AccountAdmin(admin.ModelAdmin):
    ...

admin.site.register(Account, AccountAdmin)

As necessary, you can customize AccountAdmin to get the effect you want. You can peek at the UserAdmin source code to see how it is customized, if you want your admin view to behave similarly.

sytech
  • 29,298
  • 3
  • 45
  • 86
1

You need to override the default form that is being used by UserAdmin and add your field like so:

from django.contrib.auth.forms import UserChangeForm
from django import forms


class MyAccountChangeForm(UserChangeForm):
    plan = forms.ChoiceField(choices=PLANS)

Then assign the form to your admin:

class AccountAdmin(UserAdmin):
    form = MyAccountChangeForm
Brian Destura
  • 11,487
  • 3
  • 18
  • 34
  • this solution is not working for me - I keep getting the error `TypeError: __init__() got an unexpected keyword argument 'choices'` for some reason, even after adding this to the class: `def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)` as suggested by this post: https://stackoverflow.com/questions/30274346/init-got-unexpected-keyword-argument-y – user8758206 Aug 01 '21 at 09:55
  • 1
    Updated. It should be `forms.ChoiceField` – Brian Destura Aug 01 '21 at 23:16
  • Still not working for me, but I appreciate your help. I've updated my question with my attempt at implementing your changes - have I implemented this correctly? – user8758206 Aug 02 '21 at 19:58
  • 1
    Yes it looks ok. Were you checking this on existing accounts or when adding new account? – Brian Destura Aug 02 '21 at 23:37
  • 1
    I just tried this and it works on my end. Can you show a screenshot of the form? – Brian Destura Aug 03 '21 at 04:40
  • Just uploaded some screenshots to my original description. I checked this on existing accounts, although all existing accounts do have a plan. Thanks for your help with this – user8758206 Aug 03 '21 at 19:23