#30907: SplitArrayField.has_changed() returns True for unchanged fields
--------------------------------------------+------------------------
Reporter: paveldedik | Owner: (none)
Type: Uncategorized | Status: new
Component: contrib.postgres | Version: 2.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 1
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------------+------------------------
This ticket addresses similar issue as in
https://code.djangoproject.com/ticket/28950 only for the `SplitArrayField`
I have the following models and forms:
{{{
class Service(models.Model):
name = pg_fields.CICharField(max_length=100)
class Environment(models.Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
urls = pg_fields.ArrayField(
models.URLField(max_length=500), null=True, default=list
)
class EnvironmentForm(forms.ModelForm):
urls = SplitArrayField(
forms.URLField(required=False),
remove_trailing_nulls=True,
required=False,
size=2,
)
class Meta:
model = models.Environment
fields = ["name", "urls"]
ServiceEnvironmentsFormSet = forms.inlineformset_factory(
models.Service,
models.Environment,
form=EnvironmentForm,
extra=2,
can_delete=True,
)
class ServiceForm(forms.ModelForm):
class Meta:
model = models.Service
fields = ["name"]
}}}
Note the `ServiceEnvironmentsFormSet` which I'm rendering in a template
including the `SplitArrayField` named `urls`. When I fill only the name of
the `Service` in the rendered `ServiceForm` without entering any data to
rendered `Environment` forms, the `ServiceEnvironmentsFormSet` validation
fails. That's because in `EnvironmentForm`, the `name` is required, but
that's not the problem - this should be ok when using `InlineFormSet` as
each form in the FormSet is optional. So why does it fail? Because Django
starts validating forms in `InlineFormSet` if the `form.has_changed()`
method returns `True`. And in this case, it always returns `True` because
`SplitArrayField.has_changed()` returns `True` in the following cases:
{{{
SplitArrayField.has_changed(None, ["", ""]) # returns True even though it
shouldn't as ["", ""] means no data in the form has been entered
SplitArrayField.has_changed([], ["", ""]) # returns True - should be
False
SplitArrayField.has_changed(["a"], ["a", ""]) # returns True - should be
False
}}}
Note that I'm using `remove_trailing_nulls=True` in the `SplitArrayField`.
So the above cases should all evaluate to `False` I believe.
I already opened PR for this here:
https://github.com/django/django/pull/11970
BTW I'm not sure how `has_changed()` should be evaluated when passing both
`remove_trailing_nulls=False` and `required=False` to the `base_field`, as
in that case all required fields in the FormSet would have to be filled by
the user since `has_changed()` would always return `True` even for empty
input values.
--
Ticket URL: <https://code.djangoproject.com/ticket/30907>
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/053.b17bb95f3a2f15c2958ad857136b418c%40djangoproject.com.