I have a DecimalField in a model. In the ModelForm associated with the model, I am trying to customize the field to allow simple math (just division) before processing.
For example, I want to allow 1/2 to be typed into the form and then have 0.50000 saved to the database.
In my forms:
def clean_qty(self):
data = self.cleaned_data['qty']
if type(data) == int or type(data) ==float: #need to catch decimal too?
return data
elif re.match("^(\d+)/(\d+)$", str(data)):
# do math on, return value
else:
raise forms.ValidationError("Enter number or fraction")
When I submit the form with 1/4 I get ‘Enter a number.’ And using 1 raises ‘Enter number or fraction’ as my validation error, neither of which are options from my clean method.
I think it’s being raised by the to_python method for the DecimalField? Can I customize the to_python field without having to define a custom form field type or model field type?
Or what else can I do to allow this behavoir?
Update for solution:
I ended up changing the DecimalField to a FloatField. My inexperience with the Decimal class made it surprisingly hard, and there was no reason I needed a decimal over a float. Also, as suggested, I used a CharField in the Form.
here’s the validation:
class SomeForm(ModelForm):
qty = forms.CharField(max_length=30)
def clean_qty(self):
data = self.cleaned_data['qty']
try:
float_data = float(data)
return float_data
## this is for integers or floats with no attempted division
except:
try:
match =re.match("(?P<num>([0-9.]+))/(?P<den>([0-9.]+))", str(data))
num = float(match.groupdict()['num'])
den = float(match.groupdict()['den'])
result = num/den
return result
except:
raise forms.ValidationError("Enter a number or fraction")
I’m really using/abusing the try-except syntax to allow for sloppier regex. For example ‘.’ and ‘1.2.3’ are allowed by the regex for the numerator and denominator, but they get caught when calling float(). So it’s quite hackish (in my mind) but I thought I’d post it for others.
Create a custom form with a text field and do the conversion to decimal when the form is submitted.