Ticket #5020: query.py.4.diff
File query.py.4.diff, 7.3 KB (added by , 17 years ago) |
---|
-
query.py
89 89 self._filters = Q() 90 90 self._order_by = None # Ordering, e.g. ('date', '-name'). If None, use model's ordering. 91 91 self._select_related = False # Whether to fill cache for related objects. 92 self._recurse_fields = None 92 93 self._max_related_depth = 0 # Maximum "depth" for select_related 93 94 self._distinct = False # Whether the query should use SELECT DISTINCT. 94 95 self._select = {} # Dictionary of attname -> SQL. … … 200 201 row = self.resolve_columns(row, fields) 201 202 if fill_cache: 202 203 obj, index_end = get_cached_row(klass=self.model, row=row, 203 index_start=0, max_depth=self._max_related_depth )204 index_start=0, max_depth=self._max_related_depth, fields=self._recurse_fields) 204 205 else: 205 206 obj = self.model(*row[:index_end]) 206 207 for i, k in enumerate(extra_select): … … 408 409 else: 409 410 return self._filter_or_exclude(None, **filter_obj) 410 411 411 def select_related(self, true_or_false=True, depth=0):412 def select_related(self, *fields, **kwargs): 412 413 "Returns a new QuerySet instance with '_select_related' modified." 413 return self._clone(_select_related=true_or_false, _max_related_depth=depth) 414 true_or_false = kwargs.pop('true_or_false', True) 415 depth = kwargs.pop('depth', 0) 416 if not fields: fields = None 417 return self._clone(_select_related=true_or_false, _max_related_depth=depth, _recurse_fields=fields) 414 418 415 419 def order_by(self, *field_names): 416 420 "Returns a new QuerySet instance with the ordering changed." … … 444 448 c._filters = self._filters 445 449 c._order_by = self._order_by 446 450 c._select_related = self._select_related 451 c._recurse_fields = self._recurse_fields 447 452 c._max_related_depth = self._max_related_depth 448 453 c._distinct = self._distinct 449 454 c._select = self._select.copy() … … 501 506 fill_table_cache(opts, select, tables, where, 502 507 old_prefix=opts.db_table, 503 508 cache_tables_seen=[opts.db_table], 504 max_depth=self._max_related_depth )509 max_depth=self._max_related_depth, fields=self._recurse_fields) 505 510 506 511 # Add any additional SELECTs. 507 512 if self._select: … … 819 824 raise NotImplementedError 820 825 raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type) 821 826 822 def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0):827 def get_cached_row(klass, row, index_start, fields=None, max_depth=0, cur_depth=0): 823 828 """Helper function that recursively returns an object with cache filled""" 824 829 825 830 # If we've got a max_depth set and we've exceeded that depth, bail now. 826 831 if max_depth and cur_depth > max_depth: 827 832 return None 828 833 834 fields_to_join = get_select_related_fields(klass._meta, fields) 835 829 836 index_end = index_start + len(klass._meta.fields) 830 837 obj = klass(*row[index_start:index_end]) 831 for f in klass._meta.fields: 832 if f.rel and not f.null: 833 cached_row = get_cached_row(f.rel.to, row, index_end, max_depth, cur_depth+1) 834 if cached_row: 835 rel_obj, index_end = cached_row 836 setattr(obj, f.get_cache_name(), rel_obj) 838 for f in fields_to_join.iterkeys(): 839 cached_row = get_cached_row(f.rel.to, row, index_end, fields_to_join[f], max_depth, cur_depth+1) 840 if cached_row: 841 rel_obj, index_end = cached_row 842 setattr(obj, f.get_cache_name(), rel_obj) 837 843 return obj, index_end 838 844 839 def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen, max_depth=0, cur_depth=0):845 def get_select_related_fields(opts, fields=None): 840 846 """ 847 Helper function that returns a dictionary of fields for select_related() 848 """ 849 if fields is None: 850 fields_to_join = dict([(f, None) for f in opts.fields if f.rel and not f.null]) 851 else: 852 fields_for_lookup = dict([(f.name, f) for f in opts.fields if f.rel]) 853 fields_to_join = dict() 854 for f in fields: 855 path = f.split(LOOKUP_SEPARATOR) 856 try: 857 fn = fields_for_lookup[path[0]] 858 if fn not in fields_to_join: 859 fields_to_join[fn] = [] 860 if len(path) > 1: 861 fields_to_join[fn].append(LOOKUP_SEPARATOR.join(path[1:])) 862 except KeyError: 863 raise FieldDoesNotExist, '%s has no field named %s' % (opts.object_name, path[0]) 864 return fields_to_join 865 866 def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen, max_depth=0, fields=None, cur_depth=0): 867 """ 841 868 Helper function that recursively populates the select, tables and where (in 842 869 place) for select_related queries. 870 871 Implicit select_related calls on NULL fields will force an INNER JOIN currently. 843 872 """ 844 873 845 874 # If we've got a max_depth set and we've exceeded that depth, bail now. 846 if max_depth and cur_depth > max_depth:875 if max_depth and cur_depth >= max_depth: 847 876 return None 848 877 878 fields_to_join = get_select_related_fields(opts, fields) 879 849 880 qn = backend.quote_name 850 for f in opts.fields: 851 if f.rel and not f.null: 852 db_table = f.rel.to._meta.db_table 853 if db_table not in cache_tables_seen: 854 tables.append(qn(db_table)) 855 else: # The table was already seen, so give it a table alias. 856 new_prefix = '%s%s' % (db_table, len(cache_tables_seen)) 857 tables.append('%s %s' % (qn(db_table), qn(new_prefix))) 858 db_table = new_prefix 859 cache_tables_seen.append(db_table) 860 where.append('%s.%s = %s.%s' % \ 861 (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column))) 862 select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields]) 863 fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen, max_depth, cur_depth+1) 881 for f in fields_to_join.iterkeys(): 882 db_table = f.rel.to._meta.db_table 883 if db_table not in cache_tables_seen: 884 tables.append(qn(db_table)) 885 else: # The table was already seen, so give it a table alias. 886 new_prefix = '%s%s' % (db_table, len(cache_tables_seen)) 887 tables.append('%s %s' % (qn(db_table), qn(new_prefix))) 888 db_table = new_prefix 889 cache_tables_seen.append(db_table) 890 where.append('%s.%s = %s.%s' % \ 891 (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column))) 892 select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields]) 893 fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen, max_depth, fields_to_join[f], cur_depth+1) 864 894 865 895 def parse_lookup(kwarg_items, opts): 866 896 # Helper function that handles converting API kwargs