Opened 4 years ago

Last modified 4 years ago

#23501 new Bug

remove/add fields programatically in modelform fails in admin

Reported by: hadisunyoto Owned by: nobody
Component: contrib.admin Version: 1.7
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by hadisunyoto)

model:

class Thickness(models.Model):
    value = models.DecimalField(primary_key=True, max_digits=7, decimal_places=2)
    is_active = models.BooleanField()

model form:

class ThicknessForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ThicknessForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)

        # edit
        if instance and instance.pk:
            del self.fields['value']
        else:
            del self.fields['is_active']

    class Meta:
        model = Thickness
        fields = '__all__'

admin:

class ThicknessAdmin(admin.ModelAdmin):
    list_display = ('value', 'is_active')
    form = ThicknessForm

admin.site.register(Thickness, ThicknessAdmin)

refresh page, go to admin->Thickness, create one:

KeyError at /admin/thicknesses/thickness/add/
"Key 'is_active' not found in 'ThicknessForm'"
...

Error during template rendering

In template D:\env\lib\site-packages\django\contrib\admin\templates\admin\includes\fieldset.html, error at line 7

The highlighted line is number 7

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 %}

go to admin->Thickness again, modify one (created previously without using model form):
KeyError at /admin/thicknesses/thickness/0.55/
"Key 'value' not found in 'ThicknessForm'"
...

same error as above

Without admin, model form works as expected, it remove is_active when create, and it remove value when edit

Change History (6)

comment:1 Changed 4 years ago by hadisunyoto

Description: modified (diff)

comment:2 Changed 4 years ago by Tim Graham

Triage Stage: UnreviewedAccepted

I looked into this and I believe you can fix this by using ModelAdmin.get_fields() to exclude the field. It might be easiest to simply document that you should use that method and not the del approach.

comment:3 Changed 4 years ago by hadisunyoto

I am aware of such methods, what i was trying to do is to push as much form control in modelform instead of in the admin. So next time when i have time i can build my own admin and reuse modelform without modifying the code again

comment:4 Changed 4 years ago by Tim Graham

You should be able to keep the del logic, as long as you also use get_fields().

comment:5 Changed 4 years ago by hadisunyoto

thank you for your quick response, in the mean time, i will try your suggestion

comment:6 Changed 4 years ago by hadisunyoto

A little update:

i tried get_fields() method and still keep del intact, it turns out to be an error

KeyError at /admin/thicknesses/thickness/0.55/
'value'

21.    def __init__(self, *args, **kwargs):
22.        super(ThicknessForm, self).__init__(*args, **kwargs)
23.        instance = getattr(self, 'instance', None)
24.
25.        # edit
26.        if instance and instance.pk:
27.            del self.fields['value'] <--
28.
29.    class Meta:

occur in line 27

i guess i have to forget about the form and put everything in admin then. What worries me is there will be several models that requires the clean() method in form to check related fields, that means that i have two places (form and admin) that handles the form, and i don't think that's a good approach

Note: See TracTickets for help on using tickets.
Back to Top