Index: django/db/models/sql/query.py
===================================================================
--- django/db/models/sql/query.py	(revision 9787)
+++ django/db/models/sql/query.py	(working copy)
@@ -13,7 +13,7 @@
 from django.utils.datastructures import SortedDict
 from django.utils.encoding import force_unicode
 from django.db.backends.util import truncate_name
-from django.db import connection
+from django.db import connection, transaction
 from django.db.models import signals
 from django.db.models.fields import FieldDoesNotExist
 from django.db.models.query_utils import select_related_descend
@@ -1921,6 +1921,70 @@
             select_col = join_info[RHS_JOIN_COL]
         self.select = [(select_alias, select_col)]
 
+    def _add_items(self, source_col_name, target_col_name, join_table, 
+                   pk_val, instance, field, *objs):
+        # join_table: name of the m2m link table
+        # source_col_name: the PK colname in join_table for the source object
+        # target_col_name: the PK colname in join_table for the target object
+        # *objs - objects to add. Either object instances, or primary keys of object instances.
+    
+        # If there aren't any objects, there is nothing to do.
+        if objs:
+            # Check that all the objects are of the right type
+            new_ids = set()
+            for obj in objs:
+                if isinstance(obj, self.model):
+                    new_ids.add(obj._get_pk_val())
+                else:
+                    new_ids.add(obj)
+            # Add the newly created or already existing objects to the join table.
+            # First find out which items are already added, to avoid adding them twice
+            cursor = connection.cursor()
+            cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \
+                (target_col_name, join_table, source_col_name,
+                target_col_name, ",".join(['%s'] * len(new_ids))),
+                [pk_val] + list(new_ids))
+            existing_ids = set([row[0] for row in cursor.fetchall()])
+    
+            # Add the ones that aren't there already
+            for obj_id in (new_ids - existing_ids):
+                cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
+                    (join_table, source_col_name, target_col_name),
+                    [pk_val, obj_id])
+            transaction.commit_unless_managed()
+
+    def _remove_items(self, source_col_name, target_col_name, join_table, 
+                      pk_val, instance, field, *objs):
+        # source_col_name: the PK colname in join_table for the source object
+        # target_col_name: the PK colname in join_table for the target object
+        # *objs - objects to remove
+    
+        # If there aren't any objects, there is nothing to do.
+        if objs:
+            # Check that all the objects are of the right type
+            old_ids = set()
+            for obj in objs:
+                if isinstance(obj, self.model):
+                    old_ids.add(obj._get_pk_val())
+                else:
+                    old_ids.add(obj)
+            # Remove the specified objects from the join table
+            cursor = connection.cursor()
+            cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
+                (join_table, source_col_name,
+                target_col_name, ",".join(['%s'] * len(old_ids))),
+                [pk_val] + list(old_ids))
+            transaction.commit_unless_managed()
+    
+    def _clear_items(self, source_col_name, join_table, pk_val, instance, 
+                     field):
+        # source_col_name: the PK colname in join_table for the source object
+        cursor = connection.cursor()
+        cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
+            (join_table, source_col_name),
+            [pk_val])
+        transaction.commit_unless_managed()
+
     def execute_sql(self, result_type=MULTI):
         """
         Run the query against the database and returns the result(s). The
Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 9787)
+++ django/db/models/fields/related.py	(working copy)
@@ -1,4 +1,4 @@
-from django.db import connection, transaction
+from django.db import connection
 from django.db.backends import util
 from django.db.models import signals, get_model
 from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist
@@ -361,7 +361,7 @@
     and adds behavior for many-to-many related objects."""
     class ManyRelatedManager(superclass):
         def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None,
-                join_table=None, source_col_name=None, target_col_name=None):
+                join_table=None, source_col_name=None, target_col_name=None, field=None):
             super(ManyRelatedManager, self).__init__()
             self.core_filters = core_filters
             self.model = model
@@ -370,6 +370,7 @@
             self.join_table = join_table
             self.source_col_name = source_col_name
             self.target_col_name = target_col_name
+            self.field = field
             self.through = through
             self._pk_val = self.instance._get_pk_val()
             if self._pk_val is None:
@@ -382,27 +383,59 @@
         # the add and remove methods do not exist.
         if through is None:
             def add(self, *objs):
-                self._add_items(self.source_col_name, self.target_col_name, *objs)
+                self.get_query_set()._add_items(self.source_col_name,
+                                                self.target_col_name,
+                                                self.join_table,
+                                                self._pk_val,
+                                                self.instance,
+                                                self.field, 
+                                                *objs)
 
                 # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table
                 if self.symmetrical:
-                    self._add_items(self.target_col_name, self.source_col_name, *objs)
+                    self.get_query_set()._add_items(self.target_col_name,
+                                                    self.source_col_name,
+                                                    self.join_table,
+                                                    self._pk_val,
+                                                    self.instance,
+                                                    self.field, 
+                                                    *objs)
             add.alters_data = True
 
             def remove(self, *objs):
-                self._remove_items(self.source_col_name, self.target_col_name, *objs)
+                self.get_query_set()._remove_items(self.source_col_name, 
+                                                   self.target_col_name,
+                                                   self.join_table,
+                                                   self._pk_val,
+                                                   self.instance, 
+                                                   self.field, 
+                                                   *objs)
 
                 # If this is a symmetrical m2m relation to self, remove the mirror entry in the m2m table
                 if self.symmetrical:
-                    self._remove_items(self.target_col_name, self.source_col_name, *objs)
+                    self.get_query_set()._remove_items(self.target_col_name, 
+                                                       self.source_col_name,
+                                                       self.join_table,
+                                                       self._pk_val,
+                                                       self.instance, 
+                                                       self.field, 
+                                                       *objs)
             remove.alters_data = True
 
         def clear(self):
-            self._clear_items(self.source_col_name)
+            self.get_query_set()._clear_items(self.source_col_name,
+                                              self.join_table,
+                                              self._pk_val,
+                                              self.instance, 
+                                              self.field)
 
             # If this is a symmetrical m2m relation to self, clear the mirror entry in the m2m table
             if self.symmetrical:
-                self._clear_items(self.target_col_name)
+                self.get_query_set()._clear_items(self.target_col_name,
+                                                  self.join_table,
+                                                  self._pk_val,
+                                                  self.instance, 
+                                                  self.field)
         clear.alters_data = True
 
         def create(self, **kwargs):
@@ -425,67 +458,6 @@
             return obj, created
         get_or_create.alters_data = True
 
-        def _add_items(self, source_col_name, target_col_name, *objs):
-            # join_table: name of the m2m link table
-            # source_col_name: the PK colname in join_table for the source object
-            # target_col_name: the PK colname in join_table for the target object
-            # *objs - objects to add. Either object instances, or primary keys of object instances.
-
-            # If there aren't any objects, there is nothing to do.
-            if objs:
-                # Check that all the objects are of the right type
-                new_ids = set()
-                for obj in objs:
-                    if isinstance(obj, self.model):
-                        new_ids.add(obj._get_pk_val())
-                    else:
-                        new_ids.add(obj)
-                # Add the newly created or already existing objects to the join table.
-                # First find out which items are already added, to avoid adding them twice
-                cursor = connection.cursor()
-                cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \
-                    (target_col_name, self.join_table, source_col_name,
-                    target_col_name, ",".join(['%s'] * len(new_ids))),
-                    [self._pk_val] + list(new_ids))
-                existing_ids = set([row[0] for row in cursor.fetchall()])
-
-                # Add the ones that aren't there already
-                for obj_id in (new_ids - existing_ids):
-                    cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
-                        (self.join_table, source_col_name, target_col_name),
-                        [self._pk_val, obj_id])
-                transaction.commit_unless_managed()
-
-        def _remove_items(self, source_col_name, target_col_name, *objs):
-            # source_col_name: the PK colname in join_table for the source object
-            # target_col_name: the PK colname in join_table for the target object
-            # *objs - objects to remove
-
-            # If there aren't any objects, there is nothing to do.
-            if objs:
-                # Check that all the objects are of the right type
-                old_ids = set()
-                for obj in objs:
-                    if isinstance(obj, self.model):
-                        old_ids.add(obj._get_pk_val())
-                    else:
-                        old_ids.add(obj)
-                # Remove the specified objects from the join table
-                cursor = connection.cursor()
-                cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
-                    (self.join_table, source_col_name,
-                    target_col_name, ",".join(['%s'] * len(old_ids))),
-                    [self._pk_val] + list(old_ids))
-                transaction.commit_unless_managed()
-
-        def _clear_items(self, source_col_name):
-            # source_col_name: the PK colname in join_table for the source object
-            cursor = connection.cursor()
-            cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
-                (self.join_table, source_col_name),
-                [self._pk_val])
-            transaction.commit_unless_managed()
-
     return ManyRelatedManager
 
 class ManyRelatedObjectsDescriptor(object):
@@ -561,7 +533,8 @@
             symmetrical=(self.field.rel.symmetrical and instance.__class__ == rel_model),
             join_table=qn(self.field.m2m_db_table()),
             source_col_name=qn(self.field.m2m_column_name()),
-            target_col_name=qn(self.field.m2m_reverse_name())
+            target_col_name=qn(self.field.m2m_reverse_name()),
+            field=self.field
         )
 
         return manager
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 9787)
+++ django/db/models/query.py	(working copy)
@@ -710,6 +710,27 @@
         obj = self.values("pk")
         return obj.query.as_nested_sql()
 
+    ################################################
+    # PRIVATE METHODS THAT DEAL WITH M2M RELATIONS #
+    ################################################
+    
+    def _add_items(self, source_col_name=None, target_col_name=None,
+                   join_table=None, pk_val=None, 
+                   instance=None, field=None, *objs):
+        self.query._add_items(source_col_name, target_col_name,
+                              join_table, pk_val,instance, field, *objs)
+
+    def _remove_items(self, source_col_name=None, target_col_name=None, 
+                      join_table=None, pk_val=None,
+                      instance=None, field=None, *objs):
+        self.query._remove_items(source_col_name, target_col_name,
+                                 join_table, pk_val, instance, field, *objs)
+
+    def _clear_items(self, source_col_name=None, join_table=None, pk_val=None, 
+                     instance=None, field=None):
+        self.query._clear_items(source_col_name, join_table, pk_val, instance, 
+                                field)
+
     # When used as part of a nested query, a queryset will never be an "always
     # empty" result.
     value_annotation = True
