﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33703	ModelAdmin.get_fields wrong work with ModelAdmin.fieldsets statement	Maxim Danilov	nobody	"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.    "	Uncategorized	new	contrib.admin	4.0	Normal		admin, modeladmin		Unreviewed	0	0	0	0	0	0
