Ticket #4102: 4102.2.patch

File 4102.2.patch, 6.2 KB (added by cgrady, 7 years ago)

post-qsrf patch

  • django/db/models/base.py

     
    165165class Model(object):
    166166    __metaclass__ = ModelBase
    167167
     168    def __setattr__(self, name, value):
     169        if name not in self._modified_attrs:
     170            if not hasattr(self, name) or value != getattr(self, name):
     171                self._modified_attrs.append(name)
     172        super(Model, self).__setattr__(name, value)
     173
     174    def _reset_modified_attrs(self):
     175        self.__dict__['_modified_attrs'] = []
     176
    168177    def __init__(self, *args, **kwargs):
     178        self._reset_modified_attrs()
    169179        dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
    170180
    171181        # There is a rather weird disparity here; if kwargs, it's set, then args
    172         # overrides it. It should be one or the other; don't duplicate the work
     182        # overrides it. It should be one or the other; don't duplicate the work.
    173183        # The reason for the kwargs check is that standard iterator passes in by
    174184        # args, and instantiation for iteration is 33% faster.
    175185        args_len = len(args)
     
    295305            setattr(self, field.attname, self._get_pk_val(parent._meta))
    296306
    297307        non_pks = [f for f in meta.local_fields if not f.primary_key]
     308        modified_attrs = self._modified_attrs
     309        non_pks = [f for f in non_pks if (f.name in modified_attrs or f.attname in modified_attrs)]
     310        self._reset_modified_attrs()
    298311
    299312        # First, try an UPDATE. If that doesn't update anything, do an INSERT.
    300313        pk_val = self._get_pk_val(meta)
  • django/db/models/query.py

     
    165165                        max_depth, requested=requested)
    166166            else:
    167167                obj = self.model(*row[index_start:])
     168                # Models keep a track of modified attrs to choose which
     169                # fields to save. Since we're just pulling from the
     170                # database, nothing has changed yet.
     171                obj._reset_modified_attrs()
    168172            for i, k in enumerate(extra_select):
    169173                setattr(obj, k, row[i])
    170174            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 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"""}
     62"""
     63#. Save only modified fields on update
     64"""
     65from django.db import models
     66
     67class Article(models.Model):
     68    headline = models.CharField(maxlength=100, default='Default headline')
     69    body = models.TextField()
     70    pub_date = models.DateTimeField()
     71
     72    class Meta:
     73        ordering = ('pub_date','headline')
     74
     75    def __str__(self):
     76        return self.headline
     77
     78__test__ = {'API_TESTS':"""
     79# Create a couple of Articles.
     80>>> from datetime import datetime
     81>>> a = Article(headline='Article 1', body='Body 1', pub_date=datetime(2007, 5, 5))
     82>>> a.save()
     83
     84# Change headline and body on different instances, then save both to verify
     85# that each only updated the modified field.
     86>>> a1 = Article.objects.get(pk=a.id)
     87>>> a2 = Article.objects.get(pk=a.id)
     88>>> a1.headline = 'Changed article 1'
     89>>> a2.body = 'Changed body 1'
     90>>> a1.save()
     91>>> a2.save()
     92>>> a3 = Article.objects.get(pk=a.id)
     93>>> a3.headline
     94u'Changed article 1'
     95>>> a3.body
     96u'Changed body 1'
     97
     98# Fields entered at instantiation of a model which will already exists should be
     99# saved as well.
     100>>> a = Article(id=a.id, headline='Reset article 1', body='Reset body 1', pub_date=datetime(2007, 5, 5))
     101>>> a.save()
     102>>> a3 = Article.objects.get(pk=a.id)
     103>>> a3.headline
     104u'Reset article 1'
     105>>> a3.body
     106u'Reset body 1'
     107
     108# If the value doesn't change, it won't be marked as modified -- otherwise user
     109# input like forms/etc is going to mark everything modified regardless.
     110>>> a1 = Article.objects.get(pk=a.id)
     111>>> a2 = Article.objects.get(pk=a.id)
     112>>> a1.headline = 'Changed article 2'
     113>>> a2.headline = a2.headline
     114>>> a2.body = 'Changed body 2'
     115>>> a1.save()
     116>>> a2.save()
     117>>> a3 = Article.objects.get(pk=a.id)
     118>>> a3.headline
     119u'Changed article 2'
     120>>> a3.body
     121u'Changed body 2'
     122"""}
Back to Top