Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Django 1.4, do Form.has_changed() and Form.changed_data, which are undocumented, work as expected?

Tags:

From the source code, you can see that Django 1.4's Form class has a has_changed() method and changed_data property which seem rather useful, but are undocumented. My question is: do these work as expected, i.e.:

  • In Form.clean(), Form.has_changed() returns True if any any form data has changed, otherwise False
  • In Form.clean(), Form.changed_data is a list of field names whose values have changed.

If so, are there any specific reasons not to use them, apart from the usual caveats/dangers about using undocumented features (i.e. subject to change, not supported, etc.)?

NOTE 1: For these to work with custom widgets, those widgets need to have a _has_changed() method, which is defined for built in widgets.

NOTE 2: Interestingly, the documentation does include an offhand mention of the Formset.has_changed() method, but not of Form.has_changed().

like image 452
Ghopper21 Avatar asked Jul 29 '12 16:07

Ghopper21


People also ask

What is form Is_valid () in Django?

The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.

Which function of Django's form class will render a form's fields as a series of P tags?

{{ form. as_p }} – Render Django Forms as paragraph.

What method can you use to check if form data has changed when using a form instance?

Use the has_changed() method on your Form when you need to check if the form data has been changed from the initial data. has_changed() will be True if the data from request.

What is form cleaned_data?

form. cleaned_data returns a dictionary of validated form input fields and their values, where string primary keys are returned as objects. form. data returns a dictionary of un-validated form input fields and their values in string format (i.e. not objects).


1 Answers

After studying the Django source further, with helpful hints from Florian's answer, I can report that has_changed and changed_data do work as described in my question as long as the form has a way to get the initial data to compare the new data against.

So the question is, how does a form created from POST data know what the initial values of the GET form were? The short answer is it doesn't -- unless you tell it somehow. There are two ways to tell it:

  1. Via the initial keyword argument to the form and/or the initial keyword arguments to the fields, exactly the same way you tell the GET form the initial values. NOTE: If you do this, it's up to you to make sure you use the same values for your GET and POST forms. This is the only truly reliable way to do it, since you directly control what the initial values are.

  2. You let Django do the work of remembering the initial values from your GET by setting the show_hidden_initial keyword argument to True for each applicable field. For these fields, Django renders a hidden input element with the initial value into the GET form's HTML. Later, when you call has_changed or changed_data on the POST form, for any field with show_hidden_initial as True Django will automatically get the initial values from the hidden input elements in the POST data (superseding any initial values from initial form or field arguments). NOTE: as with anything relying on POST data, this approach is ultimately unreliable, since the values for the hidden inputs could still be changed despite being hidden.

like image 72
Ghopper21 Avatar answered Sep 18 '22 14:09

Ghopper21