Opened 16 months ago
Last modified 16 months ago
#34711 closed New feature
form.has_changed() is always True for IntegerChoices Enum Model Field — at Version 1
Reported by: | GHPS | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 4.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Summary:
While trying to find out why the forms in two different applications are
marked for saving even if no field has been changed, I could pin the problem down
to the integer enum fields used in both models and form.ChoiceField involved.
In short, form.has_changed() is triggered because of a double data conversion
during the round-trip.
The value of the integer enum field is converted to a string and rendered.
The POST request comes back with this string which gets compared to the original
enum integer which shows that they are different. During the - unnecessary - saving
the string becomes an int again - which is why the original problem is hidden
from the perspective of a user.
This bug seem to be a regression from bug #22097.
Background:
In Django 4.2 on Linux (Kubuntu 22.04) take the following enum and
create a model field in model.py:
class eAssets(models.IntegerChoices): dvd =1, _('DVD') bluray =3, _('Blu-ray') none =0, _('-') eAsset=models.PositiveSmallIntegerField(choices=eAssets.choices, default=eAssets.none)
Create a choice form field in form.py:
eAsset=forms.ChoiceField(label=mdMovie._meta.get_field('eAsset').verbose_name, choices=[(dcEntry.value, dcEntry.label) for dcEntry in mdMovie.eAssets], initial=mdMovie.eAssets.none)
After processing the POST request, form.has_changed() is always true in view.py:
>fmForm=fmMovie(vRequest.POST, vRequest.FILES or None, instance=rcCurrentMovie) >fmForm.has_changed() True >fmForm.changed_data ['eAsset']
Links:
- I've found an old ticket #22097 and it looks to me like this nine year old bug has shown its ugly face again.
- On Stackoverflow someone reported the same problem.
dynamic integer model choice field always fails form.has_changed()