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