Django

Code

Ticket #3148: revised.add.getter.setter.patch

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

add documentation, fix minor whitespace issue, supercede previous patch

  • 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       
  • docs/model-api.txt

    old new  
    548548processing using the object's ``AddManipulator`` or ``ChangeManipulator`` 
    549549classes. Default is ``True``. 
    550550 
     551``getter`` 
     552~~~~~~~~~~ 
     553 
     554A string indicating a method of the class to call when you try 
     555to retrieve the value of the field. The method will be passed as its 
     556only argument the current "underlying value" of the field (as received 
     557from the database, object construction, or previous setting 
     558operation), and the return value of that method is what the user 
     559receives.  
     560 
    551561``help_text`` 
    552562~~~~~~~~~~~~~ 
    553563 
     
    581591Don't use this for a field unless it's a ``ForeignKey`` or has ``choices`` 
    582592set. 
    583593 
     594``setter`` 
     595~~~~~~~~~~ 
     596 
     597A string indicating a method of the class to call when you try to set 
     598the value of the field. The method will be passed as its only argument 
     599the value the user is setting the field to, and the return value is 
     600what will actually be set in the database.  
     601 
     602The setter will not be run when the object is created,  either by 
     603database retrieval or construction. 
     604 
    584605``unique`` 
    585606~~~~~~~~~~ 
    586607