Dear Django users,

This is my first post on this ML, please excuse me if my question sounds 
weird.

My question is about the separation of roles between Widget and Field, in 
the context of eg. a serialization/deserialization of a list of values 
using JSON. It concerns especially the "Field.to_python", "Field.clean", 
"Field.bound_data", "Widget.render" and "Widget.value_from_datadict".

More concretely, I want to manipulate a list of DB entries in a Hidden 
field of a form, use some Javascript to populate the Hidden field and send 
it back to the form. Until today, I was using 

* the to_python method to deserialize the JSON string that was arriving to 
the field, and to transform it to a proper list of objects,
* the prepare_value to initialize the JSON string to put into the Hidden 
input (non documented, this is the only way I found)

The problem was, after an erroneous form has been sent, the prepare_value 
was taking as input a non-deserialized JSON string. Example:

1* initial rendered input: <input id="json-for-list-authors" 
name="existing_authors" value="{&quot;authors&quot;: []}" type="hidden">
2* after populating it with Javascript: <input id="json-for-list-authors" 
name="existing_authors" value="{&quot;authors&quot;: 
[&quot;jean-philippe.XXX&quot;]}" type="hidden">
3* sending the form with error renders the hidden input like this <input 
id="json-for-list-authors" name="existing_authors" 
value="{&quot;authors&quot;: &quot;{&quot;authors&quot;: 
[&quot;jean-philippe.vert&quot;]&quot;}" type="hidden"> (more or less some 
&quot;). 

It is then calling prepare_value on a JSON string received from 2/, and 
embedding a JSON into a JSON. 

After that, I thought the right approach would be to override a specific 
Widget's "render" and "value_from_datadict": the transformation of the 
python list into a JSON is done in render, and the deserialization is done 
in value_from_datadict. I find that approach cleaner and neat:

* it solves my problem with having a proper serialization/deserialization 
in case of errors
* the Field.to_python does not concentrate in the actual representation of 
the data: it receives a list of values, regardless of the way I am 
serializing the data, and it concentrates on the logic of transforming the 
list or elements of this list into adequate python objects (eg. retrieving 
entries of the DB, removing duplicates)
* the widget is agnostic to logical errors (eg. entry does not exist in the 
DB): it concentrates on serializing/deserializing whatever object has been 
passed to it, and can concentrate of malformed string/data error (eg. 
unable to deserialize)
* there is no need to call a hidden API prepare_value

However, there are other problems:
* there is no proper way to unit test that: assertFieldOutput tests the 
result of the "clean", which is indirectly calling "to_python". 
  * In the case of list of values, since those are not hashable, they 
cannot be used as keys for the "valid"/"invalid" parameters of 
assertFieldOutput
  * Some weird design issues appear: if for instance I would like to remove 
the duplicates in the "to_python", the removal of the duplicates will not 
affect the Widget, and the latter may render the duplicate values again in 
the form
* I would like to test the Widget (illformed strings) and the Field 
(inexisting users, duplicate removal) separately

The other option would be to use the BoundField.data or BoundField.value() 
to put the deserialization  there. But then 
* I would not be able to test it properly until I have a form. 
* 

To put everything in a nutshell, my question is: what is the best way to 
approach this kind of design? What are the responsibilities of those 
two/three entities?

Thanks,
Raffi

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/51ba6378-b3c7-4a93-b17d-04dd2079c21c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to