9

I'm wondering if it is possible to override the default value of a field when it is returned. Say I had a model:

class ModelA(models.Model)
    name = models.CharField(max_length=30)

Is there any way that calling

modela_instance.name 

can return a modified value, for example name + " foo", but have the code that appends foo run by default within the model itself, so all I would need to do is call name to get the appended value?

I should elaborate and say that what I'm actually hoping to do is have a method within the model:

def get_name(self):
     return self.name + " foo"

or similar, and just want that get_name method to override the call to the field "name".

Brad Fox
  • 685
  • 6
  • 19
PT114
  • 931
  • 3
  • 10
  • 18

2 Answers2

17

Yes, you can use properties to do this

class ModelA(models.Model)
    _name = models.CharField(...)

    def set_name(self, val):
        self._name = "%s - foo" % val

    def get_name(self):
        return self._name

    name = property(get_name, set_name)
Timmy O'Mahony
  • 53,000
  • 18
  • 155
  • 177
  • Thanks, I ended up using a slightly different method, now I'm using a read-only property that returns my method instead of the name field itself. – PT114 May 01 '12 at 08:56
  • See also http://stackoverflow.com/questions/3757951/changing-the-behaviour-of-a-django-model-with-getattr. Basically, either use properties or `__getattr__` (with care!). – James Rutherford May 01 '12 at 22:25
1

Why would you want to do this? Not sure, but I don't think this is a good idea.. However, you can use for example the unicode method:

class ModelA(models.Model)
    name = models.CharField(max_length=30)

    def __unicode__(self):
        return "%s : foo" % self.name

and when calling just use:

modela_instance

or when foo has to be dynamic:

class ModelA(models.Model)
    name = models.CharField(max_length=30)

    def __unicode__(self):
        return "%s : %s" % (self.name, self.make_foo())

    def make_foo(self):
        return "foo"

or define your own method:

class ModelA(models.Model)
    name = models.CharField(max_length=30)

    def alt_name(self):
        return "%s : foo" % self.name  
ohrstrom
  • 2,890
  • 2
  • 20
  • 34
  • The name of my model consists of a string containing "tags" such as { ModelB: description }. The tags relate to attributes from a different model. So { ModelB: description } represents the description attribute of another model "B". I have a method that can translate these tags, but there are lots of places where name is called and it would be impractical to go and change them all, and if the description attribute of modelb contained a t ag from modelc, it would not get translated because the { ModelB: description } just returns the string tags of whatever the modelb description was holding. – PT114 Apr 30 '12 at 12:03