Error: Key 'groups' not found in 'UserForm'

413 views
Skip to first unread message

Mike Dewhirst

unread,
Jan 5, 2020, 8:47:01 PM1/5/20
to Django users
This error occurs in the Admin for my custom user when I try to specify
a custom widget for permission groups. I haven't included 'groups' in
any raw_id_fields, radio_fields or autocomplete_fields. The groups are
correctly displayed in the Admin user page with the default
FilteredSelectMultiple widget.

This is the relevant code in admin.py ... (traceback below)

class CommonUserAdmin(UserAdmin):

    model = get_user_model()

    def formfield_for_manytomany(self, db_field, request, **kwargs):

        if db_field.name == "groups":
            formfield_overrides = {
                models.ManyToManyField: {'widget':
CommonFilteredSelectMultiple},
            }
    ...

If I omit the formfield_for_manytomany() method and just run
formfield_overrides nakedly nothing happens - presumably because the
admin doesn't consider "groups" is a ManyToManyField at that point.

How do I persuade the Admin to use my widget?

Thanks for any advice

Mike



Environment:


Request Method: GET
Request URL: http://localhost:8000/admin/common/user/59/change/

Django Version: 2.2.9
Python Version: 3.7.4
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'django.contrib.staticfiles',
 'common',
 'billing',
 'company',
 'credit',
 'refer',
 'regulation',
 'substance',
 'workplace']
Installed Middleware:
['django.middleware.cache.UpdateCacheMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.contrib.admindocs.middleware.XViewMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'pwned_passwords_django.middleware.PwnedPasswordsMiddleware',
 'django.middleware.cache.FetchFromCacheMiddleware']


Template error:
In template
D:\Users\mike\envs\xxex3\lib\site-packages\django\contrib\admin\templates\admin\includes\fieldset.html,
error at line 7
   Key 'groups' not found in 'UserForm'. Choices are: email,
first_name, is_active, is_staff, last_name, password, username.
   1 : <fieldset class="module aligned {{ fieldset.classes }}">
   2 :     {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
   3 :     {% if fieldset.description %}
   4 :         <div class="description">{{ fieldset.description|safe
}}</div>
   5 :     {% endif %}
   6 :     {% for line in fieldset %}
   7 :         <div class="form-row{% if line.fields|length_is:'1' and
line.errors %} errors{% endif %}{% if not line.has_visible_field %}
hidden{% endif %} {% for field in line %} {% if field.field.name %}
field-{{ field.field.name }}{% endif %}{% endfor %}">
   8 :             {% if line.fields|length_is:'1' %}{{ line.errors
}}{% endif %}
   9 :             {% for field in line %}
   10 :                 <div{% if not line.fields|length_is:'1' %}
class="fieldBox{% if field.field.name %} field-{{ field.field.name }}{%
endif %}{% if not field.is_readonly and field.errors %} errors{% endif
%}{% if field.field.is_hidden %} hidden{% endif %}"{% elif
field.is_checkbox %} class="checkbox-row"{% endif %}>
   11 :                     {% if not line.fields|length_is:'1' and not
field.is_readonly %}{{ field.errors }}{% endif %}
   12 :                     {% if field.is_checkbox %}
   13 :                         {{ field.field }}{{ field.label_tag }}
   14 :                     {% else %}
   15 :                         {{ field.label_tag }}
   16 :                         {% if field.is_readonly %}
   17 :                             <div class="readonly">{{
field.contents }}</div>


Traceback:

File "D:\Users\mike\envs\xxex3\lib\site-packages\django\forms\forms.py"
in __getitem__
  163.             field = self.fields[name]

During handling of the above exception ('groups'), another exception
occurred:

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\core\handlers\exception.py"
in inner
  34.             response = get_response(request)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\core\handlers\base.py"
in _get_response
  145.                 response =
self.process_exception_by_middleware(e, request)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\core\handlers\base.py"
in _get_response
  143.                 response = response.render()

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\response.py"
in render
  106.             self.content = self.rendered_content

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\response.py"
in rendered_content
  83.         content = template.render(context, self._request)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\backends\django.py"
in render
  61.             return self.template.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  171.                     return self._render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
_render
  163.         return self.nodelist.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  937.                 bit = node.render_annotated(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\loader_tags.py"
in render
  150.             return compiled_parent._render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
_render
  163.         return self.nodelist.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  937.                 bit = node.render_annotated(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\loader_tags.py"
in render
  150.             return compiled_parent._render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
_render
  163.         return self.nodelist.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  937.                 bit = node.render_annotated(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\loader_tags.py"
in render
  62.                 result = block.nodelist.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  937.                 bit = node.render_annotated(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\loader_tags.py"
in render
  62.                 result = block.nodelist.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  937.                 bit = node.render_annotated(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\defaulttags.py"
in render
  209. nodelist.append(node.render_annotated(context))

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\loader_tags.py"
in render
  188.             return template.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  173.                 return self._render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
_render
  163.         return self.nodelist.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render
  937.                 bit = node.render_annotated(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\defaulttags.py"
in render
  209. nodelist.append(node.render_annotated(context))

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\base.py" in
render_annotated
  904.             return self.render(context)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\template\defaulttags.py"
in render
  165.                 values = list(values)

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\contrib\admin\helpers.py"
in __iter__
  113.                 yield AdminField(self.form, field, is_first=(i
== 0))

File
"D:\Users\mike\envs\xxex3\lib\site-packages\django\contrib\admin\helpers.py"
in __init__
  125.         self.field = form[field]  # A django.forms.BoundField
instance

File "D:\Users\mike\envs\xxex3\lib\site-packages\django\forms\forms.py"
in __getitem__
  169.                     ', '.join(sorted(f for f in self.fields)),

Exception Type: KeyError at /admin/common/user/59/change/
Exception Value: "Key 'groups' not found in 'UserForm'. Choices are:
email, first_name, is_active, is_staff, last_name, password, username."

Mike Dewhirst

unread,
Jan 6, 2020, 12:06:15 AM1/6/20
to django...@googlegroups.com
Significant refinement of the error ...

Trying to use formfield_for_manytomany() triggers the error even if all
it does is "pass"

Something fishy ... I'll write a fresh question.

Mike

Stephen J. Butler

unread,
Jan 6, 2020, 12:56:09 AM1/6/20
to django...@googlegroups.com
Take another look at the doc's example on formfield_for_manytomany:


You need to call super() and this isn't the right way to override the widget.

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

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/52cffdfe-9e4c-5c49-7f97-3e6c5857bcc2%40dewhirst.com.au.

Mike Dewhirst

unread,
Jan 6, 2020, 1:46:19 AM1/6/20
to django...@googlegroups.com
Stephen

Thank you. I should have remembered to return super()! That has stopped
it barfing and I'll withdraw my earlier question.

I'm still researching because  kwargs["widget"] =
CommonFilteredSelectMultiple doesn't seem to switch the field away from
FilteredSelectMultiple. At this point anyway.

Thanks again

Mike


On 6/01/2020 4:55 pm, Stephen J. Butler wrote:
> Take another look at the doc's example on formfield_for_manytomany:
>
> https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_manytomany
>
> You need to call super() and this isn't the right way to override the
> widget.
>
> def formfield_for_manytomany(self, db_field, request, **kwargs):
>         if db_field.name <http://db_field.name> == "groups":
>             kwargs["widget"] = CommonFilteredSelectMultiple
>         return super().formfield_for_manytomany(db_field, request,
> **kwargs)
>
> On Sun, Jan 5, 2020 at 11:05 PM Mike Dewhirst <mi...@dewhirst.com.au
> <mailto:mi...@dewhirst.com.au>> wrote:
>
> Significant refinement of the error ...
>
> Trying to use formfield_for_manytomany() triggers the error even
> if all
> it does is "pass"
>
> Something fishy ... I'll write a fresh question.
>
> Mike
>
> On 6/01/2020 12:46 pm, Mike Dewhirst wrote:
> > This error occurs in the Admin for my custom user when I try to
> > specify a custom widget for permission groups. I haven't included
> > 'groups' in any raw_id_fields, radio_fields or autocomplete_fields.
> > The groups are correctly displayed in the Admin user page with the
> > default FilteredSelectMultiple widget.
> >
> > This is the relevant code in admin.py ... (traceback below)
> >
> > class CommonUserAdmin(UserAdmin):
> >
> >     model = get_user_model()
> >
> >     def formfield_for_manytomany(self, db_field, request, **kwargs):
> >
> >         if db_field.name <http://db_field.name> == "groups":
> >    2 :     {% if fieldset.name <http://fieldset.name> %}<h2>{{
> fieldset.name <http://fieldset.name> }}</h2>{% endif %}
> >    3 :     {% if fieldset.description %}
> >    4 :         <div class="description">{{
> fieldset.description|safe
> > }}</div>
> >    5 :     {% endif %}
> >    6 :     {% for line in fieldset %}
> >    7 :         <div class="form-row{% if
> line.fields|length_is:'1' and
> > line.errors %} errors{% endif %}{% if not line.has_visible_field %}
> > hidden{% endif %} {% for field in line %} {% if field.field.name
> <http://field.field.name> %}
> > field-{{ field.field.name <http://field.field.name> }}{% endif
> %}{% endfor %}">
> >    8 :             {% if line.fields|length_is:'1' %}{{ line.errors
> > }}{% endif %}
> >    9 :             {% for field in line %}
> >    10 :                 <div{% if not line.fields|length_is:'1' %}
> > class="fieldBox{% if field.field.name <http://field.field.name>
> %} field-{{ field.field.name <http://field.field.name>
> <mailto:django-users%2Bunsu...@googlegroups.com>.
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com
> <mailto:django-users...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CAD4ANxXAtDEMr%3DT3buT9OuVrndt8AiJYaL9Gv9MfmyNcjJMWSA%40mail.gmail.com
> <https://groups.google.com/d/msgid/django-users/CAD4ANxXAtDEMr%3DT3buT9OuVrndt8AiJYaL9Gv9MfmyNcjJMWSA%40mail.gmail.com?utm_medium=email&utm_source=footer>.

Reply all
Reply to author
Forward
0 new messages