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