Ticket #4102: 4102.patch
File 4102.patch, 4.8 KB (added by , 17 years ago) |
---|
-
django/db/models/base.py
133 133 def __ne__(self, other): 134 134 return not self.__eq__(other) 135 135 136 def __setattr__(self, name, value): 137 if name not in self._modified_attrs: 138 if not hasattr(self, name) or value != getattr(self, name): 139 self._modified_attrs.append(name) 140 super(Model, self).__setattr__(name, value) 141 142 def _reset_modified_attrs(self): 143 self.__dict__['_modified_attrs'] = [] 144 136 145 def __init__(self, *args, **kwargs): 146 self._reset_modified_attrs() 137 147 dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs) 138 148 139 149 # There is a rather weird disparity here; if kwargs, it's set, then args 140 # overrides it. It should be one or the other; don't duplicate the work 150 # overrides it. It should be one or the other; don't duplicate the work. 141 151 # The reason for the kwargs check is that standard iterator passes in by 142 152 # args, and instantiation for iteration is 33% faster. 143 153 args_len = len(args) … … 206 216 dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self) 207 217 208 218 def save(self, raw=False): 219 "Save model object to database, creating if doesn't exist, otherwise updating" 209 220 dispatcher.send(signal=signals.pre_save, sender=self.__class__, 210 221 instance=self, raw=raw) 211 222 212 223 non_pks = [f for f in self._meta.fields if not f.primary_key] 224 modified_attrs = self._modified_attrs 225 non_pks = [f for f in non_pks if (f.name in modified_attrs or 226 f.attname in modified_attrs)] 227 self._reset_modified_attrs() 213 228 cursor = connection.cursor() 214 229 215 230 qn = connection.ops.quote_name -
django/db/models/query.py
204 204 index_start=0, max_depth=self._max_related_depth) 205 205 else: 206 206 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() 207 211 for i, k in enumerate(extra_select): 208 212 setattr(obj, k[0], row[index_end+i]) 209 213 yield obj -
tests/modeltests/update_fields/models.py
1 """ 2 #. Save only modified fields on update 3 """ 4 from django.db import models 5 6 class 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 33 u'Changed article 1' 34 >>> a3.body 35 u'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 43 u'Reset article 1' 44 >>> a3.body 45 u'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 58 u'Changed article 2' 59 >>> a3.body 60 u'Changed body 2' 61 """}