Trouble overriding both contrib.admin.AdminSite and django.contrib.auth.admin.UserAdmin simultaneously

Using Django 3.1 and Python 3.6, I’m trying to both override the default AdminSite class, and the UserAdmin. I’m trying to combine the examples from two different sections of the documentation:

Overriding the default admin site

Extending the existing User model

Originally I had just the overriden AdminSite class, but then the problem arose when I tried to also override UserAdmin.

Both of these work independently. I can either override AdminSite and get a custom header, or UserAdmin and get my inline showing.

For whatever reason, I run into an import error: ImportError: Module "core.admin" does not define a "CoreCustomAdmin" attribute/class. It looks like a sort of circular dependency, but that’s just a guess, as I cannot figure out where/how it’s happening.

Stack trace:

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 20, in import_string
    return getattr(module, class_name)
AttributeError: module 'core.admin' has no attribute 'CoreCustomAdmin'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 44, in autodiscover_modules
    if register_to:
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/functional.py", line 240, in inner
    self._setup()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 540, in _setup
    AdminSiteClass = import_string(apps.get_app_config('admin').default_site)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 17, in import_string
    module = import_module(module_path)
  File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/infernous/project_name/src/core/admin.py", line 2, in <module>
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/auth/admin.py", line 26, in <module>
    class GroupAdmin(admin.ModelAdmin):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/decorators.py", line 21, in _model_admin_wrapper
    if not isinstance(admin_site, AdminSite):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/functional.py", line 240, in inner
    self._setup()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 540, in _setup
    AdminSiteClass = import_string(apps.get_app_config('admin').default_site)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 24, in import_string
    ) from err
ImportError: Module "core.admin" does not define a "CoreCustomAdmin" attribute/class

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 20, in import_string
    return getattr(module, class_name)
AttributeError: module 'core.admin' has no attribute 'CoreCustomAdmin'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 110, in inner_run
    autoreload.raise_last_exception()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/autoreload.py", line 76, in raise_last_exception
    raise _exception[1]
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 357, in execute
    autoreload.check_errors(django.setup)()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/apps/registry.py", line 122, in populate
    app_config.ready()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/apps.py", line 24, in ready
    self.module.autodiscover()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/__init__.py", line 24, in autodiscover
    autodiscover_modules('admin', register_to=site)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 53, in autodiscover_modules
    if register_to:
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/functional.py", line 240, in inner
    self._setup()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 540, in _setup
    AdminSiteClass = import_string(apps.get_app_config('admin').default_site)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 17, in import_string
    module = import_module(module_path)
  File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/infernous/project_name/src/core/admin.py", line 2, in <module>
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/auth/admin.py", line 26, in <module>
    class GroupAdmin(admin.ModelAdmin):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/decorators.py", line 21, in _model_admin_wrapper
    if not isinstance(admin_site, AdminSite):
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/functional.py", line 240, in inner
    self._setup()
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 540, in _setup
    AdminSiteClass = import_string(apps.get_app_config('admin').default_site)
  File "/home/infernous/project_name/.venv/lib/python3.6/site-packages/django/utils/module_loading.py", line 24, in import_string
    ) from err
ImportError: Module "core.admin" does not define a "CoreCustomAdmin" attribute/class

I do, in fact, have the default admin not loaded (that gives an error anyway).

settings.py:

INSTALLED_APPS = [
    ...
    'core.apps.CoreCustomAdmin',
    ...
    # 'django.contrib.admin', # Commented out

The problem file? Line 2 is the only line of my own code that’s found in the stack trace. Changing the ordering of the imports does nothing, which is expected since it is Python:

core/admin.py:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User, Group

from allauth.account.models import UserData

class CoreCustomAdmin(admin.AdminSite):
    site_header = 'Custom Header'

class UserDataInline(admin.StackedInline):
    model = UserData
    can_delete = False

class CustomUserAdmin(BaseUserAdmin):
    inlines = (UserDataInline,)

admin.site = CoreCustomAdmin()
admin.site.register(User, CustomUserAdmin)
admin.site.register(Group)

The only place where I import core.admin. I have tried change admin.site = CoreCustomAdmin() from core/admin.py to something like customadmin = CoreCustomAdmin() and using that, but it did nothing, naturally.

urls.py

from django.urls import path, include

from core.admin import admin

app_name = 'project_name'
urlpatterns = [
    ...
    path('admin/', admin.site.urls),
]

core/apps.py

from django.apps import AppConfig
from django.contrib.admin.apps import AdminConfig

class CoreConfig(AppConfig):
    name = 'core'

class CoreCustomAdmin(AdminConfig):
    default_site = 'core.admin.CoreCustomAdmin'

Thanks!

I accidentally fixed it after coming back to the problem 3 weeks later and spending 5 minutes on it. I changed the line in settings.py from

'core.apps.CoreCustomAdmin',

to

'base.apps.AdminConfig',

As far as I can tell, it’s achieved the desired effect. It still has both the custom header on the admin site, as well as the inline on the User model edit page. I’m not really sure exactly why this worked, but for the time being I’ll take it and run with it.