Paulo
Paulo

Reputation: 7342

django smart decimal field

I am creating an app that basically stores shoe sizes, along with other information. I have been using the Django Decimal field to store the sizes, however the decimal field stores sizes like 10 as 10.0, so my question is, is there a way to make or if already exists a field that when provided an int ( 10 ) it stores the value as int and when provided a decimal ( 10.5 ) then stores it as decimal ?

Upvotes: 1

Views: 1292

Answers (3)

fero
fero

Reputation: 528

I adopted this solution:

  1. Create a custom Django model Field
  2. Which return a custom decimal.Decimal instance that implements the trick in __unicode__ because this is just a matter of representation

Here is the snippet:

class PyPrettyDecimal(decimal.Decimal): 

    def __unicode__(self): 
        # TODO: to improve with decimal properties ?!? 
        mod = self - int(self) 
        if not mod: 
            rv = int(self) 
        else: 
            rv = self.quantize(mod.normalize()) 
        return unicode(rv) 

class PrettyDecimalField(models.DecimalField): 

    __metaclass__ = models.SubfieldBase 

    def to_python(self, value): 
        if value is None: 
            return value 
        try: 
            return PyPrettyDecimal(value) 
        except decimal.InvalidOperation: 
            raise exceptions.ValidationError(self.error_messages['invalid']) 

Upvotes: 1

Anentropic
Anentropic

Reputation: 33823

TBH for a shoe size field I'd probably use a CharField with choices attribute - there are a relatively small number of valid shoe sizes and that way you can format them how you want to.

If it's part of a Product model that may contain things other than shoes, a CharField for 'size' is useful because you can also store values like 'M', 'L', 'XXL' etc.

You won't need to do any math on the shoe sizes so there's no point to using a DecimalField.

For that reason it doesn't really matter what is saved in the db, only what you display and @j_syk had a couple of good alternative suggestions along those lines in the comments.

Upvotes: 3

jro
jro

Reputation: 9474

Doesn't simply casting it to a string work for you? You can keep your storage as-is, but format the number to your liking when presenting your data.

>>> str(Decimal(10))
'10'
>>> str(Decimal(10.5))
'10.5'
>>> str(Decimal(10.0))
'10'

Upvotes: 2

Related Questions