Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #3389 -- Many-to-many sets can now be assigned with primary key…

… values

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4448 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit d28a63cc008c2b62d1e82ecb5ff5a2d92e6a43ec 1 parent a031cad
@adrianholovaty adrianholovaty authored
View
18 django/db/models/fields/related.py
@@ -316,18 +316,20 @@ 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
+ # *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 _remove_items(self, source_col_name, target_col_name, *objs):
# 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,
View
14 tests/modeltests/many_to_many/models.py
@@ -203,7 +203,19 @@ class Meta:
>>> p2.article_set.all()
[<Article: Oxygen-free diet works wonders>]
-# 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()
+[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
+>>> a4.publications.all()
+[<Publication: Science News>]
+>>> a4.publications = [p3.id]
+>>> p2.article_set.all()
+[<Article: Oxygen-free diet works wonders>]
+>>> a4.publications.all()
+[<Publication: Science Weekly>]
+
+# 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')
Please sign in to comment.
Something went wrong with that request. Please try again.