Django

Code

Ticket #4102: 4102.3.patch

File 4102.3.patch, 4.3 kB (added by das, 1 year ago)

Patch against django 1.0. Removed duplicate test.

  • django/db/models/base.py

    old new  
    191191class Model(object): 
    192192    __metaclass__ = ModelBase 
    193193 
     194    def __setattr__(self, name, value): 
     195        if name not in self._modified_attrs: 
     196            if not hasattr(self, name) or value != getattr(self, name): 
     197                self._modified_attrs.append(name) 
     198        super(Model, self).__setattr__(name, value) 
     199 
     200    def _reset_modified_attrs(self): 
     201        self.__dict__['_modified_attrs'] = [] 
     202 
    194203    def __init__(self, *args, **kwargs): 
     204        self._reset_modified_attrs() 
    195205        signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs) 
    196206 
    197207        # There is a rather weird disparity here; if kwargs, it's set, then args 
    198         # overrides it. It should be one or the other; don't duplicate the work 
     208        # overrides it. It should be one or the other; don't duplicate the work. 
    199209        # The reason for the kwargs check is that standard iterator passes in by 
    200210        # args, and instantiation for iteration is 33% faster. 
    201211        args_len = len(args) 
     
    342352                setattr(self, field.attname, self._get_pk_val(parent._meta)) 
    343353 
    344354        non_pks = [f for f in meta.local_fields if not f.primary_key] 
     355        modified_attrs = self._modified_attrs 
     356        non_pks = [f for f in non_pks if (f.name in modified_attrs or f.attname in modified_attrs)] 
     357        self._reset_modified_attrs() 
    345358 
    346359        # First, try an UPDATE. If that doesn't update anything, do an INSERT. 
    347360        pk_val = self._get_pk_val(meta) 
  • django/db/models/query.py

    old new  
    272272                        max_depth, requested=requested) 
    273273            else: 
    274274                obj = self.model(*row[index_start:]) 
     275                # Models keep a track of modified attrs to choose which 
     276                # fields to save. Since we're just pulling from the 
     277                # database, nothing has changed yet. 
     278                obj._reset_modified_attrs() 
    275279            for i, k in enumerate(extra_select): 
    276280                setattr(obj, k, row[i]) 
    277281            yield obj 
  • tests/modeltests/update_fields/models.py

    old new  
     1""" 
     2#. Save only modified fields on update 
     3""" 
     4from django.db import models 
     5 
     6class Article(models.Model): 
     7    headline = models.CharField(max_length=100, default='Default headline') 
     8    body = models.TextField() 
     9    pub_date = models.DateTimeField() 
     10 
     11    class Meta: 
     12        ordering = ('pub_date','headline') 
     13 
     14    def __str__(self): 
     15        return self.headline 
     16 
     17__test__ = {'API_TESTS':""" 
     18# Create a couple of Articles. 
     19>>> from datetime import datetime 
     20>>> a = Article(headline='Article 1', body='Body 1', pub_date=datetime(2007, 5, 5)) 
     21>>> a.save() 
     22 
     23# Change headline and body on different instances, then save both to verify 
     24# that each only updated the modified field. 
     25>>> a1 = Article.objects.get(pk=a.id) 
     26>>> a2 = Article.objects.get(pk=a.id) 
     27>>> a1.headline = 'Changed article 1' 
     28>>> a2.body = 'Changed body 1' 
     29>>> a1.save() 
     30>>> a2.save() 
     31>>> a3 = Article.objects.get(pk=a.id) 
     32>>> a3.headline 
     33u'Changed article 1' 
     34>>> a3.body 
     35u'Changed body 1' 
     36 
     37# Fields entered at instantiation of a model which will already exists should be 
     38# saved as well. 
     39>>> a = Article(id=a.id, headline='Reset article 1', body='Reset body 1', pub_date=datetime(2007, 5, 5)) 
     40>>> a.save() 
     41>>> a3 = Article.objects.get(pk=a.id) 
     42>>> a3.headline 
     43u'Reset article 1' 
     44>>> a3.body 
     45u'Reset body 1' 
     46 
     47# If the value doesn't change, it won't be marked as modified -- otherwise user 
     48# input like forms/etc is going to mark everything modified regardless. 
     49>>> a1 = Article.objects.get(pk=a.id) 
     50>>> a2 = Article.objects.get(pk=a.id) 
     51>>> a1.headline = 'Changed article 2' 
     52>>> a2.headline = a2.headline 
     53>>> a2.body = 'Changed body 2' 
     54>>> a1.save() 
     55>>> a2.save() 
     56>>> a3 = Article.objects.get(pk=a.id) 
     57>>> a3.headline 
     58u'Changed article 2' 
     59>>> a3.body 
     60u'Changed body 2' 
     61"""}