Django

Code

Ticket #3389: m2m_ids.diff

File m2m_ids.diff, 3.5 kB (added by russellm, 2 years ago)

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

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

    old new  
    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

    old new  
    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')