Index: django/db/models/sql/query.py
===================================================================
--- django/db/models/sql/query.py	(revision 7350)
+++ django/db/models/sql/query.py	(working copy)
@@ -55,6 +55,7 @@
         self.start_meta = None
 
         # SQL-related attributes
+        self.aggregates = []
         self.select = []
         self.tables = []    # Aliases in the order they are created.
         self.where = where()
@@ -140,6 +141,7 @@
         obj.standard_ordering = self.standard_ordering
         obj.start_meta = self.start_meta
         obj.select = self.select[:]
+        obj.aggregates = self.aggregates[:]
         obj.tables = self.tables[:]
         obj.where = deepcopy(self.where)
         obj.where_class = self.where_class
@@ -173,6 +175,30 @@
                     row = self.resolve_columns(row, fields)
                 yield row
 
+    def get_aggregation(self):
+        for field in self.select:
+            self.group_by.append(field)
+        self.select.extend(self.aggregates)
+        self.aggregates = []
+        #print self.as_sql()
+        #print 'after', self.select
+
+        get_name = lambda x : isinstance(x, tuple) and x[1] or x.aliased_name
+
+        print 'final query', self.as_sql() 
+
+        if self.group_by:
+            data = self.execute_sql(MULTI)
+            result = []
+            for rs in data.next():
+                result.append(dict(zip([get_name(i) for i in self.select], rs)))
+        else:
+            data = self.execute_sql(SINGLE)
+            result = dict(zip([get_name(i) for i in self.select], data))
+
+        self.select = []
+        return result
+
     def get_count(self):
         """
         Performs a COUNT() query using the current filter constraints.
@@ -808,6 +834,53 @@
             self.fill_related_selections(f.rel.to._meta, alias, cur_depth + 1,
                     used, next, restricted)
 
+    def add_aggregate(self, aggregate_expr, aliased_name, model):
+        """
+        Adds a single aggregate expression to the Query
+        """
+        
+        field_list = aggregate_expr.split(LOOKUP_SEP)
+        opts = model._meta
+
+        aggregate_func = field_list.pop()
+        
+        if len(field_list) > 1:
+            field, target, opts, join_list, last = self.setup_joins(
+                field_list, opts, self.get_initial_alias(), False)
+            final = len(join_list)
+            penultimate = last.pop()
+            if penultimate == final:
+                penultimate = last.pop()
+            if len(join_list) > 1:
+                extra = join_list[penultimate:]
+                final = penultimate
+                col = self.alias_map[extra[0]][LHS_JOIN_COL]
+            else:
+                col = target.column
+                
+            field_name = field_list.pop()
+            alias = join_list[-1]
+            alias = extra[final]
+        else:
+            field_name = field_list[0]
+            alias = opts.db_table
+
+        class AggregateNode:
+            def __init__(self, field_name, aggregate_func, aliased_name, alias):
+                self.field_name = field_name
+                self.aggregate_func = aggregate_func
+                self.aliased_name = aliased_name
+                self.alias = alias
+                
+            def as_sql(self, quote_func=None):
+                if not quote_func:
+                    quote_func = lambda x: x
+                return '%s(%s.%s)' % (self.aggregate_func.upper(),
+                                      quote_func(self.alias),
+                                      quote_func(self.field_name))
+
+        self.aggregates.append(AggregateNode(field_name, aggregate_func, aliased_name, alias))
+        
     def add_filter(self, filter_expr, connector=AND, negate=False, trim=False,
             single_filter=False):
         """
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 7350)
+++ django/db/models/query.py	(working copy)
@@ -165,6 +165,17 @@
                 setattr(obj, k, row[i])
             yield obj
 
+    def aggregate(self, *args, **kwargs):
+        """
+        Returns the aggregation over the current model as values (or so it should).
+        """
+        if args:
+            TypeError('Unexpected positional arguments')
+            
+        for (aggregate_expr, alias) in kwargs.items():
+            self.query.add_aggregate(aggregate_expr, alias, self.model)
+        return self.query.get_aggregation()
+
     def count(self):
         """
         Performs a SELECT COUNT() and returns the number of records as an
@@ -342,7 +353,7 @@
         Returns a new QuerySet that is a copy of the current one. This allows a
         QuerySet to proxy for a model manager in some cases.
         """
-        return self._clone()
+        return self._clone()        
 
     def filter(self, *args, **kwargs):
         """
