We encountered the bug when using a TypedChoiceField in a form of a
formset. When we have an empty extra form, and we submit all the form, the
submitted form is not validated due to some "changes" made to the
TypedChoiceFields.
The excepted behavior would be to save the formset data without treating
that extra form.
I finally found that the method has_changed of a field has been modified
from 1.8, and calls self._coerce for the initial value. By removing it, my
use case now works like expected.
I attach to this ticket a unit test that reproduces my case.
--
Ticket URL: <https://code.djangoproject.com/ticket/25942>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* Attachment "test.patch" added.
Unit test
* needs_docs: => 0
* needs_better_patch: => 0
* severity: Normal => Release blocker
* needs_tests: => 0
* stage: Unreviewed => Accepted
Comment:
I haven't completely verified the report, but bisected the change to
8714403614c4dfa37e806db4a6708b8a91a827a4.
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:1>
Comment (by claudep):
It would help to know a bit more about the use case, notably because your
test didn't set the `coerce` argument. Could you provide a little more
context, also about the form classes involved?
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:2>
Comment (by arthru):
In fact, in my case, the coerce is used using the field's to_python method
as following (my mistake, sorry) :
{{{
from django.db import models
from django.forms import TypedChoiceField
CHOICES = [
('choice1', 'Choice 1'),
('choice2', 'Choice 2'),
('choice3', 'Choice 3')
]
my_choices = models.CharField(
max_length=7,
choices=CHOICES,
null=True,
blank=True,
default=None,
)
kwargs = {
'label': 'Method',
'choices': [
('', '---------'),
('choice1', 'Choice 1'),
('choice2', 'Choice 2'),
('choice3', 'Choice 3')
],
'initial': None,
'empty_value': None,
'required': False,
'help_text': '',
'coerce': my_choices.to_python,
}
tcf = TypedChoiceField(**kwargs)
# the following line did work in django 1.8
assert not tcf.has_changed(None, '')
}}}
Overall, I detected that when using my model in a formset having an
extra=1. When submitting without touching anything, the form is treated as
a changed form due to this changed field (where it should be ignored as
nothing was changed).
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:3>
* has_patch: 0 => 1
Comment:
That's an issue with `CharField` and `null=True` (which is discouraged).
However, I think the [https://github.com/django/django/pull/5833 PR] fixes
this.
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:4>
Comment (by arthru):
I can confirm that the PR fixes the bug on my code. Thanks for that !
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:5>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:6>
* status: new => closed
* resolution: => fixed
Comment:
In [changeset:"d91cc25a2a43cb2526943dc2285ffe59e38fabfd" d91cc25]:
{{{
#!CommitTicketReference repository=""
revision="d91cc25a2a43cb2526943dc2285ffe59e38fabfd"
Fixed #25942 -- Fixed TypedChoiceField.has_changed with nullable field
This fixes a regression introduced by 871440361.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:7>
Comment (by Claude Paroz <claude@…>):
In [changeset:"ff077cd6496b6f82195e2dc040f70e19e7c206c9" ff077cd]:
{{{
#!CommitTicketReference repository=""
revision="ff077cd6496b6f82195e2dc040f70e19e7c206c9"
[1.9.x] Fixed #25942 -- Fixed TypedChoiceField.has_changed with nullable
field
This fixes a regression introduced by 871440361.
Backport of d91cc25a2a from master.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25942#comment:8>