Opened 17 years ago

Closed 12 years ago

#5524 closed Bug (fixed)

Cleaned form data should not be deleted if other data is invalid.

Reported by: Ben Slavin Owned by: Simon Charette
Component: Forms Version: dev
Severity: Normal Keywords:
Cc: hv@…, simon@…, charette.s@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Currently, when validating a newforms Form object (.full_clean()), the cleaned_data attribute is deleted if any of the fields on the form are invalid.

Data that has been cleaned should be retained, rather than deleted.

Some sample use cases are:

  1. Allowing partial previews (discussed in #5153)
  2. Maintain file-uploads across submits of a form
  3. Prevent having to perform expensive operations twice (hash the value and compare on resubmit)

Discussed here http://groups.google.com/group/django-developers/browse_thread/thread/a23807d32cc3042d/58a4ea6a2e3e8a77.

Attachments (7)

ticket_5524__revision_6369.diff (903 bytes ) - added by Ben Slavin 17 years ago.
cleaned_data is persisted for fields that do not have validation errors. (corrected typo in previous)
ticket_5524__rev_6822.diff (11.4 KB ) - added by Ben Slavin 16 years ago.
Now with docs and tests.
ticket_5524__rev_6917.diff (5.1 KB ) - added by Ben Slavin 16 years ago.
5524-new.diff (7.0 KB ) - added by Claude Paroz 12 years ago.
Refresh the patch
5524-new2.diff (7.9 KB ) - added by Claude Paroz 12 years ago.
Added release notes section
5524-new-3.diff (12.5 KB ) - added by Aymeric Augustin 12 years ago.
5524-new-4.patch (13.7 KB ) - added by Simon Charette 12 years ago.
Doc update and unicode_literals related changes

Download all attachments as: .zip

Change History (33)

comment:1 by Ben Slavin, 17 years ago

Needs documentation: set
Needs tests: set

by Ben Slavin, 17 years ago

cleaned_data is persisted for fields that do not have validation errors. (corrected typo in previous)

comment:2 by James Bennett, 16 years ago

Triage Stage: UnreviewedAccepted

by Ben Slavin, 16 years ago

Attachment: ticket_5524__rev_6822.diff added

Now with docs and tests.

comment:3 by Ben Slavin, 16 years ago

Needs documentation: unset
Needs tests: unset
Triage Stage: AcceptedReady for checkin

comment:4 by Malcolm Tredinnick, 16 years ago

Triage Stage: Ready for checkinAccepted

Is the change to the _data() method really necessary?

I'd tend to lean towards displaying the data exactly as the user entered it when we are redisplaying the form after an error. This part of the patch changes what the user entered to the normalised form, which may be more confusing than helpful. I'm not going to reject it out of hand in case there's a subtlety I'm missing, but more explanation required for that part, please.

in reply to:  4 comment:5 by Ben Slavin, 16 years ago

Owner: changed from nobody to Ben Slavin
Status: newassigned

Replying to mtredinnick:

Is the change to the _data() method really necessary?

I'd tend to lean towards displaying the data exactly as the user entered it when we are redisplaying the form after an error.


You're absolutely right on this. The use-case I'm using as a reference is #2 from the ticket description (preserving file uploads across submits). In my own solution to that problem, I had to hack data to pull the information from the normalization process. Looking more closely, this was the wrong way of handling things since it has unintended (and potentially harmful/confusing) results.

I'm attaching a new patch which introduces a cleaned_data property to the BoundField class. This means that normalized data will be easily accessible, but the behavior of _data() will remain unchanged.

What do you think of this approach?

I should have thought about this when I had to go changing so many tests.

by Ben Slavin, 16 years ago

Attachment: ticket_5524__rev_6917.diff added

comment:6 by Ben Slavin, 16 years ago

milestone: 1.0

Spoke with Malcolm, adding 1.0 milestone.... he doesn't think it's likely to be backwards incompatible, but we should give it a bit more thought.

comment:7 by Malcolm Tredinnick, 16 years ago

milestone: 1.0post-1.0
Summary: [patch] Cleaned form data should not be deleted if other data is invalid.Cleaned form data should not be deleted if other data is invalid.

Pushing to after 1.0 because it adds features. We've just got too much to do to nurse the bugs that might be caused by even little additions at the moment. Sorry, Ben.

comment:8 by Thomas Güttler, 15 years ago

Cc: hv@… added

comment:9 by (none), 15 years ago

milestone: post-1.0

Milestone post-1.0 deleted

comment:10 by Colin Copeland, 14 years ago

this ticket is somewhat related to #10828

comment:11 by Gabriel Hurley, 13 years ago

Severity: Normal
Type: Bug

comment:12 by Julien Phalip, 13 years ago

Easy pickings: unset
Patch needs improvement: set

The tests would need to be rewritten using unittests since this is now Django's preferred way.

by Claude Paroz, 12 years ago

Attachment: 5524-new.diff added

Refresh the patch

comment:13 by Claude Paroz, 12 years ago

Owner: Ben Slavin removed
Patch needs improvement: unset
Status: assignednew
UI/UX: unset

I just attached a new patch for current trunk. I didn't include the cleaned_data for the bound field, as it might be a separate issue, if I understand it well. Comments welcome.

comment:14 by Thomas Güttler, 12 years ago

I applied 5524-new.diff and all of my 280 unittests passed. I read the patch and think it can be committed.

comment:15 by ris, 12 years ago

I often find myself using the pattern

form = BananaForm ( request.GET )

if not form.is_valid ():
	# probably very APIFRAGILE, but we need the remnants of the cleaned_data
	# containing the bits of form that did validate.
	form.cleaned_data = {}
	form._clean_fields ()
	form = BananaForm ( initial = form.cleaned_data )

so I can supply arbitrary pre-filled-out form elements in a GET string to a view that only usually POSTs to itself. Doing it this way allows just the supplied (and I suppose valid) elements to be filled in without nasty error messages for e.g. required fields that weren't.

I would love to be able to remove such flaky bits from my code.

I would have personally suggested moving/renaming cleaned_data to something else (partial_cleaned_data?) when overall validation fails rather than just not deleting it. Some existing code may be implicitly relying on the existence of cleaned_data to signify the form as being valid.

in reply to:  15 comment:16 by Claude Paroz, 12 years ago

Replying to ris:
(...)

Some existing code may be implicitly relying on the existence of cleaned_data to signify the form as being valid.

The docs clearly specify that this behaviour may change in the future, so they have been warned (sorry for them).

comment:17 by Aymeric Augustin, 12 years ago

Patch needs improvement: set

This change should be explained in the release notes. Besides this the patch looks pretty good.

by Claude Paroz, 12 years ago

Attachment: 5524-new2.diff added

Added release notes section

comment:18 by Aymeric Augustin, 12 years ago

Owner: set to Aymeric Augustin

comment:19 by Simon Litchfield, 12 years ago

Cc: simon@… added

comment:20 by Aymeric Augustin, 12 years ago

Owner: changed from Aymeric Augustin to nobody
Patch needs improvement: unset

I'm uploading a new patch with the following changes:

  • updated patch against latest revision of trunk
  • kept cleaned_data when a modelform fails a uniqueness check or a date uniqueness check (and I'm not totally confident on these changes)
  • replaced a hasattr(form, 'cleaned_data') with form.is_valid() in the formtools tests
  • updated docs/ref/forms/validation.txt to account for this change
  • rephrased the docs slightly

by Aymeric Augustin, 12 years ago

Attachment: 5524-new-3.diff added

comment:21 by Thomas Güttler, 12 years ago

I applied 5524-new-3.diff and all of my 296 unittests passed. I read the patch and think it can be committed. But the release notes should be updated, too.

comment:22 by Jannis Leidel, 12 years ago

Triage Stage: AcceptedReady for checkin

comment:23 by Simon Charette, 12 years ago

Cc: charette.s@… added
Patch needs improvement: set
Triage Stage: Ready for checkinAccepted

The documentation should be changed to reflect that it has been changed in 1.5 and not 1.4

comment:24 by Simon Charette, 12 years ago

Owner: changed from nobody to Simon Charette

I'll update the patch.

by Simon Charette, 12 years ago

Attachment: 5524-new-4.patch added

Doc update and unicode_literals related changes

comment:25 by Simon Charette, 12 years ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

Since the patch was originally written by a core developer and marked as RFC by another one and it's really just a doc update to reflect the changes are taking effect in 1.5 I'm moving back to RFC. Feel free to move back to accepted. All tests still pass on Python 2.7.3rc1 sqlite3.

comment:26 by Claude Paroz <claude@…>, 12 years ago

Resolution: fixed
Status: newclosed

In [121fd109de09ece4e263e508f9034df9b583da46]:

Fixed #5524 -- Do not remove cleaned_data when a form fails validation

cleaned_data is no longer deleted when form validation fails but only
contains the data that did validate.
Thanks to the various contributors to this patch (see ticket).

Note: See TracTickets for help on using tickets.
Back to Top