#33703: ModelAdmin.get_fields wrong work with ModelAdmin.fieldsets statement
-----------------------------------+--------------------------------------
Reporter: Maxim Danilov | Owner: nobody
Type: Uncategorized | Status: new
Component: contrib.admin | Version: 4.0
Severity: Normal | Resolution:
Keywords: admin, modeladmin | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-----------------------------------+--------------------------------------
Changes (by Maxim Danilov):
* has_patch: 1 => 0
* easy: 1 => 0
Old description:
> almost all my issue is "not fixed", but i try
>
> I found a bug: ModelAdmin.get_fields works wrong with fieldset statement.
>
> How to reproduce it:
>
> {{{
> from django.db import models
> from django.contrib.admin import ModelAdmin
>
> class MyModel(models.Model):
> title = models.CharField('Meta Title of object', max_length=80,
> blank=True)
> slug = models.CharField('Meta Slug of object', max_length=80,
> blank=True)
>
> class MyModelAdmin1(ModelAdmin):
>
> fields = ('title', )
>
> class MyModelAdmin2(ModelAdmin):
> fieldset = ('title', )
>
> print(MyModelAdmin1(MyModel, None).get_fields(None))
> print(MyModelAdmin2(MyModel, None).get_fields(None))
> }}}
> save as test.py, in new or old project.
> python manage.py test output:
>
> {{{
> ('title',)
> ['title', 'slug']
> Found xxx test(s).
> ...
> }}}
>
> Problem is nor directly in def get_fields.
> {{{
> def get_fields(self, request, obj=None):
> """
> Hook for specifying fields.
> """
> if self.fields:
> return self.fields
> # _get_form_for_get_fields() is implemented in subclasses.
> form = self._get_form_for_get_fields(request, obj)
> return [*form.base_fields, *self.get_readonly_fields(request,
> obj)]
> }}}
>
> But in call of self._get_form_for_get_fields
>
> {{{
> def _get_form_for_get_fields(self, request, obj):
> return self.get_form(request, obj, fields=None)
> }}}
>
> The author of _get_form_for_get_fields has forgotten how self.get_form
> handles "fields":
>
> {{{
> def get_form(self, request, obj=None, change=False, **kwargs):
> """
> Return a Form class for use in the admin add view. This is used
> by
> add_view and change_view.
> """
> if 'fields' in kwargs:
> fields = kwargs.pop('fields')
> else:
> fields = flatten_fieldsets(self.get_fieldsets(request, obj))
> ...
> }}}
>
> I see two possibility to fix it:
>
> or
> {{{
> def _get_form_for_get_fields(self, request, obj):
> return self.get_form(request, obj)
> }}}
>
> or
>
> {{{
> def get_form(self, request, obj=None, change=False, **kwargs):
> """
> Return a Form class for use in the admin add view. This is used
> by
> add_view and change_view.
> """
> fields = kwargs.pop('fields', None) or []
> if not fields:
> fields = flatten_fieldsets(self.get_fieldsets(request, obj))
> ...
> }}}
> p.s.
> this issue is easy to create, we already have 'contrib.admin' in
> "component select" in Issue-Creation-Form, unlike, for example,
> 'contrib.gis'.
> For 'contrib.gis' we suddenly use GIS in uppercase.
New description:
almost all my issue is "not fixed", but i try
I found a bug: ModelAdmin.get_fields works wrong with fieldset statement.
How to reproduce it:
{{{
from django.db import models
from django.contrib.admin import ModelAdmin
class MyModel(models.Model):
title = models.CharField('Meta Title of object', max_length=80,
blank=True)
slug = models.CharField('Meta Slug of object', max_length=80,
blank=True)
class MyModelAdmin1(ModelAdmin):
fields = ('title', )
class MyModelAdmin2(ModelAdmin):
fieldset = ('title', )
print(MyModelAdmin1(MyModel, None).get_fields(None))
print(MyModelAdmin2(MyModel, None).get_fields(None))
}}}
save as test.py, in new or old project.
python manage.py test output:
{{{
('title',)
['title', 'slug']
Found xxx test(s).
...
}}}
Problem is nor directly in def get_fields.
{{{
def get_fields(self, request, obj=None):
"""
Hook for specifying fields.
"""
if self.fields:
return self.fields
# _get_form_for_get_fields() is implemented in subclasses.
form = self._get_form_for_get_fields(request, obj)
return [*form.base_fields, *self.get_readonly_fields(request,
obj)]
}}}
But in call of self._get_form_for_get_fields
{{{
def _get_form_for_get_fields(self, request, obj):
return self.get_form(request, obj, fields=None)
}}}
The author of _get_form_for_get_fields has forgotten how self.get_form
handles "fields":
{{{
def get_form(self, request, obj=None, change=False, **kwargs):
"""
Return a Form class for use in the admin add view. This is used by
add_view and change_view.
"""
if 'fields' in kwargs:
fields = kwargs.pop('fields')
else:
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
...
}}}
I thought we had two options to fix this:
{{{
def _get_form_for_get_fields(self, request, obj):
return self.get_form(request, obj)
}}}
or
{{{
def get_form(self, request, obj=None, change=False, **kwargs):
"""
Return a Form class for use in the admin add view. This is used by
add_view and change_view.
"""
fields = kwargs.pop('fields', None) or []
if not fields:
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
...
}}}
BUT! My solution not works, we receive a recursion:
{{{
in get_fields
call self._get_form_for_get_fields
in _get_form_for_get_fields
call self.get_form
in get_form
call self.get_fieldsets
in get_fieldsets
call self.get_fields (go to 1. step)
}}}
p.s.
this issue is easy to create, we already have 'contrib.admin' in
"component select" in Issue-Creation-Form, unlike, for example,
'contrib.gis'.
For 'contrib.gis' we suddenly use GIS in uppercase.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/33703#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070180b99523cf-6e7bd5fd-6574-43b1-8d2d-4feb7878161d-000000%40eu-central-1.amazonses.com.