Opened 5 years ago
Closed 5 years ago
#30596 closed Bug (fixed)
SplitArrayField.has_changed() is always True for numeric fields.
Reported by: | Evgeniy Krysanov | Owned by: | Chason Chaffin |
---|---|---|---|
Component: | contrib.postgres | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Code example:
# models.py class Signal(models.Model): order_price = ArrayField(models.FloatField(), default=list) # admin.py class SignalForm(forms.ModelForm): order_price = SplitArrayField(base_field=forms.FloatField(), size=3, remove_trailing_nulls=True, required=False) @admin.register(Signal) class SignalAdmin(admin.ModelAdmin): form = SignalForm def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) print(form.has_changed()) # Always True even if no values was changed
Attachments (1)
Change History (7)
follow-up: 2 comment:1 by , 5 years ago
comment:2 by , 5 years ago
Replying to felixxm:
I was not able to reproduce this issue in basic tests. Maybe it is related
remove_trailing_nulls=True
, do you have them in a database? e.g.[1.33, 5.33. 8.78, None]
Can you check initial data?
I checked a lot of cases until I isolated the problem - https://github.com/django/django/blob/master/django/forms/forms.py#L451
initial_value
is the original object's value, for example [3.5, 1.0, 2.2]. data_value
is converted from form data to ['3.5', '1.0', '2.2'], but not converted to FloatField values. If the initial_value
is [] then the data_value
is ['', '', '']
. Thats why has_changed
always returns True.
I fixed this bug in my project with the following code:
class BetterSplitArrayField(SplitArrayField): def to_python(self, value): return self.clean(value)
When calling field.has_changed(initial_value, data_value)
there is a call to data = self.to_python(data)
https://github.com/django/django/blob/master/django/forms/fields.py#L181 but SplitArrayField
just returns the original value from this method. My code fix this.
But it would be better to see the fix in Django source. I can write a PR with unitests if you wish.
comment:3 by , 5 years ago
Component: | Forms → contrib.postgres |
---|---|
Summary: | Form method `has_changed` always returns True if form has the SplitArrayField field → SplitArrayField.has_changed() is always True for numeric fields. |
Triage Stage: | Unreviewed → Accepted |
Version: | 2.2 → master |
Thanks for details. I was able to reproduce this issue.
comment:4 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
I was not able to reproduce this issue in basic tests. Maybe it is related
remove_trailing_nulls=True
, do you have them in a database? e.g.[1.33, 5.33. 8.78, None]
Can you check initial data?