diff --git a/django/db/models/query.py b/django/db/models/query.py index 7a81910715..8a784be7c8 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -197,9 +197,12 @@ class QuerySet(object): "Performs a SELECT COUNT() and returns the number of records as an integer." counter = self._clone() counter._order_by = () + counter._select_related = False + + offset = counter._offset + limit = counter._limit counter._offset = None counter._limit = None - counter._select_related = False try: select, sql, params = counter._get_sql_clause() @@ -213,7 +216,16 @@ class QuerySet(object): cursor.execute("SELECT COUNT(DISTINCT(%s))" % id_col + sql, params) else: cursor.execute("SELECT COUNT(*)" + sql, params) - return cursor.fetchone()[0] + count = cursor.fetchone()[0] + + # Apply any offset and limit constraints manually, since using LIMIT or + # OFFSET in SQL doesn't change the output of COUNT. + if offset: + count = max(0, count - offset) + if limit: + count = min(limit, count) + + return count def get(self, *args, **kwargs): "Performs the SELECT and returns a single object matching the given keyword arguments." diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py index d344710bef..106c97d3b4 100644 --- a/tests/modeltests/lookup/models.py +++ b/tests/modeltests/lookup/models.py @@ -58,6 +58,17 @@ Article 4 >>> Article.objects.filter(headline__startswith='Blah blah').count() 0L +# count() should respect sliced query sets. +>>> articles = Article.objects.all() +>>> articles.count() +7L +>>> articles[:4].count() +4 +>>> articles[1:100].count() +6L +>>> articles[10:100].count() +0 + # Date and date/time lookups can also be done with strings. >>> Article.objects.filter(pub_date__exact='2005-07-27 00:00:00').count() 3L