djangodjango-modelsdjango-validation

Django how to write PositiveDecimalField


I'd like to write PositiveDecimalField.

Here is my code:

from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _

from django.db.models import DecimalField
from decimal import *

def validate_positive_decimal(value):
    try:
        decimal_value = Decimal(value)

        if decimal_value < 0:
            raise ValidationError(_('{val} should be a positive decimal number'.format(val = decimal_value)), code='negative decimal')

    except (ValueError, TypeError):
        raise ValidationError(_('Enter a valid decimal or integer value'), code='invalid decimal')


class PositiveDecimalField(DecimalField):
    default_validators = [validate_positive_decimal]

    def __init__(self, *args, **kwargs):

        super(DecimalField, self).__init__(*args, **kwargs)

    def validators(self):
        return super(PositiveDecimalField, self).validators + [validate_positive_decimal]

Then, in my models.py

class Service(models.Model):
    service_rate = PositiveDecimalField(max_digits = 6, decimal_places=2, blank=True) # e.g. 125.25 for water (demo phase), -125.25 should not be accepted

The error I get is this:

super(DecimalField, self).__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'max_digits'

I looked at the source code for Django's DecimalField in the docs. I also tried to just pass the validator, validate_positive_decimal, to the DecimalField, but it does not validate against it.

What do I need to do here?


Solution

  • Your call to super() in __init__ should be

    super(PositiveDecimalField, self).__init__(*args, **kwargs)
    

    instead of

    super(DecimalField, self).__init__(*args, **kwargs)