Opened 2 years ago
Last modified 2 years 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()