Django

Code

Ticket #10109: patch_django_10109.20090422.diff

File patch_django_10109.20090422.diff, 14.7 kB (added by david, 1 year ago)

Update patch against r10618

  • django/db/models/sql/query.py

    old new  
    1313from django.utils.datastructures import SortedDict 
    1414from django.utils.encoding import force_unicode 
    1515from django.db.backends.util import truncate_name 
    16 from django.db import connection 
     16from django.db import connection, transaction 
    1717from django.db.models import signals 
    1818from django.db.models.fields import FieldDoesNotExist 
    1919from django.db.models.query_utils import select_related_descend 
     
    22842284        self.select = [(select_alias, select_col)] 
    22852285        self.remove_inherited_models() 
    22862286 
     2287    def _add_items(self, source_col_name, target_col_name, join_table,  
     2288                   pk_val, instance, field, *objs): 
     2289        # join_table: name of the m2m link table 
     2290        # source_col_name: the PK colname in join_table for the source object 
     2291        # target_col_name: the PK colname in join_table for the target object 
     2292        # *objs - objects to add. Either object instances, or primary keys of object instances. 
     2293         
     2294        # If there aren't any objects, there is nothing to do. 
     2295        if objs: 
     2296            from django.db.models.base import Model 
     2297            # Check that all the objects are of the right type 
     2298            new_ids = set() 
     2299            for obj in objs: 
     2300                if isinstance(obj, self.model): 
     2301                    new_ids.add(obj._get_pk_val()) 
     2302                elif isinstance(obj, Model): 
     2303                    raise TypeError, "'%s' instance expected" % self.model._meta.object_name 
     2304                else: 
     2305                    new_ids.add(obj) 
     2306            # Add the newly created or already existing objects to the join table. 
     2307            # First find out which items are already added, to avoid adding them twice 
     2308            cursor = connection.cursor() 
     2309            cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \ 
     2310                (target_col_name, join_table, source_col_name, 
     2311                target_col_name, ",".join(['%s'] * len(new_ids))), 
     2312                [pk_val] + list(new_ids)) 
     2313            existing_ids = set([row[0] for row in cursor.fetchall()]) 
     2314         
     2315            # Add the ones that aren't there already 
     2316            for obj_id in (new_ids - existing_ids): 
     2317                cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ 
     2318                    (join_table, source_col_name, target_col_name), 
     2319                    [pk_val, obj_id]) 
     2320            transaction.commit_unless_managed() 
     2321 
     2322    def _remove_items(self, source_col_name, target_col_name, join_table,  
     2323                      pk_val, instance, field, *objs): 
     2324        # source_col_name: the PK colname in join_table for the source object 
     2325        # target_col_name: the PK colname in join_table for the target object 
     2326        # *objs - objects to remove 
     2327         
     2328        # If there aren't any objects, there is nothing to do. 
     2329        if objs: 
     2330            # Check that all the objects are of the right type 
     2331            old_ids = set() 
     2332            for obj in objs: 
     2333                if isinstance(obj, self.model): 
     2334                    old_ids.add(obj._get_pk_val()) 
     2335                else: 
     2336                    old_ids.add(obj) 
     2337            # Remove the specified objects from the join table 
     2338            cursor = connection.cursor() 
     2339            cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \ 
     2340                (join_table, source_col_name, 
     2341                target_col_name, ",".join(['%s'] * len(old_ids))), 
     2342                [pk_val] + list(old_ids)) 
     2343            transaction.commit_unless_managed() 
     2344     
     2345    def _clear_items(self, source_col_name, join_table, pk_val, instance,  
     2346                     field): 
     2347        # source_col_name: the PK colname in join_table for the source object 
     2348        cursor = connection.cursor() 
     2349        cursor.execute("DELETE FROM %s WHERE %s = %%s" % \ 
     2350            (join_table, source_col_name), 
     2351            [pk_val]) 
     2352        transaction.commit_unless_managed() 
     2353 
    22872354    def execute_sql(self, result_type=MULTI): 
    22882355        """ 
    22892356        Run the query against the database and returns the result(s). The 
  • django/db/models/fields/related.py

    old new  
    1 from django.db import connection, transaction 
     1from django.db import connection 
    22from django.db.backends import util 
    33from django.db.models import signals, get_model 
    44from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist 
     
    382382    and adds behavior for many-to-many related objects.""" 
    383383    class ManyRelatedManager(superclass): 
    384384        def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None, 
    385                 join_table=None, source_col_name=None, target_col_name=None): 
     385                join_table=None, source_col_name=None, target_col_name=None, field=None): 
    386386            super(ManyRelatedManager, self).__init__() 
    387387            self.core_filters = core_filters 
    388388            self.model = model 
     
    391391            self.join_table = join_table 
    392392            self.source_col_name = source_col_name 
    393393            self.target_col_name = target_col_name 
     394            self.field = field 
    394395            self.through = through 
    395396            self._pk_val = self.instance._get_pk_val() 
    396397            if self._pk_val is None: 
     
    403404        # the add and remove methods do not exist. 
    404405        if through is None: 
    405406            def add(self, *objs): 
    406                 self._add_items(self.source_col_name, self.target_col_name, *objs) 
     407                self.get_query_set()._add_items(self.source_col_name, 
     408                                                self.target_col_name, 
     409                                                self.join_table, 
     410                                                self._pk_val, 
     411                                                self.instance, 
     412                                                self.field,  
     413                                                *objs) 
    407414 
    408415                # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table 
    409416                if self.symmetrical: 
    410                     self._add_items(self.target_col_name, self.source_col_name, *objs) 
     417                    self.get_query_set()._add_items(self.target_col_name, 
     418                                                    self.source_col_name, 
     419                                                    self.join_table, 
     420                                                    self._pk_val, 
     421                                                    self.instance, 
     422                                                    self.field,  
     423                                                    *objs) 
    411424            add.alters_data = True 
    412425 
    413426            def remove(self, *objs): 
    414                 self._remove_items(self.source_col_name, self.target_col_name, *objs) 
     427                self.get_query_set()._remove_items(self.source_col_name,  
     428                                                   self.target_col_name, 
     429                                                   self.join_table, 
     430                                                   self._pk_val, 
     431                                                   self.instance,  
     432                                                   self.field,  
     433                                                   *objs) 
    415434 
    416435                # If this is a symmetrical m2m relation to self, remove the mirror entry in the m2m table 
    417436                if self.symmetrical: 
    418                     self._remove_items(self.target_col_name, self.source_col_name, *objs) 
     437                    self.get_query_set()._remove_items(self.target_col_name,  
     438                                                       self.source_col_name, 
     439                                                       self.join_table, 
     440                                                       self._pk_val, 
     441                                                       self.instance,  
     442                                                       self.field,  
     443                                                       *objs) 
    419444            remove.alters_data = True 
    420445 
    421446        def clear(self): 
    422             self._clear_items(self.source_col_name) 
     447            self.get_query_set()._clear_items(self.source_col_name, 
     448                                              self.join_table, 
     449                                              self._pk_val, 
     450                                              self.instance,  
     451                                              self.field) 
    423452 
    424453            # If this is a symmetrical m2m relation to self, clear the mirror entry in the m2m table 
    425454            if self.symmetrical: 
    426                 self._clear_items(self.target_col_name) 
     455                self.get_query_set()._clear_items(self.target_col_name, 
     456                                                  self.join_table, 
     457                                                  self._pk_val, 
     458                                                  self.instance,  
     459                                                  self.field) 
    427460        clear.alters_data = True 
    428461 
    429462        def create(self, **kwargs): 
     
    446479            return obj, created 
    447480        get_or_create.alters_data = True 
    448481 
    449         def _add_items(self, source_col_name, target_col_name, *objs): 
    450             # join_table: name of the m2m link table 
    451             # source_col_name: the PK colname in join_table for the source object 
    452             # target_col_name: the PK colname in join_table for the target object 
    453             # *objs - objects to add. Either object instances, or primary keys of object instances. 
    454  
    455             # If there aren't any objects, there is nothing to do. 
    456             if objs: 
    457                 from django.db.models.base import Model 
    458                 # Check that all the objects are of the right type 
    459                 new_ids = set() 
    460                 for obj in objs: 
    461                     if isinstance(obj, self.model): 
    462                         new_ids.add(obj._get_pk_val()) 
    463                     elif isinstance(obj, Model): 
    464                         raise TypeError, "'%s' instance expected" % self.model._meta.object_name 
    465                     else: 
    466                         new_ids.add(obj) 
    467                 # Add the newly created or already existing objects to the join table. 
    468                 # First find out which items are already added, to avoid adding them twice 
    469                 cursor = connection.cursor() 
    470                 cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \ 
    471                     (target_col_name, self.join_table, source_col_name, 
    472                     target_col_name, ",".join(['%s'] * len(new_ids))), 
    473                     [self._pk_val] + list(new_ids)) 
    474                 existing_ids = set([row[0] for row in cursor.fetchall()]) 
    475  
    476                 # Add the ones that aren't there already 
    477                 for obj_id in (new_ids - existing_ids): 
    478                     cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ 
    479                         (self.join_table, source_col_name, target_col_name), 
    480                         [self._pk_val, obj_id]) 
    481                 transaction.commit_unless_managed() 
    482  
    483         def _remove_items(self, source_col_name, target_col_name, *objs): 
    484             # source_col_name: the PK colname in join_table for the source object 
    485             # target_col_name: the PK colname in join_table for the target object 
    486             # *objs - objects to remove 
    487  
    488             # If there aren't any objects, there is nothing to do. 
    489             if objs: 
    490                 # Check that all the objects are of the right type 
    491                 old_ids = set() 
    492                 for obj in objs: 
    493                     if isinstance(obj, self.model): 
    494                         old_ids.add(obj._get_pk_val()) 
    495                     else: 
    496                         old_ids.add(obj) 
    497                 # Remove the specified objects from the join table 
    498                 cursor = connection.cursor() 
    499                 cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \ 
    500                     (self.join_table, source_col_name, 
    501                     target_col_name, ",".join(['%s'] * len(old_ids))), 
    502                     [self._pk_val] + list(old_ids)) 
    503                 transaction.commit_unless_managed() 
    504  
    505         def _clear_items(self, source_col_name): 
    506             # source_col_name: the PK colname in join_table for the source object 
    507             cursor = connection.cursor() 
    508             cursor.execute("DELETE FROM %s WHERE %s = %%s" % \ 
    509                 (self.join_table, source_col_name), 
    510                 [self._pk_val]) 
    511             transaction.commit_unless_managed() 
    512  
    513482    return ManyRelatedManager 
    514483 
    515484class ManyRelatedObjectsDescriptor(object): 
     
    585554            symmetrical=(self.field.rel.symmetrical and isinstance(instance, rel_model)), 
    586555            join_table=qn(self.field.m2m_db_table()), 
    587556            source_col_name=qn(self.field.m2m_column_name()), 
    588             target_col_name=qn(self.field.m2m_reverse_name()) 
     557            target_col_name=qn(self.field.m2m_reverse_name()), 
     558            field=self.field 
    589559        ) 
    590560 
    591561        return manager 
  • django/db/models/query.py

    old new  
    683683        obj = self.values("pk") 
    684684        return obj.query.as_nested_sql() 
    685685 
     686    ################################################ 
     687    # PRIVATE METHODS THAT DEAL WITH M2M RELATIONS # 
     688    ################################################ 
     689     
     690    def _add_items(self, source_col_name=None, target_col_name=None, 
     691                   join_table=None, pk_val=None,  
     692                   instance=None, field=None, *objs): 
     693        self.query._add_items(source_col_name, target_col_name, 
     694                              join_table, pk_val,instance, field, *objs) 
     695 
     696    def _remove_items(self, source_col_name=None, target_col_name=None,  
     697                      join_table=None, pk_val=None, 
     698                      instance=None, field=None, *objs): 
     699        self.query._remove_items(source_col_name, target_col_name, 
     700                                 join_table, pk_val, instance, field, *objs) 
     701 
     702    def _clear_items(self, source_col_name=None, join_table=None, pk_val=None,  
     703                     instance=None, field=None): 
     704        self.query._clear_items(source_col_name, join_table, pk_val, instance,  
     705                                field) 
     706 
    686707    # When used as part of a nested query, a queryset will never be an "always 
    687708    # empty" result. 
    688709    value_annotation = True