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 Initial Version

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

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.

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()

Change History (0)

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