public
Last active

Django - Generic Custom Model Manager for summarizing data by any field

  • Download Gist
1-models.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
'''
This Snippet, lets you create a generic custom model manager to summarize data on a table by any field.
 
Benefits:
- You wont be repeating yourself!
- A single url & template can be used to summarize by any field in your model
 
Example Usage: Book.counts.by(field, year, month, day) i.e Book.counts.by(category, 2009, 9, 24)
 
Notes:
- day is optional
- My current use case only requires summaries by month/day, this snippet could easily be modified to make both month and year optional using **kwargs
 
Instructions:
1. Create your custom model manager & assign it to your model (models.py)
2. Create your view (views.py)
3. Add urls (urls.py)
4. Create a new template tag and register it (get.py)
5. Customize your template
 
'''
from django.db import models
from django.db.models import Count
 
# Snippet for your models.py
class CountsManager(models.Manager):
def by(self, field, year, month, *args):
year = year
month = month
field = field
if args:
day = args[0]
return self.filter(pub_date_time__year=year).filter(pub_date_time__month=month).filter(pub_date_time__day=day).values(field).annotate(Count(field))
else:
return self.filter(pub_date_time__year=year).filter(pub_date_time__month=month).values(field).annotate(Count(field))
 
# Add the custom manager to your model
class Book(models.Model):
pub_date_time = models.DateTimeField(blank=True, null=True)
author = models.CharField(max_length=50,blank=True, null=True)
publisher = models.CharField(max_length=50,blank=True, null=True)
category = models.CharField(max_length=50,blank=True, null=True)
 
objects = models.Manager()
counts = CountsManager()
2-views.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
from django.views.generic.list_detail import object_list
from myproject.app.models import Book
 
# Snippet for your views.py
def by(request, field, year , month, **kwargs):
field = field
field_count = field + "__count"
context = {'year': year, 'month': month, 'field': field, 'field_count': field_count}
if kwargs:
day = kwargs['day']
query = Book.counts.by(field, year, month, day)
context['day'] = day
else:
query = Book.counts.by(field, year, month)
template = 'type.html'
return object_list(request,
queryset=query,
template_name = template,
extra_context = context
)
3-urls.py
Python
1 2 3 4 5 6 7 8
from django.conf.urls.defaults import *
 
# Snippet for your urls.py
urlpatterns = patterns('myapp.views',
url('^(?P<field>[\w-]+)/(?P<year>\d{4})/(?P<month>\d+)/$','by', name='count_link_month'),
url('^(?P<field>[\w-]+)/(?P<year>\d{4})/(?P<month>\d+)/(?P<day>\d+)/$','by', name='chart_link_day'),
)
4-get.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
from django.template import Library
 
register = Library()
 
# Add the following filter in your templatetags dir - Source: http://www.djangosnippets.org/snippets/1412/
 
@register.filter
def get( dict, key, default = '' ):
"""
Usage:
 
view:
some_dict = {'keyA':'valueA','keyB':{'subKeyA':'subValueA','subKeyB':'subKeyB'},'keyC':'valueC'}
keys = ['keyA','keyC']
template:
{{ some_dict|get:"keyA" }}
{{ some_dict|get:"keyB"|get:"subKeyA" }}
{% for key in keys %}{{ some_dict|get:key }}{% endfor %}
"""
 
try:
return dict.get(key,default)
except:
return default + 'Except Clause'
5-template.html
HTML
1 2 3 4
<-- Make your template generic by using the two variables (field & field__count) passed in the context variable customize the code below for your template template -->
{% for object in object_list %}
<h1>{{ object|get:field }} : {{ object|get:field_count }}</h1>
{% endfor %}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.