## Middleware.py
from tags.models import Tag
# must have a url expression similar to the one below in order to use this
# (r'^tags/(?P<tag>[-\w]+)/$','show_view'),

class TagClicksMiddleware(object):
    """
    This middleware class increments the
	number of times that a user clicks on a particular tag
    """
    def process_response(self, request, response):
        # this is kinda hackish but it works.
        try:
            tag_url = request.META['PATH_INFO'].split('/tags/')
            tag_url = tag_url[1][:-1]
            tags = Tag.objects.get(slug__exact=tag_url)
            tags.clicks = tags.clicks + 1
            tags.save() 
        except:
            return response
        return response

## models.py

from django.db import models
from django.contrib.contenttypes.models import ContentType

class Tag(models.Model):
    """
    This is the table that holds our tag names associated with our blog
    """
    name = models.CharField(max_length=25)
    slug = models.SlugField(prepopulate_from=('name',))
    clicks = models.IntegerField(null=True, default=0)
    content_type = models.ForeignKey(ContentType,)
    
    class Meta:
        db_table = 'tags'
        verbose_name = 'tag'
        verbose_name_plural = 'tags'
        
    class Admin:
        fields = (
            ('Tag Form', {
                'fields': ('name', 'slug', 'content_type')
            }),
        )

        list_display = ('name', 'clicks', 'content_type')
        list_filter = ('content_type',)
        search_fields = ['name', 'content_type']
        ordering = ['name']

    def get_absolute_url(self):
        """Returns the associated tag URl"""
        return "/%s/tags/%s/" % (self.content_type.app_label,self.slug)
        
    def __str__(self):
        return '%s' % self.name

## tag_processor.py

from django.db.models import get_model
from tags.models import Tag
 
def tag_cloud_processor(model_name, buckets=4, base_font_size=8,cloud_size=12):
    """
    Tag cloud processor returns the most used tags for a particular application.
    """
    if model_name:
        try:
            tag_list = Tag.objects.filter(content_type__app_label__exact=model_name)[:cloud_size]
        except:
            tag_list = None
        tag_range = []
        thresholds = []
        tags = []
        if tag_list:
            for tag in tag_list:
                tag_range.append(float(getattr(tag, model_name).count()))
            max_tag = max(tag_range) or None
            min_tag = min(tag_range) or None
            if max_tag and min_tag:
                delta = (max_tag - min_tag) / float(buckets)
                for i in range(1,buckets + 1):
                    thresh_value = min_tag + i * delta
                    thresholds.append(thresh_value)
                for tag in tag_list:
                    for bucket in range(1,buckets + 1):
                        if float(getattr(tag, model_name).count()) <= thresholds[bucket]:
                            tags.append({"tag":tag, "font_size":(base_font_size + bucket * 2)})
                            break
                return tags
            else:
                return []
        else:
            return []
    else:
        return []


# must have a url expression similar to the one below in order to use this function
# (r'^tags/(?P<tag>[-\w]+)/$','show_view'),

def popular_tag_cloud(buckets=4, base_font_size=8,cloud_size=12):
    """
    Tag cloud processor that returns a list of the top tags that users have clicked.
    """
    try:
        tag_clicks = Tag.objects.filter(clicks__gte=1).order_by('clicks')[:cloud_size]
        tag_filter = [tag.clicks for tag in tag_clicks]
        tag_list = Tag.objects.filter(clicks__in=tag_filter)[:cloud_size]
    except:
        tag_list = None
    tag_range = []
    thresholds = []
    tags = []
    if tag_list:
        for tag in tag_list:
            tag_range.append(float(tag.clicks))
        max_tag = max(tag_range) or None
        min_tag = min(tag_range) or None
        if max_tag and min_tag:
            delta = (max_tag - min_tag) / float(buckets)
            for i in range(1, buckets + 1):
                thresh_value = min_tag + i * delta
                thresholds.append(thresh_value)
            for tag in tag_list:
                for bucket in range(1, buckets + 1):
                    if tag.clicks <= thresholds[bucket]:
                        tags.append({"tag":tag, "font_size":(base_font_size + bucket * 2)})
                        break
            return tags
        else:
            return []
    else:
        return []