diff --git a/django/db/models/base.py b/django/db/models/base.py
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -276,13 +276,14 @@
     _deferred = False
 
     def __init__(self, *args, **kwargs):
+        self._reset_modified_attrs()
         signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs)
 
         # Set up the storage for instance state
         self._state = ModelState()
 
         # There is a rather weird disparity here; if kwargs, it's set, then args
-        # overrides it. It should be one or the other; don't duplicate the work
+        # overrides it. It should be one or the other; don't duplicate the work.
         # The reason for the kwargs check is that standard iterator passes in by
         # args, and instantiation for iteration is 33% faster.
         args_len = len(args)
@@ -368,6 +369,15 @@
         super(Model, self).__init__()
         signals.post_init.send(sender=self.__class__, instance=self)
 
+    def __setattr__(self, name, value):
+        if name not in self._modified_attrs:
+            if not hasattr(self, name) or value != getattr(self, name):
+                self._modified_attrs.append(name)
+        super(Model, self).__setattr__(name, value)
+
+    def _reset_modified_attrs(self):
+        self.__dict__['_modified_attrs'] = []
+
     def __repr__(self):
         try:
             u = unicode(self)
@@ -514,6 +524,11 @@
         if not meta.proxy:
             non_pks = [f for f in meta.local_fields if not f.primary_key]
 
+            if self._state.db == using:
+                modified_attrs = self._modified_attrs
+                non_pks = [f for f in non_pks if (f.name in modified_attrs or f.attname in modified_attrs)]
+                self._reset_modified_attrs()
+
             # First, try an UPDATE. If that doesn't update anything, do an INSERT.
             pk_val = self._get_pk_val(meta)
             pk_set = pk_val is not None
diff --git a/django/db/models/query.py b/django/db/models/query.py
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -284,6 +284,10 @@
                 else:
                     # Omit aggregates in object creation.
                     obj = model(*row[index_start:aggregate_start])
+                    # Models keep a track of modified attrs to choose which
+                    # fields to save. Since we're just pulling from the
+                    # database, nothing has changed yet.
+                    obj._reset_modified_attrs()
 
                 # Store the source database of the object
                 obj._state.db = db
diff --git a/tests/regressiontests/update_fields/__init__.py b/tests/regressiontests/update_fields/__init__.py
new file mode 100644
diff --git a/tests/regressiontests/update_fields/models.py b/tests/regressiontests/update_fields/models.py
new file mode 100644
--- /dev/null
+++ b/tests/regressiontests/update_fields/models.py
@@ -0,0 +1,15 @@
+"""
+Save only modified fields on update
+"""
+from django.db import models
+
+class Article(models.Model):
+    headline = models.CharField(max_length=100, default='Default headline')
+    body = models.TextField()
+    pub_date = models.DateTimeField()
+
+    class Meta:
+        ordering = ('pub_date','headline')
+
+    def __str__(self):
+        return self.headline
diff --git a/tests/regressiontests/update_fields/tests.py b/tests/regressiontests/update_fields/tests.py
new file mode 100644
--- /dev/null
+++ b/tests/regressiontests/update_fields/tests.py
@@ -0,0 +1,47 @@
+from datetime import datetime
+
+from django.test import TestCase
+
+from models import Article
+
+
+class UpdateFieldsTest(TestCase):
+
+    def test_basic_update_fields(self):
+        # Create a couple of Articles.
+        a = Article(headline=u'Article 1', body=u'Body 1', pub_date=datetime(2007, 5, 5))
+        a.save()
+
+        # Change headline and body on different instances, then save both to
+        # verify that each only updated the modified field.
+        a1 = Article.objects.get(pk=a.id)
+        a2 = Article.objects.get(pk=a.id)
+        a1.headline = u'Changed article 1'
+        a2.body = u'Changed body 1'
+        a1.save()
+        a2.save()
+        a3 = Article.objects.get(pk=a.id)
+        self.assertEqual(a3.headline, u'Changed article 1')
+        self.assertEqual(a3.body, u'Changed body 1')
+
+        # Fields entered at instantiation of a model which will already exists
+        # should be saved as well.
+        a = Article(id=a.id, headline=u'Reset article 1', body=u'Reset body 1', pub_date=datetime(2007, 5, 5))
+        a.save()
+        a3 = Article.objects.get(pk=a.id)
+        self.assertEqual(a3.headline, u'Reset article 1')
+        self.assertEqual(a3.body, u'Reset body 1')
+
+        # If the value doesn't change, it won't be marked as modified --
+        # otherwise user input like forms/etc is going to mark everything
+        # modified regardless.
+        a1 = Article.objects.get(pk=a.id)
+        a2 = Article.objects.get(pk=a.id)
+        a1.headline = u'Changed article 2'
+        a2.headline = a2.headline
+        a2.body = u'Changed body 2'
+        a1.save()
+        a2.save()
+        a3 = Article.objects.get(pk=a.id)
+        self.assertEqual(a3.headline, u'Changed article 2')
+        self.assertEqual(a3.body, u'Changed body 2')
