How can I use a custom widget in the Admin for a custom user

186 views
Skip to first unread message

Mike Dewhirst

unread,
Jan 6, 2020, 3:27:46 AM1/6/20
to Django users
Sorry for being boring  ...

I cannot persuade the UserAdmin to use a custom widget instead of the
one it usually uses. If you can point out where I'm going wrong I will
be indebted to you.

 I have tried two ways of using a custom widget ...

1.
https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides

2.
https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_manytomany

Neither of these seem to work for me with a minimally adjusted widget
(see below). This is what I have done ...

#common.widgets.py (my app here is "common")

from django.contrib.admin import widgets


class CommonFilteredSelectMultiple(widgets.FilteredSelectMultiple):
    """ If we can only get this to execute we can adjust the context """

   def get_context(self, name, value, attrs):
        # apart from the print call, this matches FilteredSelectMultiple
print("\n10 admin.widgets")
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['class'] = 'selectfilter'
        if self.is_stacked:
            context['widget']['attrs']['class'] += 'stacked'
        context['widget']['attrs']['data-field-name'] = self.verbose_name
        context['widget']['attrs']['data-is-stacked'] =
int(self.is_stacked)
        return context



#common.admin.py

from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.db import models
from common.utils import (
    is_sharedsds, user_sharedsds_admin, userprofile_sharedsds_admin,
)
from common.models import UserProfile
from common.widgets import CommonFilteredSelectMultiple


class CommonUserAdmin(UserAdmin):

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "groups":
            kwargs["widget"] = CommonFilteredSelectMultiple
            print("\n23 common.admin")
        return super().formfield_for_manytomany(db_field, request,
**kwargs)

    model = get_user_model()
    extra = 0
    readonly_fields = [
        "last_login",
        "is_staff",
        "is_active",
        "date_joined",
        "groups",
    ]
    get_readonly_fields = user_sharedsds_admin
    fieldsets = [
        (
            "More detail",
            {
                "description": "Server date/times are UTC rather than
local time<hr/>",
                "classes": ("",),
                "fields": (
                    "password",
                    "last_login",
                    "username",
                    "first_name",
                    "last_name",
                    "email",
                    "is_staff",
                    "is_active",
                    "groups",
                    "date_joined",
                ),
            },
        ),
    ]

    class UserProfileInline(admin.StackedInline):
        def has_add_permission(self, request=None, obj=None):
            return False

        def has_delete_permission(self, request=None, obj=None):
            return False

        model = UserProfile
        extra = 0
        verbose_name_plural = "Profile"
        readonly_fields = ("company", "modified",)
        get_readonly_fields = userprofile_sharedsds_admin
        fieldsets = (
            (
                "Cellphone, Company",
                {
                    "classes": ("collapse",),
                    "fields": (
                        "cellphone",
                        "company",
                        #'otp',
                        #'sms',
                        #'fluency',
                    ),
                },
            ),
            (
                "Preferences",
                {
                    "classes": ("collapse",),
                    "fields": (
                        "code_preference",
                        "subsections",
                        "licensed_data",
                        "open_data",
                        "ingredient_data",
                        "modified",
                    ),
                },
            ),
        )
    inlines = [
        UserProfileInline,
    ]


admin.site.register(get_user_model(), CommonUserAdmin)

Thanks for any help ...

Cheers

Mike

Mike Dewhirst

unread,
Jan 7, 2020, 9:03:42 PM1/7/20
to django...@googlegroups.com
On 6/01/2020 7:26 pm, Mike Dewhirst wrote:
> Sorry for being boring  ...
>
> I cannot persuade the UserAdmin to use a custom widget instead of the
> one it usually uses. If you can point out where I'm going wrong I will
> be indebted to you.
>
>  I have tried two ways of using a custom widget ...
>
> 1.
> https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides
>
> 2.
> https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_manytomany

I think the documentation might be wrong on both the above references.
Or at least I couldn't get either to work so your mileage may vary.

What did work (for me) was the following ...

#common.admin.py (common is my custom-user app)

from django.contrib.auth.admin import UserAdmin
from common.widgets import CommonFilteredSelectMultiple

class CommonUserAdmin(UserAdmin):

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "groups":
            formfield = super().formfield_for_manytomany(db_field,
request, **kwargs)
            formfield.widget = CommonFilteredSelectMultiple(
                db_field.verbose_name,
                db_field.name in self.filter_vertical,
            )
            return formfield
        return super().formfield_for_manytomany(db_field, request,
**kwargs)
...

#common.widgets.py

from django.contrib.admin import widgets

class CommonFilteredSelectMultiple(widgets.FilteredSelectMultiple):

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['attrs']['class'] = 'selectfilter'
        if self.is_stacked:
            context['widget']['attrs']['class'] += 'stacked'
        context['widget']['attrs']['data-field-name'] = self.verbose_name
        context['widget']['attrs']['data-is-stacked'] =
int(self.is_stacked)
        print("\n20 common.widgets")



Cheers

Mike
Reply all
Reply to author
Forward
0 new messages