Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#32692 closed Bug (invalid)

Django 3.2 automatic AppConfig discovery breaks projects working in 3.1.8

Reported by: Manel Clos Owned by: nobody
Component: contrib.admin Version: 3.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Manel Clos)

The described method of overriding the default admin site (https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#overriding-the-default-admin-site), is not compatible with automatic AppConfig discovery, if the app (myproject, or myapps) is already in INSTALLED_APPS.

Example:

  • pip install Django==3.2
  • django-admin startproject myproject
  • python manage.py migrate
  • python manage.py createsuperuser
  • Put a template in myproject/templates/admin/base_site.html
    {% extends 'admin/base_site.html' %}
    
    {% block branding %}
    Template test
    {% endblock %}
    
  • Add myproject to INSTALLED_APPS
    INSTALLED_APPS = [
        'myproject',
    
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    
  • python manage.py runserver works, I can access the admin site and see the changes in templates
  • Follow the guide to override the default admin site, https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#overriding-the-default-admin-site, this is, create myproject/admin.py, myproject/apps.py and modify settings.py.
    # myproject/admin.py
    from django.contrib import admin
    
    class MyAdminSite(admin.AdminSite):
        index_title = 'Test'
    
    
    # myproject/apps.py
    from django.contrib.admin.apps import AdminConfig
    
    class MyAdminConfig(AdminConfig):
        default_site = 'myproject.admin.MyAdminSite'
    
    
    # myproject/settings.py
    INSTALLED_APPS = [
        'myproject',
    
        'myproject.apps.MyAdminConfig',  # 'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    
  • python manage.py runserver

Actual result:
RuntimeError: 'myproject.apps' declares more than one default AppConfig: 'AdminConfig', 'MyAdminConfig'.`

Is this a regression?

  • pip install Django==3.1.8
  • python manage.py runserver
  • All ok, both templates and AdminConfig working at the same time

Workaroud

  • use app_admin.py instead of apps.py when following the documentation to override the default admin site
    # myproject/apps_admin.py
    from django.contrib.admin.apps import AdminConfig
    
    class MyAdminConfig(AdminConfig):
        default_site = 'myproject.admin.MyAdminSite'
    
  • adjust settings.py: `'myproject.apps_admin.MyAdminConfig' in INSTALLED_APPS
    INSTALLED_APPS = [
        'myproject',
    
        'myproject.apps_admin.MyAdminConfig',  # 'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    
  • works with Django 3.2!

Change History (12)

comment:1 by Manel Clos, 3 years ago

Description: modified (diff)

comment:2 by Mariusz Felisiak, 3 years ago

Component: Core (Other)contrib.admin
Description: modified (diff)
Resolution: duplicate
Status: newclosed

IMO it's a duplicate of #30402. You should customize a default admin site inside a main project directory (like described in the documentation) not in an app.

Please feel-free to send a PR with docs adjustments if you think we should make it clearer.

comment:3 by Manel Clos, 3 years ago

Description: modified (diff)
Resolution: duplicate
Status: closednew

Hi, I reviewed #30402 and it is not the same bug. Also, the steps to reproduce show that the admin site is customised inside the main project as you suggest. Reopening.

comment:4 by Manel Clos, 3 years ago

Description: modified (diff)

Description updated with the example code that was overwritten in comment 2

comment:5 by Mariusz Felisiak, 3 years ago

Resolution: invalid
Status: newclosed

You shouldn't have myproject in the INSTALLED_APPS it's not an app. Please use one of support channels if you have further questions.

comment:6 by Manel Clos, 3 years ago

Ok, but take into account that this has worked on every Django version til 3.2, and there is no indication about what's wrong or deprecated, it just stops working because of the automatic AppConfig discovery. Now I've to create a different app just to put some *global* templates, sigh...

comment:7 by Manel Clos, 3 years ago

Hi Marius, just checked the documentation: https://docs.djangoproject.com/en/3.2/ref/applications/#projects-and-applications

The project package is often extended to include things like fixtures, CSS, and templates which aren’t tied to a particular application.

There’s no restriction that a project package can’t also be considered an application and have models, etc. (which would require adding it to INSTALLED_APPS).

I really think Django 3.2 is breaking this, but I can open a different ticket to fix the documentation if you prefer that.

in reply to:  6 comment:8 by Mariusz Felisiak, 3 years ago

Replying to Manel Clos:

Ok, but take into account that this has worked on every Django version til 3.2, and there is no indication about what's wrong or deprecated, it just stops working because of the automatic AppConfig discovery. Now I've to create a different app just to put some *global* templates, sigh...

Yes but it was only by chance, that kind of configuration wasn't officially supported.

Now I've to create a different app just to put some *global* templates, sigh...

You don't need to have an app for global templates.

comment:9 by Carlton Gibson, 3 years ago

Specifically Manel you can use the DIRS option to the TEMPLATES setting to configure project level directories, rather than (mis)using APP_DIRS, which loads the per-app templates, that you've been relying on up to now.

https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-TEMPLATES-DIRS

See also the Overriding Templates How-To, which provides more of a walk through of the configuration at the beginning. https://docs.djangoproject.com/en/3.2/howto/overriding-templates/

Last edited 3 years ago by Carlton Gibson (previous) (diff)

comment:10 by Manel Clos, 3 years ago

Hi Carlton, I agree, but I'd also need to modify STATICFILES_DIRS, and FIXTURES_DIRS, and maybe something else.

In the end it would be better to modify the AdminConfig documentation as Marius suggested, even when this was previously working correctly up to 3.2.

Based on the tested workaround in the description, what about this? https://github.com/manelclos/django/commit/c5da1ff59d6d53dc25cf503be9d59c1f825fb10a

comment:11 by Mariusz Felisiak, 3 years ago

Based on the tested workaround in the description, what about this? ​https://github.com/manelclos/django/commit/c5da1ff59d6d53dc25cf503be9d59c1f825fb10a

This change is not correct, you can still use apps.py unless you do this in the main project and you don't use your project as an app, because it will discover two configs. I think proposed change makes it even more confusing.

comment:12 by Manel Clos, 3 years ago

Ok, would you consider a patch to https://github.com/django/django/commit/e0519301238b43633bab64054772f9a62634a05f, basically removing the last paragraph?

There's no restriction that a project package can't also be considered an application and have models, etc. (which would require adding it to :setting:INSTALLED_APPS).

Otherwise I'd consider this settled :)

Note: See TracTickets for help on using tickets.
Back to Top