| 8 | | |
|---|
| 9 | | |
|---|
| 10 | | def get_cached_row(klass, row, index_start): |
|---|
| 11 | | "Helper function that recursively returns an object with cache filled" |
|---|
| 12 | | index_end = index_start + len(klass._meta.fields) |
|---|
| 13 | | obj = klass(*row[index_start:index_end]) |
|---|
| 14 | | for f in klass._meta.fields: |
|---|
| 15 | | if f.rel and not f.null: |
|---|
| 16 | | rel_obj, index_end = get_cached_row(f.rel.to, row, index_end) |
|---|
| 17 | | setattr(obj, f.get_cache_name(), rel_obj) |
|---|
| 18 | | return obj, index_end |
|---|
| 19 | | |
|---|
| 20 | | |
|---|
| 21 | | def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen): |
|---|
| 22 | | """ |
|---|
| 23 | | Helper function that recursively populates the select, tables and where (in |
|---|
| 24 | | place) for select_related queries. |
|---|
| 25 | | """ |
|---|
| 26 | | from django.db.models.fields import AutoField |
|---|
| 27 | | qn = backend.quote_name |
|---|
| 28 | | for f in opts.fields: |
|---|
| 29 | | if f.rel and not f.null: |
|---|
| 30 | | db_table = f.rel.to._meta.db_table |
|---|
| 31 | | if db_table not in cache_tables_seen: |
|---|
| 32 | | tables.append(qn(db_table)) |
|---|
| 33 | | else: # The table was already seen, so give it a table alias. |
|---|
| 34 | | new_prefix = '%s%s' % (db_table, len(cache_tables_seen)) |
|---|
| 35 | | tables.append('%s %s' % (qn(db_table), qn(new_prefix))) |
|---|
| 36 | | db_table = new_prefix |
|---|
| 37 | | cache_tables_seen.append(db_table) |
|---|
| 38 | | where.append('%s.%s = %s.%s' % \ |
|---|
| 39 | | (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column))) |
|---|
| 40 | | select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields if not isinstance(f2, AutoField)]) |
|---|
| 41 | | fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) |
|---|