0

I'm using django-composite-field to create a currency field that includes both a dollar_value and a dollar_year (i.e., "$200 in 2008 dollars").

I have the following models in a Django app:

#models.py
from composite_field import CompositeField

class DollarField(CompositeField):
    """ Composite field to associate dollar values with dollar-years."""
    dollar_value = models.DecimalField(max_digits=8, decimal_places=2)
    dollar_year = models.PositiveSmallIntegerField(
        blank=False,
        null=False, 
        validators=[
            MinValueValidator(1980),
            MaxValueValidator(2020)])

    def __unicode__(self):
        return self.dollar_year+"$: $"+self.dollar_value # "2012$: $149.95"

class ProductStandard(models.Model):
    product = models.ForeignKey(Product)
    standard_level = models.ForeignKey(StandardLevel)
    price = DollarField()

When I access the price attribute of a ProductStandard instance, I expect to see a formatted string like this: 2012$: $199.99. Instead, I see DollarField(dollar_value=Decimal('199.99'), dollar_year=2012), which is the return value of the CompositeField __repr__ method. But since I've sublassed CompositeField and added my own __unicode__ method, shouldn't Django overwrite? Or am I misunderstanding something?

I'm using Django 1.5.4 with Python 2.7.3 and django-composite-field 0.1.

numbers are fun
  • 423
  • 1
  • 7
  • 12
  • Did you try returning a `unicode` ? `return u'%s$:$%s' %(self.dollar_year, self.dollar_value)` – karthikr Oct 30 '13 at 21:47
  • `__unicode__` is for returning a Unicode human-readable representation (similar to `__str__`). `__repr__` has other uses: http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python – Peter DeGlopper Oct 30 '13 at 21:48

1 Answers1

0

The __repr__ you are seeing is actually not a __repr__ of a CompositeField, but of it's Proxy (refer to composite_field/base.py, line 104). So you would have to provide your own proxy, and override the __repr__ method there, like so:

class DollarField(CompositeField):
    """ Composite field to associate dollar values with dollar-years."""
    dollar_value = models.DecimalField(max_digits=8, decimal_places=2)
    dollar_year = models.PositiveSmallIntegerField(
        blank=False,
        null=False, 
        validators=[
            MinValueValidator(1980),
            MaxValueValidator(2020)])

    def get_proxy(self, model):
        return DollarField.Proxy(self, model)

    class Proxy(CompositeField.Proxy):
        def __repr__(self):
            return "%s$: $%s" % (self.dollar_year, self.dollar_value) # "2012$: $149.95"

of course, if you would like to leave __repr__ as it is, you can override __unicode__ instead of __repr__, like you did. The difference is that:

print(mymodel.price)

would call the __repr__, while

print(unicode(mymodel.price))

would call the __unicode__ method.

toudi
  • 804
  • 7
  • 11