Anonymous avatar Anonymous committed a8d8182

Added utility template filters.

Comments (0)

Files changed (5)

 
 The *value* returned by custom stats is considered safe, so it can be an
 html string too.
+
+
+Template filters
+~~~~~~~~~~~~~~~~
+
+This application provides a set of aggrgation template filters too:
+
+    - avg_of
+    - sum_of
+    - min_of
+    - max_of
+    - count_of
+
+Each one is used over a queryset and return the aggregation of
+the given field, e.g.:
+
+.. code-block:: html+django
+
+    {{ myqueriset|avg_of:'field' }}
+
+or:
+
+.. code-block:: html+django
+
+    {% with objects|sum_of:'hours' as total_hours %}
+        Total hours: {{ total_hours }}
+    {% endwith %}

admin_stats/__init__.py

-VERSION = (0, 1)
+VERSION = (0, 2)

admin_stats/templatetags/admin_stats_tags.py

 import re
 
 from django import template
+from django.db.models import Avg, Sum, Min, Max, Count
 
 from admin_stats import models
 
 @register.tag
 def collect_stats(parser, token):
     """
-    Usage::
+    Usage:
+
+    .. code-block:: html+django
     
         {% collect_stats for cl as varname %}
     
         # calling all stats callbales
         context[self.varname] = [i(request, objects, data) for i in callables]
         return u''
+
+
+# UTILITY FILTERS (actually not used by the app)
+
+def _get_aggregation_filter(func):
+    """
+    This is a filter factory that creates the following filters:
+        - avg_of
+        - sum_of
+        - min_of
+        - max_of
+        - count_of
+    Each one is used over a queryset and return the aggregation of
+    the given field, e.g.:
+
+    .. code-block:: html+django
+
+        {{ myqueriset|avg_of:'field' }}
+    """
+    def aggregation_filter(queryset, field):
+        aggregations = queryset.aggregate(aggregated=func(field))
+        return aggregations['aggregated']
+    return aggregation_filter
+
+for func in Avg, Sum, Min, Max, Count:
+    filter_name = '%s_of' % (func.name.lower())
+    register.filter(name=filter_name)(_get_aggregation_filter(func))

admin_stats/tests.py

 import unittest
 
 from django.db import models as django_models
+from django.template import Template, Context
 
 from admin_stats import admin, models
 from admin_stats.templatetags import admin_stats_tags
 
 
 class ModelTestCase(unittest.TestCase, AdminStatsTestMixin):
-    def setUp(self):
+    def setUp(self):  
         self.create_instances(1, 3, 5, 8, 13)
 
     def test_aggregates(self):
         
     def tearDown(self):
         self.clean()
+
+
+class TemplatetagsTestCase(unittest.TestCase, AdminStatsTestMixin):
+    def setUp(self):
+        self.create_instances(1, 3, 5, 8, 13)
+
+    def render(self, template, context_dict):
+        context = Context(context_dict.copy())
+        return Template(template).render(context)
+
+    def test_utils(self):
+        template = u"""
+            {% load admin_stats_tags %}
+            {{ queryset|avg_of:'value' }}
+            {{ queryset|sum_of:'value' }}
+            {{ queryset|min_of:'value' }}
+            {{ queryset|max_of:'value' }}
+            {{ queryset|count_of:'value' }}
+        """
+        context_dict = {
+            'queryset': self.all(),
+        }
+        html = self.render(template, context_dict)
+        expected = [u'6.0', u'30', u'1', u'13', u'5']
+        self.assertEqual(html.split(), expected)
+        
+    def tearDown(self):
+        self.clean()
 
 The *value* returned by custom stats is considered safe, so it can be an
 html string too.
+
+
+Template filters
+~~~~~~~~~~~~~~~~
+
+This application provides a set of aggrgation template filters too:
+
+    - avg_of
+    - sum_of
+    - min_of
+    - max_of
+    - count_of
+
+Each one is used over a queryset and return the aggregation of
+the given field, e.g.:
+
+.. code-block:: html+django
+
+    {{ myqueriset|avg_of:'field' }}
+
+or:
+
+.. code-block:: html+django
+
+    {% with objects|sum_of:'hours' as total_hours %}
+        Total hours: {{ total_hours }}
+    {% endwith %}
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.