Django

Code

Changeset 5658

Show
Ignore:
Timestamp:
07/12/07 02:45:35 (2 years ago)
Author:
russellm
Message:

Fixed #4459 -- Added 'raw' argument to save method, to override any pre-save processing, and modified serializers to use a raw-save. This enables serialization of DateFields? with auto_now/auto_now_add. Also modified serializers to invoke save() directly on the model baseclass, to avoid any (potentially order-dependent, data modifying) behavior in a custom save() method.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/serializers/base.py

    r5609 r5658  
    159159 
    160160    def save(self, save_m2m=True): 
    161         self.object.save() 
     161        # Call save on the Model baseclass directly. This bypasses any  
     162        # model-defined save. The save is also forced to be raw. 
     163        # This ensures that the data that is deserialized is literally  
     164        # what came from the file, not post-processed by pre_save/save 
     165        # methods. 
     166        models.Model.save(self.object, raw=True) 
    162167        if self.m2m_data and save_m2m: 
    163168            for accessor_name, object_list in self.m2m_data.items(): 
  • django/trunk/django/db/models/base.py

    r5609 r5658  
    202202    _prepare = classmethod(_prepare) 
    203203 
    204     def save(self): 
     204    def save(self, raw=False): 
    205205        dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self) 
    206206 
     
    219219            # If it does already exist, do an UPDATE. 
    220220            if cursor.fetchone()[0] > 0: 
    221                 db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] 
     221                db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, False)) for f in non_pks] 
    222222                if db_values: 
    223223                    cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ 
     
    230230        if not pk_set or not record_exists: 
    231231            field_names = [backend.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)] 
    232             db_values = [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)] 
     232            db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)] 
    233233            # If the PK has been manually set, respect that. 
    234234            if pk_set: 
    235235                field_names += [f.column for f in self._meta.fields if isinstance(f, AutoField)] 
    236                 db_values += [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)] 
     236                db_values += [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)] 
    237237            placeholders = ['%s'] * len(field_names) 
    238238            if self._meta.order_with_respect_to: 
  • django/trunk/docs/db-api.txt

    r5609 r5658  
    118118Explicitly specifying auto-primary-key values is mostly useful for bulk-saving 
    119119objects, when you're confident you won't have primary-key collision. 
     120 
     121Raw saves 
     122--------- 
     123 
     124When you save an Django object, some pre-processing will occur on the the data 
     125that is in the object. For example, if your model has a ``DateField`` with  
     126``auto_now=True`` set, the pre-save phase will alter the data in the object  
     127to ensure that the date field contains the current date stamp. 
     128 
     129Although these automated changes can be very useful, there will be times when 
     130you just want to save the data as-is. In these cases, you can invoke a *Raw Save*  
     131by passing ``raw=True`` as an argument to the ``save()`` method:: 
     132 
     133    b4.save(raw=True)  # Saves object, but does no pre-processing 
     134 
     135A raw save saves all the data in your object, but performs no pre-save processing  
     136on the data in the object.  
    120137 
    121138Saving changes to objects 
  • django/trunk/tests/regressiontests/serializers_regress/models.py

    r5409 r5658  
    210210    field2 = models.CharField(maxlength=10) 
    211211    field3 = models.CharField(maxlength=10) 
     212 
     213# Tests for handling fields with pre_save functions, or 
     214# models with save functions that modify data 
     215class AutoNowDateTimeData(models.Model): 
     216    data = models.DateTimeField(null=True, auto_now=True) 
     217 
     218class ModifyingSaveData(models.Model): 
     219    data = models.IntegerField(null=True) 
     220 
     221    def save(self): 
     222        "A save method that modifies the data in the object" 
     223        self.data = 666 
     224        super(ModifyingSaveData, self).save(raw) 
  • django/trunk/tests/regressiontests/serializers_regress/tests.py

    r5609 r5658  
    2525 
    2626# A set of functions that can be used to recreate 
    27 # test data objects of various kinds 
     27# test data objects of various kinds. 
     28# The save method is a raw base model save, to make 
     29# sure that the data in the database matches the 
     30# exact test case. 
    2831def data_create(pk, klass, data): 
    2932    instance = klass(id=pk) 
    3033    instance.data = data 
    31     instance.save(
     34    models.Model.save(instance, raw=True
    3235    return instance 
    3336 
     
    3538    instance = klass(id=pk) 
    3639    instance.data = data[0] 
    37     instance.save(
     40    models.Model.save(instance, raw=True
    3841    for tag in data[1:]: 
    3942        instance.tags.create(data=tag) 
     
    4346    instance = klass(id=pk) 
    4447    setattr(instance, 'data_id', data) 
    45     instance.save(
     48    models.Model.save(instance, raw=True
    4649    return instance 
    4750 
    4851def m2m_create(pk, klass, data): 
    4952    instance = klass(id=pk) 
    50     instance.save(
     53    models.Model.save(instance, raw=True
    5154    instance.data = data 
    5255    return instance 
     
    5558    instance = klass() 
    5659    instance.data_id = data 
    57     instance.save(
     60    models.Model.save(instance, raw=True
    5861    return instance 
    5962 
     
    6164    instance = klass() 
    6265    instance.data = data 
    63     instance.save(
     66    models.Model.save(instance, raw=True
    6467    return instance 
    6568 
     
    250253    (pk_obj, 780, USStatePKData, "MA"), 
    251254#     (pk_obj, 790, XMLPKData, "<foo></foo>"), 
     255 
     256    (data_obj, 800, AutoNowDateTimeData, datetime.datetime(2006,6,16,10,42,37)), 
     257    (data_obj, 810, ModifyingSaveData, 42), 
    252258] 
    253259 
     
    304310 
    305311    obj = ComplexModel(field1='first',field2='second',field3='third') 
    306     obj.save(
     312    obj.save(raw=True
    307313 
    308314    # Serialize then deserialize the test database 
     
    320326 
    321327    obj = ComplexModel(field1='first',field2='second',field3='third') 
    322     obj.save(
     328    obj.save(raw=True
    323329 
    324330    # Serialize the test database to a stream