[Django] #22097: IntegerField with given choices leads to wrong has_changed() work

37 views
Skip to first unread message

Django

unread,
Feb 20, 2014, 1:22:18 AM2/20/14
to django-...@googlegroups.com
#22097: IntegerField with given choices leads to wrong has_changed() work
---------------------------------+-------------------------
Reporter: igor.mitrenko@… | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 1.7-alpha-1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-------------------------
It seems that providing choices to IntegerField makes ModelForm (created
by admin, for example) to use ChoiceField and call it's to_python method,
which return string. Finally, _has_changed method compares initial value
(of type int) to new value (of type unicode), and always returns True.
My code sending "object created" signals on each inline object change, so
it leads to creation of unnecessary "changed" events logging.

Snippet:
{{{
...
class PhoneNumber(models.Model):
"""
Phone number set for workers
"""
MOBILE_PHONE = 0
WORK_PHONE = 1
HOME_PHONE = 2
KIND_CHOICES = (
(MOBILE_PHONE, _('Mobile')),
(WORK_PHONE, _('Work')),
(HOME_PHONE, pgettext('kind of phone number', 'Home')),
)
worker = models.ForeignKey(Worker)
phone_number = models.CharField(_('phone number'), max_length=12)
kind = models.SmallIntegerField(_('kind of number'),
choices=KIND_CHOICES, default=MOBILE_PHONE)
...
}}}
ModelForm derived from such a model created ChoiceField for kind, but it's
has_changed method return True always, cause it's (as example) always 1 !=
u'1'

Removing choices argument is a workaround, but it breaks desired
behaviour.
Another workaround is to use CharField, but the problem still remains.
Django version 1.7.dev20131210091409

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

Django

unread,
Feb 20, 2014, 4:08:00 AM2/20/14
to django-...@googlegroups.com
#22097: IntegerField with given choices leads to wrong has_changed() work
---------------------------------+---------------------------------------
Reporter: igor.mitrenko@… | Owner: claudep
Type: Bug | Status: assigned
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 claudep):

* status: new => assigned
* severity: Normal => Release blocker
* needs_better_patch: => 0
* needs_tests: => 0
* owner: nobody => claudep
* needs_docs: => 0
* stage: Unreviewed => Accepted


Comment:

This regression was introduced in a0f3eeccf3d5a90f9914bfe20b15df05673ea59d
in response to the use case described in #21397.

--
Ticket URL: <https://code.djangoproject.com/ticket/22097#comment:1>

Django

unread,
Feb 20, 2014, 7:43:27 AM2/20/14
to django-...@googlegroups.com
#22097: IntegerField with given choices leads to wrong has_changed() work
---------------------------------+---------------------------------------
Reporter: igor.mitrenko@… | Owner: claudep
Type: Bug | Status: closed
Component: Forms | Version: 1.7-alpha-1
Severity: Release blocker | Resolution: fixed

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 Claude Paroz <claude@…>):

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


Comment:

In [changeset:"cb844497d01ddb45603e47891cdf36ae0b006d03"]:
{{{
#!CommitTicketReference repository=""
revision="cb844497d01ddb45603e47891cdf36ae0b006d03"
Fixed #22097 -- Fixed change detection for TypedChoiceField

Thanks Igor Mitrenko for the report.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/22097#comment:2>

Django

unread,
Jul 14, 2023, 12:35:32 PM7/14/23
to django-...@googlegroups.com
#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

unread,
Jul 14, 2023, 12:46:31 PM7/14/23
to django-...@googlegroups.com
#22097: IntegerField with given choices leads to wrong has_changed() work
---------------------------------+----------------------------------------
Reporter: igor.mitrenko@… | Owner: Claude Paroz
Type: Bug | Status: new
Component: Forms | Version: 4.2

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

* cc: GHPS (added)
* version: 1.7-alpha-1 => 4.2


--
Ticket URL: <https://code.djangoproject.com/ticket/22097#comment:4>

Django

unread,
Jul 14, 2023, 1:29:25 PM7/14/23
to django-...@googlegroups.com
#22097: IntegerField with given choices leads to wrong has_changed() work
---------------------------------+----------------------------------------
Reporter: igor.mitrenko@… | Owner: Claude Paroz
Type: Bug | Status: closed
Component: Forms | Version: 1.7-alpha-1
Severity: Release blocker | Resolution: fixed

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 Mariusz Felisiak):

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


Comment:

GHPS, please don't reopen old already fixed issue. If you believe it's an
issue in Django, then please create a new ticket in Trac and follow our
[https://docs.djangoproject.com/en/dev/internals/contributing/bugs-and-
features/#reporting-bugs bug reporting guidelines].

Reply all
Reply to author
Forward
0 new messages