Ticket #3389: m2m_ids.diff

File m2m_ids.diff, 3.5 KB (added by russellm, 9 years ago)

Patch to allow m2m relations to be set by assigning primary key

  • django/db/models/fields/related.py

     
    316316            # join_table: name of the m2m link table
    317317            # source_col_name: the PK colname in join_table for the source object
    318318            # target_col_name: the PK colname in join_table for the target object
    319             # *objs - objects to add
     319            # *objs - objects to add. Either object instances, or primary keys of object instances.
    320320            from django.db import connection
    321321
    322322            # If there aren't any objects, there is nothing to do.
    323323            if objs:
    324324                # Check that all the objects are of the right type
     325                new_ids = set()
    325326                for obj in objs:
    326                     if not isinstance(obj, self.model):
    327                         raise ValueError, "objects to add() must be %s instances" % self.model._meta.object_name
     327                    if isinstance(obj, self.model):
     328                        new_ids.add(obj._get_pk_val())
     329                    else:
     330                        new_ids.add(obj)
    328331                # Add the newly created or already existing objects to the join table.
    329332                # First find out which items are already added, to avoid adding them twice
    330                 new_ids = set([obj._get_pk_val() for obj in objs])
    331333                cursor = connection.cursor()
    332334                cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \
    333335                    (target_col_name, self.join_table, source_col_name,
     
    354356            # If there aren't any objects, there is nothing to do.
    355357            if objs:
    356358                # Check that all the objects are of the right type
     359                old_ids = set()
    357360                for obj in objs:
    358                     if not isinstance(obj, self.model):
    359                         raise ValueError, "objects to remove() must be %s instances" % self.model._meta.object_name
     361                    if isinstance(obj, self.model):
     362                        old_ids.add(obj._get_pk_val())
     363                    else:
     364                        old_ids.add(obj)
    360365                # Remove the specified objects from the join table
    361                 old_ids = set([obj._get_pk_val() for obj in objs])
    362366                cursor = connection.cursor()
    363367                cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
    364368                    (self.join_table, source_col_name,
  • tests/modeltests/many_to_many/models.py

     
    203203>>> p2.article_set.all()
    204204[<Article: Oxygen-free diet works wonders>]
    205205
    206 # Recreate the article and Publication we just deleted.
     206# Relation sets can also be set using primary key values
     207>>> p2.article_set = [a4.id, a5.id]
     208>>> p2.article_set.all()
     209[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
     210>>> a4.publications.all()
     211[<Publication: Science News>]
     212>>> a4.publications = [p3.id]
     213>>> p2.article_set.all()
     214[<Article: Oxygen-free diet works wonders>]
     215>>> a4.publications.all()
     216[<Publication: Science Weekly>]
     217
     218# Recreate the article and Publication we have deleted.
    207219>>> p1 = Publication(id=None, title='The Python Journal')
    208220>>> p1.save()
    209221>>> a2 = Article(id=None, headline='NASA uses Python')
Back to Top