Index: django/db/models/base.py
===================================================================
--- django/db/models/base.py	(revision 12677)
+++ django/db/models/base.py	(working copy)
@@ -539,6 +539,11 @@
 
     save_base.alters_data = True
 
+    @classmethod
+    def update(klass, queryset, updates, using=None):
+        for field in klass._meta.fields:
+            field.pre_update(queryset, updates)
+
     def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
         """
         Recursively populates seen_objs with all objects related to this
Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 12677)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -282,6 +282,10 @@
         "Returns field's value just before saving."
         return getattr(model_instance, self.attname)
 
+    def pre_update(self, queryset, kwargs):
+        "Do nothing by default"
+        pass
+
     def get_prep_value(self, value):
         "Perform preliminary non-db specific value checks and conversions."
         return value
@@ -649,6 +653,10 @@
         else:
             return super(DateField, self).pre_save(model_instance, add)
 
+    def pre_update(self, queryset, kwargs):
+        if self.auto_now and (self.name not in kwargs):
+            kwargs[self.name] =  datetime.datetime.now()
+
     def contribute_to_class(self, cls, name):
         super(DateField,self).contribute_to_class(cls, name)
         if not self.null:
Index: django/db/models/signals.py
===================================================================
--- django/db/models/signals.py	(revision 12677)
+++ django/db/models/signals.py	(working copy)
@@ -14,3 +14,6 @@
 post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"])
 
 m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set"])
+
+pre_update = Signal(providing_args=["queryset", "updates"])
+post_update = Signal(providing_args=["queryset", "updates"])
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 12677)
+++ django/db/models/query.py	(working copy)
@@ -450,8 +450,10 @@
         """
         assert self.query.can_filter(), \
                 "Cannot update a query once a slice has been taken."
+        signals.pre_update.send(sender=self.model, queryset=self, updates=kwargs)
         self._for_write = True
         query = self.query.clone(sql.UpdateQuery)
+        self.model.update(self, kwargs)
         query.add_update_values(kwargs)
         if not transaction.is_managed(using=self.db):
             transaction.enter_transaction_management(using=self.db)
@@ -468,6 +470,7 @@
             if forced_managed:
                 transaction.leave_transaction_management(using=self.db)
         self._result_cache = None
+        signals.post_update.send(sender=self.model, queryset=self, updates=kwargs)
         return rows
     update.alters_data = True
 
