diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 384b05d218..b517747735 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -316,18 +316,20 @@ def create_many_related_manager(superclass): # 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 + # *objs - objects to add. Either object instances, or primary keys of object instances. from django.db import connection # 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 not isinstance(obj, self.model): - raise ValueError, "objects to add() must be %s instances" % self.model._meta.object_name + 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 - new_ids = set([obj._get_pk_val() for obj in objs]) 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, @@ -354,11 +356,13 @@ def create_many_related_manager(superclass): # 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 not isinstance(obj, self.model): - raise ValueError, "objects to remove() must be %s instances" % self.model._meta.object_name + 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 - old_ids = set([obj._get_pk_val() for obj in objs]) cursor = connection.cursor() cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \ (self.join_table, source_col_name, diff --git a/tests/modeltests/many_to_many/models.py b/tests/modeltests/many_to_many/models.py index 38f8931ee7..5e46ad428d 100644 --- a/tests/modeltests/many_to_many/models.py +++ b/tests/modeltests/many_to_many/models.py @@ -203,7 +203,19 @@ __test__ = {'API_TESTS':""" >>> p2.article_set.all() [] -# Recreate the article and Publication we just deleted. +# Relation sets can also be set using primary key values +>>> p2.article_set = [a4.id, a5.id] +>>> p2.article_set.all() +[, ] +>>> a4.publications.all() +[] +>>> a4.publications = [p3.id] +>>> p2.article_set.all() +[] +>>> a4.publications.all() +[] + +# Recreate the article and Publication we have deleted. >>> p1 = Publication(id=None, title='The Python Journal') >>> p1.save() >>> a2 = Article(id=None, headline='NASA uses Python')