Nick Heiner
Nick Heiner

Reputation: 122432

How do I convert a django form input to python data?

I have a widget that allows user to enter data for a model field. The data in the form can't be directly converted to Python - it requires some coercion. Where do I put this code? Is the widget responsible for translating its post data to a python value? The field itself?

I thought that maybe value_from_datadict() would be correct, but now it looks like that serves a different purpose.

(I'm using the form in the admin interface, if it makes any difference.)

Update @AndiDog: I'm incredulous that to_python is what I want. From the Django source:

135     def to_python(self, value):
136         """
137         Converts the input value into the expected Python data type, raising
138         django.core.exceptions.ValidationError if the data can't be converted.
139         Returns the converted value. Subclasses should override this.
140         """
141         return value

You're saying that this is called with value being the POST data from the form? I put in a print statement, and value is None when submitting the form, even though the input has data.

Update 2: Actually, it looks like value_from_datadict is the way to go. It has a dictionary from names of inputs to their values.

Upvotes: 0

Views: 3145

Answers (2)

user257111
user257111

Reputation:

Quoting the django source for value_from_datadict():

Given a dictionary of data and this widget's name, returns the value of this widget. Returns None if it's not provided.

It isn't actually clear what this function is for. Its purpose is to return the value for that widget based on the entire dictionary of posted data; namely, it looks through that data, works out given an instance of the widget which data belongs to it and returns that.

I checked this by crashing my own custom widget with a carefully placed raise exception.

File "/usr/lib/python2.7/site-packages/django/forms/forms.py" in is_valid
  121.         return self.is_bound and not bool(self.errors)
File "/usr/lib/python2.7/site-packages/django/forms/forms.py" in _get_errors
  112.             self.full_clean()
File "/usr/lib/python2.7/site-packages/django/forms/forms.py" in full_clean
  267.         self._clean_fields()
File "/usr/lib/python2.7/site-packages/django/forms/forms.py" in _clean_fields
  278.             value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))

Do you want to validate here? I did using a multiwidget subclass, but that's not necessarily the best approach. My method re-constructs the date from the dictionary, attempts to create a python date object from it. If this succeeds, it converts it to a string and returns that which is valid; if it doesn't it returns None, which fails validation in the database for the DateField() type, which is what I wanted to happen.

Whether your widget wants that to happen that way depends on what you're doing. I'm not convinced its the most elegant solution so I'm going to open up my own question...

Refs:

Upvotes: 1

gruszczy
gruszczy

Reputation: 42168

The clean and clean_<field> methods in Form subclass are responsible for this. Here are the docs about validation (and cleaning): http://docs.djangoproject.com/en/1.2/ref/forms/validation/

Upvotes: 1

Related Questions