Skip to content

Instantly share code, notes, and snippets.

@codiez
Created November 12, 2009 20:44
Show Gist options
  • Save codiez/233262 to your computer and use it in GitHub Desktop.
Save codiez/233262 to your computer and use it in GitHub Desktop.
Django - Generic Custom Model Manager for summarizing data by any field
'''
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()
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
)
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'),
)
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'
<-- 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 %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment