Opened 10 years ago
Last modified 10 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 |
Pull Requests: | How to create a pull request | ||
Description (last modified by ) ¶
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
According to the ticket's flags, the next step(s) to move this issue forward are:
- To provide a patch by sending a pull request. Claim the ticket when you start working so that someone else doesn't duplicate effort. Before sending a pull request, review your work against the patch review checklist. Check the "Has patch" flag on the ticket after sending a pull request and include a link to the pull request in the ticket comment when making that update. The usual format is:
[https://github.com/django/django/pull/#### PR]
.
Change History (6)
comment:1 by , 10 years ago
Description: | modified (diff) |
---|
comment:2 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 10 years ago
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 by , 10 years ago
You should be able to keep the del
logic, as long as you also use get_fields()
.
comment:5 by , 10 years ago
thank you for your quick response, in the mean time, i will try your suggestion
comment:6 by , 10 years ago
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
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.