27

I want to modify a few tiny details of Django's built-in django.contrib.auth module. Specifically, I want a different form that makes username an email field (and email an alternate email address. (I'd rather not modify auth any more than necessary -- a simple form change seems to be all that's needed.)

When I use autodiscover with a customized ModelAdmin for auth I wind up conflicting with auth's own admin interface and get an "already registered" error.

It looks like I have to create my own admin site, enumerating all of my Models. It's only 18 classes, but it seems like a DRY problem -- every change requires both adding to the Model and adding to the customized admin site.

Or, should I write my own version of "autodiscover with exclusions" to essentially import all the admin modules except auth?

Fabian Steeg
  • 44,988
  • 7
  • 85
  • 112
S.Lott
  • 384,516
  • 81
  • 508
  • 779

2 Answers2

53

None of the above. Just use admin.site.unregister(). Here's how I recently added filtering Users on is_active in the admin (n.b. is_active filtering is now on the User model by default in Django core; still works here as an example), all DRY as can be:

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

class MyUserAdmin(UserAdmin):
    list_filter = UserAdmin.list_filter + ('is_active',)

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
Carl Meyer
  • 122,012
  • 20
  • 106
  • 116
  • 1
    Sweet -- totally missed the unregister method in `sites.AdminSite` – S.Lott Jan 23 '09 at 02:29
  • Interesting. Thanks for sharing, Carl. – ayaz Jan 23 '09 at 06:17
  • 3
    I note that, after adding this unregister() call to my code, I had to manually kill and re-start my development server before Django "saw" the change I had made. Which made me waste 15 minutes trying to figure out why unregister() wasn't working. Which finally brought me to this Stack Overflow question, where I discovered that what I was doing *was* supposed to work. :-) – Brandon Rhodes Aug 24 '09 at 02:19
  • 1
    @Brandon Yeah, in general Django's admin.py autodiscovery does not play well with the dev server auto-reloading. This'll also bite you if you have a syntax error in an admin.py; after you fix it, the error will go away but that app will be missing entirely from the admin until you manually restart the dev server. Irritating, but I haven't yet dug in to find the bug. – Carl Meyer Aug 25 '09 at 15:27
  • FWIW, the bug was fixed for Django 1.2, and admin.py and runserver autoreload should be better together now. – Carl Meyer Dec 06 '10 at 21:45
  • You can try out https://github.com/kux/django-admin-extend for a generic way of extending already registered admin objects. – Ioan Alexandru Cucu Jul 15 '13 at 13:00
  • Can you explain why you had to unregister User, then reregister it along with MyUserAdmin? – thumbtackthief May 02 '14 at 19:56
  • 1
    @thumbtackthief Because Django won't let you register the same model twice, and User is already registered by contrib.auth with its UserAdmin class. So you have to unregistered it before you can register it with your own ModelAdmin subclass. – Carl Meyer May 04 '14 at 01:41
  • Nice solution, helped me a lot! For me also this code part came to picture: https://stackoverflow.com/questions/5429276/how-to-change-the-django-admin-filter-to-use-a-dropdown-instead-of-list | from django_admin_listfilter_dropdown.filters import (DropdownFilter, ChoiceDropdownFilter, RelatedDropdownFilter) With this I could use: list_filter = (('groups', RelatedDropdownFilter), ... ) – because the original group filtering is too long. – szabozoltan Jun 05 '19 at 09:57
  • The addition "admin.site.unregister(User)" helped me. – Vadim Sep 07 '21 at 10:39
2

I think it might be easier to do this with a custom auth backend and thus remove the need for a customized ModelAdmin.

I did something similar with this snippet: http://www.djangosnippets.org/snippets/74/

Andy Baker
  • 21,158
  • 12
  • 58
  • 71
  • Actually, I need both the enhanced backend and the front-end. I need to have the usernames be email addresses so that the "@domain" assures they're unique. I'm already using your snippet. But it helps to have it as part of this answer set. – S.Lott Jan 23 '09 at 11:34