#22097: IntegerField with given choices leads to wrong has_changed() work
---------------------------------+----------------------------------------
     Reporter:  igor.mitrenko@…  |                    Owner:  Claude Paroz
         Type:  Bug              |                   Status:  new
    Component:  Forms            |                  Version:  1.7-alpha-1
     Severity:  Release blocker  |               Resolution:
     Keywords:                   |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+----------------------------------------
Changes (by GHPS):

 * status:  closed => new
 * resolution:  fixed =>


Comment:

 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.

 I found this old ticket and it looks to me like the nine year old bug has
 shown its ugly face again.

 Background:

 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:
 On Stackoverflow someone reported the same problem.
 [https://stackoverflow.com/questions/68763230/django-forms-a-dynamic-
 integer-model-choice-field-always-fails-form-has-changed|A dynamic integer
 model choice field always fails form.has_changed()]

-- 
Ticket URL: <https://code.djangoproject.com/ticket/22097#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701895541de0b-303ed10e-39e1-49c8-8814-dc8f3f38b037-000000%40eu-central-1.amazonses.com.

Reply via email to