Ticket #14700: patch_obj_creation.diff

File patch_obj_creation.diff, 5.7 KB (added by Anssi Kääriäinen, 13 years ago)

Probably backwards incompatible optimization to model instance initialization

  • django/db/models/base.py

    diff --git a/django/db/models/base.py b/django/db/models/base.py
    index 796ccaa..d781e63 100644
    a b class Model(object):  
    272272
    273273        # Set up the storage for instance state
    274274        self._state = ModelState()
     275        if '_use_dict' in kwargs:
     276            self.__dict__.update(kwargs['_use_dict'])
     277            # for attname, val in kwargs['_use_dict'].iteritems():
     278            #     setattr(self, attname, val)
     279            signals.post_init.send(sender=self.__class__, instance=self)
     280            return
    275281
    276282        # There is a rather weird disparity here; if kwargs, it's set, then args
    277283        # overrides it. It should be one or the other; don't duplicate the work
  • django/db/models/query.py

    diff --git a/django/db/models/query.py b/django/db/models/query.py
    index d448dec..946c29b 100644
    a b class RawQuerySet(object):  
    12911291        self.translations = translations or {}
    12921292
    12931293    def __iter__(self):
    1294         for row in self.query:
    1295             yield self.transform_results(row)
     1294        # mapping of attrnames to row column positions.
     1295        model_init_field_names = {}
     1296        # just the positions for as-fast-as-possible iteration.
     1297        # contains the same values as model_init_field_names.itervalues(),
     1298        # but ordered in the order model.__init__ expects them. Used so that
     1299        # when all fields are present, we can use *args based model
     1300        # initialization.
     1301        model_init_field_pos = []
     1302        # A list of tuples of column name to column position.
     1303        annotation_fields = []
     1304
     1305        # Note, calling self.db is relatively expensive, so we need to call it
     1306        # just once instead of inside the loop.
     1307        db = self.db
     1308        connection = connections[db]
     1309
     1310        compiler = connection.ops.compiler('SQLCompiler')(self.query, connection, db)
     1311        if hasattr(compiler, 'resolve_columns'):
     1312            fields = [self.model_fields.get(c, None) for c in self.columns]
     1313        model_fields_keys = self.model_fields.keys()
     1314        for pos, column in enumerate(self.columns):
     1315            if column in model_fields_keys:
     1316                model_init_field_names[self.model_fields[column].attname] = pos
     1317            else:
     1318                annotation_fields.append((column, pos))
     1319        skip = set()
     1320        for field in self.model._meta.fields:
     1321            if field.attname not in model_init_field_names:
     1322                skip.add(field.attname)
     1323        if skip:
     1324            if self.model._meta.pk.attname in skip:
     1325                raise InvalidQuery('Raw query must include the primary key')
     1326            model_cls = deferred_class_factory(self.model, skip)
     1327        else:
     1328            model_cls = self.model
     1329            for field in self.model._meta.fields:
     1330                model_init_field_pos.append(model_init_field_names[field.attname])
     1331        need_resolv_columns = hasattr(compiler, 'resolve_columns')
     1332        for values in self.query:
     1333            if need_resolv_columns:
     1334                values = compiler.resolve_columns(values, fields)
     1335            # Associate fields to values
     1336            #if skip:
     1337            model_init_kwargs = {}
     1338            for attname, pos in model_init_field_names.iteritems():
     1339                model_init_kwargs[attname] = values[pos]
     1340            instance = model_cls(_use_dict=model_init_kwargs)
     1341            # else:
     1342            #     model_init_args = []
     1343            #     model_init_args = [values[pos] for pos in model_init_field_pos]
     1344            #    instance = model_cls(*model_init_args)
     1345            # Construct model instance and apply annotations
     1346            if annotation_fields:
     1347                for column, pos in annotation_fields:
     1348                    setattr(instance, column, values[pos])
     1349
     1350            instance._state.db = db
     1351
     1352            yield instance
    12961353
    12971354    def __repr__(self):
    12981355        return "<RawQuerySet: %r>" % (self.raw_query % self.params)
    class RawQuerySet(object):  
    13471404                self._model_fields[converter(column)] = field
    13481405        return self._model_fields
    13491406
    1350     def transform_results(self, values):
    1351         model_init_kwargs = {}
    1352         annotations = ()
    1353 
    1354         # Perform database backend type resolution
    1355         connection = connections[self.db]
    1356         compiler = connection.ops.compiler('SQLCompiler')(self.query, connection, self.db)
    1357         if hasattr(compiler, 'resolve_columns'):
    1358             fields = [self.model_fields.get(c,None) for c in self.columns]
    1359             values = compiler.resolve_columns(values, fields)
    1360 
    1361         # Associate fields to values
    1362         for pos, value in enumerate(values):
    1363             column = self.columns[pos]
    1364 
    1365             # Separate properties from annotations
    1366             if column in self.model_fields.keys():
    1367                 model_init_kwargs[self.model_fields[column].attname] = value
    1368             else:
    1369                 annotations += (column, value),
    1370 
    1371         # Construct model instance and apply annotations
    1372         skip = set()
    1373         for field in self.model._meta.fields:
    1374             if field.attname not in model_init_kwargs.keys():
    1375                 skip.add(field.attname)
    1376 
    1377         if skip:
    1378             if self.model._meta.pk.attname in skip:
    1379                 raise InvalidQuery('Raw query must include the primary key')
    1380             model_cls = deferred_class_factory(self.model, skip)
    1381         else:
    1382             model_cls = self.model
    1383 
    1384         instance = model_cls(**model_init_kwargs)
    1385 
    1386         for field, value in annotations:
    1387             setattr(instance, field, value)
    1388 
    1389         instance._state.db = self.query.using
    1390 
    1391         return instance
    13921407
    13931408def insert_query(model, values, return_id=False, raw_values=False, using=None):
    13941409    """
Back to Top