Douglas Denhartog
Douglas Denhartog

Reputation: 2054

admin.py for project, not app

How can I specify a project level admin.py?

I asked this question some time ago and was just awarded the Tumbleweed award because of the lack of activity on the question! >_<

Project:

For example, admin.autodiscover() is typically put in the project level urls.py (yes, it will be automatically included in 1.7)

I would like to move this, and the following, into their own admin.py file:

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

UserAdmin.list_display = ('email', 'first_name', 'last_name', 'is_active')
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
admin.autodiscover()

I tried doing just that, making an admin.py file and adding the code into it. Didn't work.

I tried adding a project level folder called admin, added an __init__.py and threw admin.py into the admin folder. Didn't work

Further I tried adding this admin folder to INSTALLED_APPS in settings.py. No luck.

Upvotes: 7

Views: 1450

Answers (4)

minusf
minusf

Reputation: 1373

Sooner or later, a heavily customized admin class will most likely need a project wide admin.py, as it is the place to register all per-app admins that are not being auto-discovered anymore. The documentation mentions this, but there is no extensive example to illustrate it:

https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#customizing-the-adminsite-class

Note that you may not want autodiscovery of admin modules when using your own AdminSite instance since you will likely be importing all the per-app admin modules in your myproject.admin module. This means you need to put 'django.contrib.admin.apps.SimpleAdminConfig' instead of 'django.contrib.admin' in your INSTALLED_APPS setting.

There is a bit outdated but more or less valid example in the wiki as well for multiple admin sites:

https://code.djangoproject.com/wiki/NewformsAdminBranch

# project-level admin.py

from django.contrib import admin
from myproject.myapp.models import Book, Author
from myproject.anotherapp.models import Musician, Instrument

site1 = admin.AdminSite()
site1.register(Book)
site1.register(Author)

site2 = admin.AdminSite()
site2.register(Musician)
site2.register(Instrument)

Upvotes: 1

Patrick
Patrick

Reputation: 2247

I'm curious to see if this gets downvoted. It seems to work, but it feels wrong. ;-)

The question is how to override the UserAdmin settings.

  1. Put an admin.py in your project folder (alongside settings.py)
from django.contrib.auth import admin
from django.contrib.auth.admin import UserAdmin

UserAdmin.list_display = ('email', 'first_name', 'last_name',
                          'is_active', 'date_joined', 'last_login',
                          'is_staff')
UserAdmin.ordering = ['-date_joined']
  1. add your project to installed_apps (this seems wrong, but I don't know why)

And now you should see the new columns and sort order on /admin/auth/user/

This is working for me with Django 1.11. So far no issues that I can find. What say you StackOverflow?

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599620

All admin.autodiscover() is import all the admin files it finds. There is no point putting the line itself in an admin files.

To understand why it's not working, you need to realise how it works. What it does is import the admin.py files inside registered apps. A registered app is a package included in INSTALLED_APPS that has a models.py. That's worth repeating: an app isn't considered if it doesn't have a models.py - even a blank one will work, but without it the package isn't an app.

So if you create a blank models.py in your directory, ensure that that directory is in INSTALLED_APPS, and move admin.autodisover back to urls.py, everything will work.

Edit

I'm not exactly sure what you do want, and why. As I mentioned, autodiscover depends on apps; but as I also mentioned, all autodiscover does is import all the admin files. If you really don't want to follow best practices, all you need to do is import your admin file manually: you can do that in the same place that you normally call autodiscover from, ie in the main urls.py.

Upvotes: 1

Raydel Miranda
Raydel Miranda

Reputation: 14360

From the admin.autodiscover doc string:

Auto-discover INSTALLED_APPS admin.py modules and fail silently when not present. This forces an import on them to register any admin bits they may want.

And here is the complete function very well documented:

def autodiscover():
    """
    Auto-discover INSTALLED_APPS admin.py modules and fail silently when
    not present. This forces an import on them to register any admin bits they
    may want.
    """

    import copy
    from django.conf import settings
    from django.utils.importlib import import_module
    from django.utils.module_loading import module_has_submodule

    for app in settings.INSTALLED_APPS:
        mod = import_module(app)
        # Attempt to import the app's admin module.
        try:
            before_import_registry = copy.copy(site._registry)
            import_module('%s.admin' % app)
        except:
            # Reset the model registry to the state before the last import as
            # this import will have to reoccur on the next request and this
            # could raise NotRegistered and AlreadyRegistered exceptions
            # (see #8245).
            site._registry = before_import_registry

            # Decide whether to bubble up this error. If the app just
            # doesn't have an admin module, we can ignore the error
            # attempting to import it, otherwise we want it to bubble up.
            if module_has_submodule(mod, 'admin'):
                raise

So the only thing autodiscover does for you is look for some module called admin.py inside installed app directories, hence you can put your admin.py where you want just make sure you import it, this make the code in it (registration of models ect..) get executed.

IMPORTANT: I'm not sure the correct moment for importing your custom-path admin.py. But it's sure you have to import it after load all the related apps.

Upvotes: 1

Related Questions