Ticket #4997: query.py.diff
File query.py.diff, 4.2 KB (added by , 17 years ago) |
---|
-
django/trunk/django/db/models/query.py
88 88 self.model = model 89 89 self._filters = Q() 90 90 self._order_by = None # Ordering, e.g. ('date', '-name'). If None, use model's ordering. 91 self._group_by = [] # Grouping, e.g. ('foreignkey'). 91 92 self._select_related = False # Whether to fill cache for related objects. 92 93 self._max_related_depth = 0 # Maximum "depth" for select_related 93 94 self._distinct = False # Whether the query should use SELECT DISTINCT. … … 215 216 If the queryset is already cached (i.e. self._result_cache is set) this 216 217 simply returns the length of the cached results set to avoid multiple 217 218 SELECT COUNT(*) calls. 219 220 If they were using GROUP_BY we have to change this to a COUNT(DISTINCT). 218 221 """ 219 222 if self._result_cache is not None: 220 223 return len(self._result_cache) … … 228 231 counter._offset = None 229 232 counter._limit = None 230 233 234 if counter._group_by: 235 id_col = ", ".join(counter.groupby2columns(self.model._meta)) 236 counter._group_by = () 237 counter._distinct = True 238 elif self._distinct: 239 id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table), 240 backend.quote_name(self.model._meta.pk.column)) 241 231 242 try: 232 243 select, sql, params = counter._get_sql_clause() 233 244 except EmptyResultSet: … … 418 429 "Cannot reorder a query once a slice has been taken." 419 430 return self._clone(_order_by=field_names) 420 431 432 def group_by(self, *field_names): 433 "Returns a new QuerySet instance with '_group_by' modified." 434 return self._clone(_group_by=field_names) 435 421 436 def distinct(self, true_or_false=True): 422 437 "Returns a new QuerySet instance with '_distinct' modified." 423 438 return self._clone(_distinct=true_or_false) … … 443 458 c.model = self.model 444 459 c._filters = self._filters 445 460 c._order_by = self._order_by 461 c._group_by = self._group_by 446 462 c._select_related = self._select_related 447 463 c._max_related_depth = self._max_related_depth 448 464 c._distinct = self._distinct … … 473 489 if (self._order_by is not None and len(self._order_by) > 0) and \ 474 490 (combined._order_by is None or len(combined._order_by) == 0): 475 491 combined._order_by = self._order_by 492 if (self._group_by is not None and len(self._group_by) > 0) and \ 493 (combined._group_by is None or len(combined._group_by) == 0): 494 combined._group_by = self._group_by 476 495 return combined 477 496 478 497 def _get_data(self): … … 523 542 if where: 524 543 sql.append(where and "WHERE " + " AND ".join(where)) 525 544 545 # GROUP BY clause 546 group_by = self.groupby2columns(opts) 547 if group_by: 548 sql.append("GROUP BY " + ", ".join(group_by)) 549 526 550 # ORDER BY clause 527 551 order_by = [] 528 552 if self._order_by is not None: … … 561 585 562 586 return select, " ".join(sql), params 563 587 588 def groupby2columns(self, opts): 589 group_by = [] 590 for col_name in self._group_by: 591 if "." in col_name: 592 table_prefix, col_name = col_name.split('.', 1) 593 table_prefix = backend.quote_name(table_prefix) + '.' 594 else: 595 # Use the database table as a column prefix if it wasn't given, 596 # and if the requested column isn't a custom SELECT. 597 if "." not in col_name and col_name not in (self._select or ()): 598 table_prefix = backend.quote_name(opts.db_table) + '.' 599 else: 600 table_prefix = '' 601 group_by.append('%s%s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)))) 602 return group_by 603 564 604 # Use the backend's QuerySet class if it defines one, otherwise use _QuerySet. 565 605 if hasattr(backend, 'get_query_set_class'): 566 606 QuerySet = backend.get_query_set_class(_QuerySet)