| 1302 | | for row in self.query: |
| 1303 | | yield self.transform_results(row) |
| | 1302 | # Mapping of attrnames to row column positions. Used for constructing |
| | 1303 | # the model using kwargs, needed when not all model's fields are |
| | 1304 | # present in the query. |
| | 1305 | model_init_field_names = {} |
| | 1306 | # A list of tuples of (column name, column position). Used for |
| | 1307 | # annotation fields. |
| | 1308 | annotation_fields = [] |
| | 1309 | |
| | 1310 | # Cache some things for performance reasons outside the loop. |
| | 1311 | db = self.db |
| | 1312 | compiler = connections[db].ops.compiler('SQLCompiler')(self.query, connections[db], db) |
| | 1313 | need_resolv_columns = hasattr(compiler, 'resolve_columns') |
| | 1314 | |
| | 1315 | # Find out which columns are model's fields, and which ones should be |
| | 1316 | # annotated to the model. |
| | 1317 | for pos, column in enumerate(self.columns): |
| | 1318 | if column in self.model_fields.keys(): |
| | 1319 | model_init_field_names[self.model_fields[column].attname] = pos |
| | 1320 | else: |
| | 1321 | annotation_fields.append((column, pos)) |
| | 1322 | |
| | 1323 | # Find out which model's fields are not present in the query. |
| | 1324 | skip = set() |
| | 1325 | for field in self.model._meta.fields: |
| | 1326 | if field.attname not in model_init_field_names: |
| | 1327 | skip.add(field.attname) |
| | 1328 | if skip: |
| | 1329 | if self.model._meta.pk.attname in skip: |
| | 1330 | raise InvalidQuery('Raw query must include the primary key') |
| | 1331 | model_cls = deferred_class_factory(self.model, skip) |
| | 1332 | else: |
| | 1333 | model_cls = self.model |
| | 1334 | # All model's fields are present in the query. So, it is possible |
| | 1335 | # to use *args based model instantation. For each field of the model, |
| | 1336 | # record the query column position matching that field. |
| | 1337 | model_init_field_pos = [] |
| | 1338 | for field in self.model._meta.fields: |
| | 1339 | model_init_field_pos.append(model_init_field_names[field.attname]) |
| | 1340 | if need_resolv_columns: |
| | 1341 | fields = [self.model_fields.get(c, None) for c in self.columns] |
| | 1342 | # Begin looping through the query values. |
| | 1343 | for values in self.query: |
| | 1344 | if need_resolv_columns: |
| | 1345 | values = compiler.resolve_columns(values, fields) |
| | 1346 | # Associate fields to values |
| | 1347 | if skip: |
| | 1348 | model_init_kwargs = {} |
| | 1349 | for attname, pos in model_init_field_names.iteritems(): |
| | 1350 | model_init_kwargs[attname] = values[pos] |
| | 1351 | instance = model_cls(**model_init_kwargs) |
| | 1352 | else: |
| | 1353 | model_init_args = [values[pos] for pos in model_init_field_pos] |
| | 1354 | instance = model_cls(*model_init_args) |
| | 1355 | if annotation_fields: |
| | 1356 | for column, pos in annotation_fields: |
| | 1357 | setattr(instance, column, values[pos]) |
| | 1358 | |
| | 1359 | instance._state.db = db |
| | 1360 | instance._state.adding = False |
| | 1361 | |
| | 1362 | yield instance |
| 1358 | | def transform_results(self, values): |
| 1359 | | model_init_kwargs = {} |
| 1360 | | annotations = () |
| 1361 | | |
| 1362 | | # Perform database backend type resolution |
| 1363 | | connection = connections[self.db] |
| 1364 | | compiler = connection.ops.compiler('SQLCompiler')(self.query, connection, self.db) |
| 1365 | | if hasattr(compiler, 'resolve_columns'): |
| 1366 | | fields = [self.model_fields.get(c,None) for c in self.columns] |
| 1367 | | values = compiler.resolve_columns(values, fields) |
| 1368 | | |
| 1369 | | # Associate fields to values |
| 1370 | | for pos, value in enumerate(values): |
| 1371 | | column = self.columns[pos] |
| 1372 | | |
| 1373 | | # Separate properties from annotations |
| 1374 | | if column in self.model_fields.keys(): |
| 1375 | | model_init_kwargs[self.model_fields[column].attname] = value |
| 1376 | | else: |
| 1377 | | annotations += (column, value), |
| 1378 | | |
| 1379 | | # Construct model instance and apply annotations |
| 1380 | | skip = set() |
| 1381 | | for field in self.model._meta.fields: |
| 1382 | | if field.attname not in model_init_kwargs.keys(): |
| 1383 | | skip.add(field.attname) |
| 1384 | | |
| 1385 | | if skip: |
| 1386 | | if self.model._meta.pk.attname in skip: |
| 1387 | | raise InvalidQuery('Raw query must include the primary key') |
| 1388 | | model_cls = deferred_class_factory(self.model, skip) |
| 1389 | | else: |
| 1390 | | model_cls = self.model |
| 1391 | | |
| 1392 | | instance = model_cls(**model_init_kwargs) |
| 1393 | | |
| 1394 | | for field, value in annotations: |
| 1395 | | setattr(instance, field, value) |
| 1396 | | |
| 1397 | | instance._state.db = self.query.using |
| 1398 | | instance._state.adding = False |
| 1399 | | |
| 1400 | | return instance |
| 1401 | | |