Ticket #3148: add.getter.setter.patch

File add.getter.setter.patch, 5.0 KB (added by jerf@…, 13 years ago)

patch to add getters and setters

  • django/db/models/base.py

     
    9090
    9191    def __init__(self, *args, **kwargs):
    9292        dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
     93        self._django_initializing = True
    9394        for f in self._meta.fields:
    9495            if isinstance(f.rel, ManyToOneRel):
    9596                try:
     
    127128            setattr(self, self._meta.fields[i].attname, arg)
    128129        dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
    129130
     131        del self._django_initializing
     132
    130133    def add_to_class(cls, name, value):
    131134        if name == 'Admin':
    132135            assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
  • django/db/models/fields/__init__.py

     
    7070        core=False, rel=None, default=NOT_PROVIDED, editable=True,
    7171        prepopulate_from=None, unique_for_date=None, unique_for_month=None,
    7272        unique_for_year=None, validator_list=None, choices=None, radio_admin=None,
    73         help_text='', db_column=None):
     73        help_text='', db_column=None,getter=None,setter=None):
    7474        self.name = name
    7575        self.verbose_name = verbose_name
    7676        self.primary_key = primary_key
     
    8686        self.radio_admin = radio_admin
    8787        self.help_text = help_text
    8888        self.db_column = db_column
     89        self.getter = getter
     90        self.setter = setter
    8991
    9092        # Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
    9193        self.db_index = db_index
     
    139141        cls._meta.add_field(self)
    140142        if self.choices:
    141143            setattr(cls, 'get_%s_display' % self.name, curry(cls._get_FIELD_display, field=self))
     144        if self.setter is not None or self.getter is not None:
     145            self.create_property_on_class(cls)
    142146
     147    def create_property_on_class(self, cls):
     148        """create the property to support setters and getters"""
     149        name = self.name
     150        field_att = "_%s" % name
     151
     152        if self.getter:
     153            getter_name = self.getter
     154            def get_func(self):
     155                value = getattr(self, field_att)
     156                return getattr(self, getter_name)(value)
     157        else:
     158            def get_func(self):
     159                return getattr(self, field_att)
     160
     161        if self.setter:
     162            setter_name = self.setter
     163            def set_func(self, value):
     164                if hasattr(self, '_django_initializing'):
     165                    setattr(self, field_att, value)
     166                else:
     167                    setattr(self, field_att,
     168                            getattr(self, setter_name)(value))
     169        else:
     170            def set_func(self, value):
     171                setattr(self, field_att, value)
     172
     173        setattr(cls, name, property(get_func, set_func))
     174
    143175    def get_attname(self):
    144176        return self.name
    145177
  • tests/modeltests/getters_setters/models.py

     
     1"""
     2Test the 'getter' and 'setter' functionality on fields.
     3
     4This tests a field with a setter, a field with a getter, and a field
     5with both. Since the getter/setter implementation is at the Field
     6level, and I've verified that all Field objects pass through the code
     7that constructs these properties, I believe it would be redundent to
     8test all the Field Types individually.
     9
     10Doc note: Setters
     11"""
     12
     13from django.db import models
     14
     15class GetSet(models.Model):
     16    has_getter = models.CharField(maxlength=20, getter='simple_getter')
     17    has_setter = models.CharField(maxlength=20, setter='simple_setter')
     18    has_both = models.CharField(maxlength=20, getter='simple_getter',
     19                                setter='updater')
     20    updated_length_field = models.IntegerField(default=0)
     21
     22    def simple_getter(self, value):
     23        return value + "_getter"
     24    def simple_setter(self, value):
     25        return value + "_setter"
     26    def updater(self, value):
     27        self.updated_length_field = len(value)
     28        return value
     29
     30
     31__test__ = {'API_TESTS':"""
     32>>> a = GetSet(has_getter='x', has_setter='y', has_both='z')
     33>>> a.has_getter
     34'x_getter'
     35>>> a.has_setter
     36'y'
     37>>> a.has_both
     38'z_getter'
     39
     40# Setter has not run yet
     41
     42>>> a.updated_length_field
     430
     44>>> a.has_both = 'abcd'
     45>>> a.updated_length_field
     464
     47>>> a.save()
     48>>> a_id = a.id
     49>>> del a
     50>>> a = GetSet.objects.get(id=a_id)
     51>>> a.updated_length_field
     524
     53"""}
     54                                 
     55     
Back to Top