from django.db import models, connection, backend # from django.db.backends import get_limit_offset_sql from django.contrib.auth.models import User from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager from django.contrib.contenttypes.models import ContentType from django.conf import settings from django.dispatch import dispatcher from django.core.cache import cache from zilbo.common.counter import signals from zilbo.common.utils.misc import get_content_type_id import datetime class PopularPaginator: def __init__(self, dbtable, limit, offset, content_type_id, fromtime=None): self.dbtable = dbtable self.limit = limit self.offset = offset self.content_type_id = content_type_id self.fromtime = fromtime def getwhere(self): sql = "where site_id=%s" if self.fromtime: sql = sql + " and effective_date >= %s" if self.content_type_id: sql = sql + " and content_type_id in ( %s )" % ",".join(self.content_type_id) sql = sql + " group by content_type_id, object_id" return sql def getsql(self): sql = """select content_type_id, object_id, sum( unique_views ) as sum_uv from %s %s order by sum_uv desc %s """ % ( self.dbtable, self.getwhere(), backend.get_limit_offset_sql( self.limit,self.offset)) return sql def getcountsql(self): sql = """select content_type_id, object_id from %s %s""" % ( self.dbtable, self.getwhere()) return sql def run(self): cursor = connection.cursor() sql = self.getcountsql() if self.fromtime: cursor.execute( sql, [ settings.SITE_ID, self.fromtime]) else: cursor.execute( sql, [ settings.SITE_ID ]) rows = cursor.fetchall() # print sql self.row_count = len(rows) # print len(rows) # for id in rows: # # print id # self.row_count += 1 sql = self.getsql() if self.fromtime: cursor.execute( sql, [ settings.SITE_ID, self.fromtime]) else: cursor.execute( sql, [ settings.SITE_ID ]) rows = cursor.fetchall() ids = [] for id in rows: ids.append( ( id[0], id[1], id[2] )) return ids def get_count(self): return self.row_count class ObjectCounter(models.Model): content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.IntegerField('object ID', db_index=True) last_change = models.DateTimeField('last changed', auto_now=True) unique_views = models.IntegerField() site = models.ForeignKey(Site, default=settings.SITE_ID, blank=True) objects = CurrentSiteManager() content_object = models.GenericForeignKey() class Meta: unique_together = (('site', 'content_type','object_id'),) def save(self): self.site_id = settings.SITE_ID super(ObjectCounter, self).save() @classmethod def most_popular(cls, limit=40, offset=0, content_type_id=None): if type(content_type_id).__name__ == "list": content_type_id = [str(z) for z in content_type_id ] cache_key = 'OC_most_popular_%s_%s_%s_%s' % (settings.SITE_ID, limit, offset, ",".join(content_type_id) ) elif content_type_id: cache_key = 'OC_most_popular_%s_%s_%s_%s' % (settings.SITE_ID, limit, offset, content_type_id ) content_type_id = [ str(content_type_id) ] else: cache_key = 'OC_most_popular_%s_%s_%s' % (settings.SITE_ID, limit, offset ) ids = cache.get( cache_key ) if ids: return ids pp = PopularPaginator( ObjectCounter._meta.db_table, limit, offset, content_type_id, fromtime=None) rows = pp.run() count = pp.get_count() ids = {'count':count, 'rows':rows} # cache it for 30 minutes cache.set( cache_key, ids, 1800 ) return ids class ObjectDateCounter(models.Model): content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.IntegerField('object ID', db_index=True) effective_date = models.DateField() unique_views = models.IntegerField() site = models.ForeignKey(Site, default=settings.SITE_ID, blank=True) objects = CurrentSiteManager() content_object = models.GenericForeignKey() def save(self): self.site_id = settings.SITE_ID super(ObjectDateCounter, self).save() class Meta: unique_together = (('site', 'content_type','object_id', 'effective_date' ),) @classmethod def most_popular(cls, days=7, limit=40, offset=0, content_type_id=None): if type(content_type_id).__name__ == "list": content_type_id = [str(z) for z in content_type_id ] cache_key = 'ODC_most_popular_%s_%s_%s_%s_%s' % (settings.SITE_ID, days, limit, offset, ",".join(content_type_id) ) elif content_type_id: cache_key = 'ODC_most_popular_%s_%s_%s_%s_%s' % (settings.SITE_ID, days, limit, offset, content_type_id ) content_type_id = [ str(content_type_id) ] else: cache_key = 'ODC_most_popular_%s_%s_%s_%s' % (settings.SITE_ID, days, limit, offset ) ids = cache.get( cache_key ) if ids: return ids now = datetime.datetime.now() past = now - datetime.timedelta(days=days) pp = PopularPaginator( ObjectDateCounter._meta.db_table, limit, offset, content_type_id, fromtime=past) rows = pp.run() count = pp.get_count() ids = {'count':count, 'rows':rows} # cache it for 30 minutes cache.set( cache_key, ids, 1800 ) return ids class ObjectHourCounter(models.Model): content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.IntegerField(_("Primary Key of Reference Object"), db_index=True) effective_date = models.DateTimeField(_("Hour")) unique_views = models.IntegerField(_("Unique Views")) site = models.ForeignKey(Site, default=settings.SITE_ID, blank=True) objects = CurrentSiteManager() content_object = models.GenericForeignKey() def save(self): self.site_id = settings.SITE_ID super(ObjectHourCounter, self).save() class Meta: unique_together = (('site', 'content_type','object_id', 'effective_date' ),) @classmethod def most_popular(cls, hours=24, limit=40, offset=0, content_type_id=None): if type(content_type_id).__name__ == "list": content_type_id = [str(z) for z in content_type_id ] cache_key = 'OHC_most_popular_%s_%s_%s_%s_%s' % (settings.SITE_ID, hours, limit, offset,",".join(content_type_id) ) elif content_type_id: cache_key = 'OHC_most_popular_%s_%s_%s_%s_%s' % (settings.SITE_ID, hours, limit, offset, content_type_id ) content_type_id = [ str(content_type_id) ] else: cache_key = 'OHC_most_popular_%s_%s_%s_%s' % (settings.SITE_ID, hours, limit, offset ) ids = cache.get( cache_key ) # ids=None if ids: return ids now = datetime.datetime.now() past = now - datetime.timedelta(hours=hours) pp = PopularPaginator( ObjectHourCounter._meta.db_table, limit, offset, content_type_id, fromtime=past) rows = pp.run() count = pp.get_count() ids = {'count':count, 'rows':rows} # cache it for 30 minutes cache.set( cache_key, ids, 1800 ) return ids class ObjectUserCounter(models.Model): content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.IntegerField('object ID', db_index=True) last_change = models.DateTimeField('last changed', auto_now=True) views = models.IntegerField() user = models.ForeignKey(User, null=True, blank=True, db_index=True) session_key = models.CharField('session key', blank=True, maxlength=40, db_index=True) site = models.ForeignKey(Site, default=settings.SITE_ID, blank=True) objects = CurrentSiteManager() content_object = models.GenericForeignKey() class Meta: unique_together = (('site', 'content_type', 'object_id', 'user','session_key' ),) def save(self): self.site_id = settings.SITE_ID super(ObjectUserCounter, self).save() class ObjectDateUserCounter(models.Model): content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.IntegerField('object ID', db_index=True) effective_date = models.DateField() user = models.ForeignKey(User, null=True, blank=True, db_index=True) session_key = models.CharField('session key', blank=True, maxlength=40, db_index=True) views = models.IntegerField() site = models.ForeignKey(Site, default=settings.SITE_ID, blank=True) objects = CurrentSiteManager() content_object = models.GenericForeignKey() def get_content_object(self): """ Returns the object that this comment is a comment on. Returns None if the object no longer exists. """ try: return self.content_type.get_object_for_this_type(pk=self.object_id) except ObjectDoesNotExist: return None get_content_object.short_description = _('Content object') class Meta: unique_together = (('site', 'content_type', 'object_id', 'effective_date', 'user','session_key' ),) def save(self): self.site_id = settings.SITE_ID super(ObjectDateUserCounter, self).save() class ObjectHourUserCounter(models.Model): content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.IntegerField('object ID', db_index=True) effective_date = models.DateTimeField() user = models.ForeignKey(User, null=True, blank=True, db_index=True) session_key = models.CharField('session key', blank=True, maxlength=40, db_index=True) views = models.IntegerField() site = models.ForeignKey(Site, default=settings.SITE_ID, blank=True) objects = CurrentSiteManager() content_object = models.GenericForeignKey() class Meta: unique_together = (('site', 'content_type','object_id', 'effective_date', 'user','session_key' ),) def save(self): self.site_id = settings.SITE_ID super(ObjectHourUserCounter, self).save() def inc_object_view( object, request ): now = datetime.datetime.now() this_hour = datetime.datetime( now.year, now.month, now.day, now.hour, 0, 0, 0 ) this_day = datetime.datetime( now.year, now.month, now.day, 0, 0, 0, 0 ) session = "" user_id = 0 if request.user.is_anonymous(): session = request.session.session_key if session is None: return else: user = request.user user_id = user.id ct_id = get_content_type_id ( object ) obj, created = ObjectHourUserCounter.objects.get_or_create( content_type__id__exact = ct_id, object_id = object.id, effective_date= this_hour, user__id__exact = user_id, session_key = session, defaults={'views':1, 'content_type_id':ct_id, 'user_id':user_id, 'session_key': session , 'effective_date':this_hour, 'object_id': object.id } ) if not created: obj.views += 1 obj.save() return obj, created = ObjectHourCounter.objects.get_or_create( content_type__id__exact = ct_id, object_id = object.id, effective_date= this_hour, defaults={'unique_views':1, 'content_type_id':ct_id, 'effective_date':this_hour, 'object_id': object.id } ) if not created: obj.unique_views += 1 obj.save() obj, created = ObjectDateUserCounter.objects.get_or_create( content_type__id__exact = ct_id, object_id = object.id, effective_date= this_day, user__id__exact = user_id, session_key = session, defaults={'views':1, 'content_type_id':ct_id, 'user_id':user_id, 'session_key': session, 'effective_date':this_day, 'object_id': object.id } ) if not created: obj.views += 1 obj.save() return obj, created = ObjectDateCounter.objects.get_or_create( content_type__id__exact = ct_id, object_id = object.id, effective_date= this_day, defaults={'unique_views':1, 'content_type_id':ct_id, 'effective_date':this_day, 'object_id': object.id } ) if not created: obj.unique_views += 1 obj.save() obj, created = ObjectUserCounter.objects.get_or_create( content_type__id__exact = ct_id, object_id = object.id, user__id__exact = user_id, session_key = session, defaults={'views':1, 'content_type_id':ct_id, 'user_id':user_id, 'session_key': session, 'object_id': object.id } ) if not created: obj.views += 1 obj.save() return obj, created = ObjectCounter.objects.get_or_create( content_type__id__exact = ct_id, object_id = object.id, defaults={'unique_views':1, 'last_change':now, 'content_type_id':ct_id, 'object_id': object.id } ) if not created: obj.unique_views += 1 obj.last_change = now obj.save() dispatcher.connect( inc_object_view, signal=signals.object_viewed)