def get_ordering(self): lookup_opts, params = self.lookup_opts, self.params # For ordering, first check the "ordering" parameter in the admin options, # then check the object's default ordering. If neither of those exist, # order descending by ID by default. Finally, look for manually-specified # ordering from the query string. ordering = lookup_opts.admin.ordering or lookup_opts.ordering or [ '-' + lookup_opts.pk.name ] # Normalize it to new-style ordering. ordering = handle_legacy_orderlist(ordering) if ordering[0].startswith('-'): order_field, order_type = ordering[0][1:], 'desc' else: order_field, order_type = ordering[0], 'asc' if ORDER_VAR in params: try: field_name = lookup_opts.admin.list_display[int( params[ORDER_VAR])] try: f = lookup_opts.get_field(field_name) except models.FieldDoesNotExist: # see if field_name is a name of a non-field # that allows sorting try: attr = getattr(lookup_opts.admin.manager.model, field_name) order_field = attr.admin_order_field except AttributeError: pass else: if not isinstance(f.rel, models.ManyToOneRel) or not f.null: order_field = f.name except (IndexError, ValueError): pass # Invalid ordering specified. Just use the default. if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'): order_type = params[ORDER_TYPE_VAR] return order_field, order_type
def get_ordering(self): lookup_opts, params = self.lookup_opts, self.params # For ordering, first check the "ordering" parameter in the admin options, # then check the object's default ordering. If neither of those exist, # order descending by ID by default. Finally, look for manually-specified # ordering from the query string. ordering = lookup_opts.admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name] # Normalize it to new-style ordering. ordering = handle_legacy_orderlist(ordering) if ordering[0].startswith('-'): order_field, order_type = ordering[0][1:], 'desc' else: order_field, order_type = ordering[0], 'asc' if ORDER_VAR in params: try: field_name = lookup_opts.admin.list_display[int(params[ORDER_VAR])] try: f = lookup_opts.get_field(field_name) except models.FieldDoesNotExist: # see if field_name is a name of a non-field # that allows sorting try: attr = getattr(lookup_opts.admin.manager.model, field_name) order_field = attr.admin_order_field except AttributeError: pass else: if not isinstance(f.rel, models.ManyToOneRel) or not f.null: order_field = f.name except (IndexError, ValueError): pass # Invalid ordering specified. Just use the default. if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'): order_type = params[ORDER_TYPE_VAR] return order_field, order_type
def _get_sql_clause(self, get_full_query=False): from django.db.models.query import fill_table_cache, \ handle_legacy_orderlist, orderfield2column opts = self.model._meta qn = connection.ops.quote_name # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) for f in opts.fields] tables = [quote_only_if_word(t) for t in self._tables] joins = SortedDict() where = self._where[:] params = self._params[:] # Convert self._filters into SQL. joins2, where2, params2 = self._filters.get_sql(opts) joins.update(joins2) where.extend(where2) params.extend(params2) # Add additional tables and WHERE clauses based on select_related. if self._select_related: fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table]) # Add any additional SELECTs. if self._select: select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) for s in self._select.items()]) # Start composing the body of the SQL statement. sql = [" FROM", qn(opts.db_table)] # Compose the join dictionary into SQL describing the joins. if joins: sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, alias, condition) for (alias, (table, join_type, condition)) in joins.items()])) # Compose the tables clause into SQL. if tables: sql.append(", " + ", ".join(tables)) # Compose the where clause into SQL. if where: sql.append(where and "WHERE " + " AND ".join(where)) # ORDER BY clause order_by = [] if self._order_by is not None: ordering_to_use = self._order_by else: ordering_to_use = opts.ordering for f in handle_legacy_orderlist(ordering_to_use): if f == '?': # Special case. order_by.append(DatabaseOperations().random_function_sql()) else: if f.startswith('-'): col_name = f[1:] order = "DESC" else: col_name = f order = "ASC" if "." in col_name: table_prefix, col_name = col_name.split('.', 1) table_prefix = qn(table_prefix) + '.' else: # Use the database table as a column prefix if it wasn't given, # and if the requested column isn't a custom SELECT. if "." not in col_name and col_name not in (self._select or ()): table_prefix = qn(opts.db_table) + '.' else: table_prefix = '' order_by.append('%s%s %s' % (table_prefix, qn(orderfield2column(col_name, opts)), order)) if order_by: sql.append("ORDER BY " + ", ".join(order_by)) # Look for column name collisions in the select elements # and fix them with an AS alias. This allows us to do a # SELECT * later in the paging query. cols = [clause.split('.')[-1] for clause in select] for index, col in enumerate(cols): if cols.count(col) > 1: col = '%s%d' % (col.replace('"', ''), index) cols[index] = col select[index] = '%s AS %s' % (select[index], col) # LIMIT and OFFSET clauses # To support limits and offsets, Oracle requires some funky rewriting of an otherwise normal looking query. select_clause = ",".join(select) distinct = (self._distinct and "DISTINCT " or "") if order_by: order_by_clause = " OVER (ORDER BY %s )" % (", ".join(order_by)) else: #Oracle's row_number() function always requires an order-by clause. #So we need to define a default order-by, since none was provided. order_by_clause = " OVER (ORDER BY %s.%s)" % \ (qn(opts.db_table), qn(opts.fields[0].db_column or opts.fields[0].column)) # limit_and_offset_clause if self._limit is None: assert self._offset is None, "'offset' is not allowed without 'limit'" if self._offset is not None: offset = int(self._offset) else: offset = 0 if self._limit is not None: limit = int(self._limit) else: limit = None limit_and_offset_clause = '' if limit is not None: limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % (offset, limit+offset) elif offset: limit_and_offset_clause = "WHERE rn > %s" % (offset) if len(limit_and_offset_clause) > 0: fmt = \ """SELECT * FROM (SELECT %s%s, ROW_NUMBER()%s AS rn %s) %s""" full_query = fmt % (distinct, select_clause, order_by_clause, ' '.join(sql).strip(), limit_and_offset_clause) else: full_query = None if get_full_query: return select, " ".join(sql), params, full_query else: return select, " ".join(sql), params
def _get_sql_clause(self, get_full_query=False): from django.db.models.query import fill_table_cache, \ handle_legacy_orderlist, orderfield2column opts = self.model._meta qn = connection.ops.quote_name # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. select = [ "%s.%s" % (qn(opts.db_table), qn(f.column)) for f in opts.fields ] tables = [quote_only_if_word(t) for t in self._tables] joins = SortedDict() where = self._where[:] params = self._params[:] # Convert self._filters into SQL. joins2, where2, params2 = self._filters.get_sql(opts) joins.update(joins2) where.extend(where2) params.extend(params2) # Add additional tables and WHERE clauses based on select_related. if self._select_related: fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table]) # Add any additional SELECTs. if self._select: select.extend([ '(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) for s in self._select.items() ]) # Start composing the body of the SQL statement. sql = [" FROM", qn(opts.db_table)] # Compose the join dictionary into SQL describing the joins. if joins: sql.append(" ".join([ "%s %s %s ON %s" % (join_type, table, alias, condition) for (alias, (table, join_type, condition)) in joins.items() ])) # Compose the tables clause into SQL. if tables: sql.append(", " + ", ".join(tables)) # Compose the where clause into SQL. if where: sql.append(where and "WHERE " + " AND ".join(where)) # ORDER BY clause order_by = [] if self._order_by is not None: ordering_to_use = self._order_by else: ordering_to_use = opts.ordering for f in handle_legacy_orderlist(ordering_to_use): if f == '?': # Special case. order_by.append( DatabaseOperations().random_function_sql()) else: if f.startswith('-'): col_name = f[1:] order = "DESC" else: col_name = f order = "ASC" if "." in col_name: table_prefix, col_name = col_name.split('.', 1) table_prefix = qn(table_prefix) + '.' else: # Use the database table as a column prefix if it wasn't given, # and if the requested column isn't a custom SELECT. if "." not in col_name and col_name not in ( self._select or ()): table_prefix = qn(opts.db_table) + '.' else: table_prefix = '' order_by.append( '%s%s %s' % (table_prefix, qn(orderfield2column( col_name, opts)), order)) if order_by: sql.append("ORDER BY " + ", ".join(order_by)) # Look for column name collisions in the select elements # and fix them with an AS alias. This allows us to do a # SELECT * later in the paging query. cols = [clause.split('.')[-1] for clause in select] for index, col in enumerate(cols): if cols.count(col) > 1: col = '%s%d' % (col.replace('"', ''), index) cols[index] = col select[index] = '%s AS %s' % (select[index], col) # LIMIT and OFFSET clauses # To support limits and offsets, Oracle requires some funky rewriting of an otherwise normal looking query. select_clause = ",".join(select) distinct = (self._distinct and "DISTINCT " or "") if order_by: order_by_clause = " OVER (ORDER BY %s )" % ( ", ".join(order_by)) else: #Oracle's row_number() function always requires an order-by clause. #So we need to define a default order-by, since none was provided. order_by_clause = " OVER (ORDER BY %s.%s)" % \ (qn(opts.db_table), qn(opts.fields[0].db_column or opts.fields[0].column)) # limit_and_offset_clause if self._limit is None: assert self._offset is None, "'offset' is not allowed without 'limit'" if self._offset is not None: offset = int(self._offset) else: offset = 0 if self._limit is not None: limit = int(self._limit) else: limit = None limit_and_offset_clause = '' if limit is not None: limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % ( offset, limit + offset) elif offset: limit_and_offset_clause = "WHERE rn > %s" % (offset) if len(limit_and_offset_clause) > 0: fmt = \ """SELECT * FROM (SELECT %s%s, ROW_NUMBER()%s AS rn %s) %s""" full_query = fmt % (distinct, select_clause, order_by_clause, ' '.join(sql).strip(), limit_and_offset_clause) else: full_query = None if get_full_query: return select, " ".join(sql), params, full_query else: return select, " ".join(sql), params