Django

Code

Ticket #3148: add.getter.setter.patch

File add.getter.setter.patch, 5.0 kB (added by jerf@jerf.org, 2 years ago)

patch to add getters and setters

  • django/db/models/base.py

    old new  
    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

    old new  
    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

    old new  
     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