Code

Ticket #4102: 4102-dirty-set.8.patch

File 4102-dirty-set.8.patch, 8.1 KB (added by Collin Grady <cgrady@…>, 7 years ago)

fixed another value/name mixup, optimized a few operations

  • django/db/models/base.py

     
    1919import sys 
    2020import os 
    2121 
     22try: 
     23    set 
     24except NameError: 
     25    from sets import Set as set   # Python 2.3 fallback 
     26 
    2227class ModelBase(type): 
    2328    "Metaclass for all models" 
    2429    def __new__(cls, name, bases, attrs): 
     
    97102    def __ne__(self, other): 
    98103        return not self.__eq__(other) 
    99104 
     105    def __setattr__(self, name, value): 
     106        if name != '_modified_attrs' and (not hasattr(self, name) or 
     107                                          value != getattr(self, name)): 
     108            if hasattr(self, '_modified_attrs'): 
     109                if name not in self._modified_attrs:  
     110                    self._modified_attrs.add(name) 
     111            else: 
     112                self._modified_attrs = set((name,)) 
     113        super(Model, self).__setattr__(name, value) 
     114 
     115    def _reset_modified_attrs(self): 
     116        try: 
     117            self._modified_attrs.clear() 
     118        except AttributeError: 
     119            pass 
     120 
    100121    def __init__(self, *args, **kwargs): 
    101122        dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs) 
    102123 
    103124        # There is a rather weird disparity here; if kwargs, it's set, then args 
    104         # overrides it. It should be one or the other; don't duplicate the work 
     125        # overrides it. It should be one or the other; don't duplicate the work. 
    105126        # The reason for the kwargs check is that standard iterator passes in by 
    106         # args, and nstantiation for iteration is 33% faster. 
     127        # args, and instantiation for iteration is 33% faster. 
    107128        args_len = len(args) 
    108129        if args_len > len(self._meta.fields): 
    109130            # Daft, but matches old exception sans the err msg. 
     
    202223    _prepare = classmethod(_prepare) 
    203224 
    204225    def save(self, raw=False): 
     226        "Save model object to database, creating if doesn't exist, otherwise updating" 
    205227        dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self) 
    206228 
    207229        non_pks = [f for f in self._meta.fields if not f.primary_key] 
     230        if hasattr(self, '_modified_attrs'): 
     231            ma = self._modified_attrs 
     232            non_pks = [f for f in non_pks if (f.name in ma or f.attname in ma)] 
     233            self._reset_modified_attrs() 
    208234        cursor = connection.cursor() 
    209235 
    210236        qn = connection.ops.quote_name 
  • django/db/models/query.py

     
    204204                                                    index_start=0, max_depth=self._max_related_depth) 
    205205                else: 
    206206                    obj = self.model(*row[:index_end]) 
     207                    # Models keep a track of modified attrs to choose which 
     208                    # fields to save. Since we're just pulling from the 
     209                    # database, nothing has changed yet. 
     210                    obj._reset_modified_attrs() 
    207211                for i, k in enumerate(extra_select): 
    208212                    setattr(obj, k[0], row[index_end+i]) 
    209213                yield obj 
  • tests/modeltests/update_fields/models.py

     
     1""" 
     2#. Save only modified fields on update 
     3""" 
     4from django.db import models 
     5 
     6class Article(models.Model): 
     7    headline = models.CharField(maxlength=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 istantiation 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""" 
     48#. Save only modified fields on update 
     49""" 
     50from django.db import models 
     51 
     52class Article(models.Model): 
     53    headline = models.CharField(maxlength=100, default='Default headline') 
     54    body = models.TextField() 
     55    pub_date = models.DateTimeField() 
     56 
     57    class Meta: 
     58        ordering = ('pub_date','headline') 
     59 
     60    def __str__(self): 
     61        return self.headline 
     62 
     63__test__ = {'API_TESTS':""" 
     64# Create a couple of Articles. 
     65>>> from datetime import datetime 
     66>>> a = Article(headline='Article 1', body='Body 1', pub_date=datetime(2007, 5, 5)) 
     67>>> a.save() 
     68 
     69# Change headline and body on different instances, then save both to verify 
     70# that each only updated the modified field 
     71>>> a1 = Article.objects.get(pk=a.id) 
     72>>> a2 = Article.objects.get(pk=a.id) 
     73>>> a1.headline = 'Changed article 1' 
     74>>> a2.body = 'Changed body 1' 
     75>>> a1.save() 
     76>>> a2.save() 
     77>>> a3 = Article.objects.get(pk=a.id) 
     78>>> a3.headline 
     79'Changed article 1' 
     80>>> a3.body 
     81'Changed body 1' 
     82"""} 
     83""" 
     84#. Save only modified fields on update 
     85""" 
     86from django.db import models 
     87 
     88class Article(models.Model): 
     89    headline = models.CharField(maxlength=100, default='Default headline') 
     90    body = models.TextField() 
     91    pub_date = models.DateTimeField() 
     92 
     93    class Meta: 
     94        ordering = ('pub_date','headline') 
     95 
     96    def __str__(self): 
     97        return self.headline 
     98 
     99__test__ = {'API_TESTS':""" 
     100# Create a couple of Articles. 
     101>>> from datetime import datetime 
     102>>> a = Article(headline='Article 1', body='Body 1', pub_date=datetime(2007, 5, 5)) 
     103>>> a.save() 
     104 
     105# Change headline and body on different instances, then save both to verify 
     106# that each only updated the modified field. 
     107>>> a1 = Article.objects.get(pk=a.id) 
     108>>> a2 = Article.objects.get(pk=a.id) 
     109>>> a1.headline = 'Changed article 1' 
     110>>> a2.body = 'Changed body 1' 
     111>>> a1.save() 
     112>>> a2.save() 
     113>>> a3 = Article.objects.get(pk=a.id) 
     114>>> a3.headline 
     115u'Changed article 1' 
     116>>> a3.body 
     117u'Changed body 1' 
     118 
     119# Fields entered at istantiation of a model which will already exists should be 
     120# saved as well. 
     121>>> a = Article(id=a.id, headline='Reset article 1', body='Reset body 1', pub_date=datetime(2007, 5, 5)) 
     122>>> a.save() 
     123>>> a3 = Article.objects.get(pk=a.id) 
     124>>> a3.headline 
     125u'Reset article 1' 
     126>>> a3.body 
     127u'Reset body 1' 
     128"""} 
     129""" 
     130#. Save only modified fields on update 
     131""" 
     132from django.db import models 
     133 
     134class Article(models.Model): 
     135    headline = models.CharField(maxlength=100, default='Default headline') 
     136    body = models.TextField() 
     137    pub_date = models.DateTimeField() 
     138 
     139    class Meta: 
     140        ordering = ('pub_date','headline') 
     141 
     142    def __str__(self): 
     143        return self.headline 
     144 
     145__test__ = {'API_TESTS':""" 
     146# Create a couple of Articles. 
     147>>> from datetime import datetime 
     148>>> a = Article(headline='Article 1', body='Body 1', pub_date=datetime(2007, 5, 5)) 
     149>>> a.save() 
     150 
     151# Change headline and body on different instances, then save both to verify 
     152# that each only updated the modified field 
     153>>> a1 = Article.objects.get(pk=a.id) 
     154>>> a2 = Article.objects.get(pk=a.id) 
     155>>> a1.headline = 'Changed article 1' 
     156>>> a2.body = 'Changed body 1' 
     157>>> a1.save() 
     158>>> a2.save() 
     159>>> a3 = Article.objects.get(pk=a.id) 
     160>>> a3.headline 
     161'Changed article 1' 
     162>>> a3.body 
     163'Changed body 1' 
     164"""}