Ticket #4102: 4102-dirty-set.6.patch
File 4102-dirty-set.6.patch, 5.0 KB (added by , 17 years ago) |
---|
-
django/db/models/base.py
19 19 import sys 20 20 import os 21 21 22 try: 23 set 24 except NameError: 25 from sets import Set as set # Python 2.3 fallback 26 22 27 class ModelBase(type): 23 28 "Metaclass for all models" 24 29 def __new__(cls, name, bases, attrs): … … 97 102 def __ne__(self, other): 98 103 return not self.__eq__(other) 99 104 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 value not in self._modified_attrs: 110 self._modified_attrs.add(name) 111 else: 112 self._modified_attrs = set((value,)) 113 super(Model, self).__setattr__(name, value) 114 115 def _reset_modified_attrs(self): 116 try: 117 del self._modified_attrs 118 except AttributeError: 119 pass 120 100 121 def __init__(self, *args, **kwargs): 101 122 dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs) 102 123 103 124 # 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. 105 126 # 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. 107 128 args_len = len(args) 108 129 if args_len > len(self._meta.fields): 109 130 # Daft, but matches old exception sans the err msg. … … 202 223 _prepare = classmethod(_prepare) 203 224 204 225 def save(self, raw=False): 226 "Save model object to database, creating if doesn't exist, otherwise updating" 205 227 dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self) 206 228 207 229 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() 208 234 cursor = connection.cursor() 209 235 210 236 # First, try an UPDATE. If that doesn't update anything, do an INSERT. -
django/db/models/query.py
203 203 index_start=0, max_depth=self._max_related_depth) 204 204 else: 205 205 obj = self.model(*row[:index_end]) 206 # Models keep a track of modified attrs to choose which 207 # fields to save. Since we're just pulling from the 208 # database, nothing has changed yet. 209 obj._reset_modified_attrs() 206 210 for i, k in enumerate(extra_select): 207 211 setattr(obj, k[0], row[index_end+i]) 208 212 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 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 43 u'Reset article 1' 44 >>> a3.body 45 u'Reset body 1' 46 """}