# Create your views here. from django.http import Http404, HttpResponse, HttpResponseForbidden from django.conf import settings from django.template import loader, RequestContext from django.core.exceptions import ObjectDoesNotExist from django.dispatch import dispatcher from django.contrib.auth.views import redirect_to_login from django.contrib.sites.models import Site from django.contrib.auth.models import User from django.contrib.sessions.middleware import SessionWrapper from django.contrib.sessions.models import Session from django.utils import feedgenerator from django.utils.html import strip_tags from django.utils.text import truncate_words from django.utils.cache import patch_vary_headers from zilbo.common.counter import signals from zilbo.common.utils.misc import get_object from zilbo.common.utils.misc import get_content_type, get_content_type_id, verify_objref_hash, get_content_type_id_by_modelname from zilbo.common.counter.models import ObjectCounter, ObjectDateCounter, ObjectHourCounter, ObjectDateUserCounter, ObjectHourUserCounter from zilbo.common.utils.misc import verify_objref_hash import datetime import sys def inc_object(request, content_type_id, object_id ): """ this view is purely for debugging, it should not be enabled in production mode """ if settings.DEBUG: obj = get_object( content_type_id, object_id ) dispatcher.send(signal=signals.object_viewed , request=request, object = obj ) return HttpResponse("OK") else: raise Http404("Not Available in production mode") def by_object( request, content_type_id, object_id, hash, template_name="counter/by_object.html", template_name_field=None, template_loader=loader, extra_lookup_kwargs={}, context_processors=None, template_object_name ='object', extra_context=None, mimetype=None, privacy=False): if extra_context is None: extra_context = {} if not request.user.is_anonymous(): if not request.user.is_staff: if not verify_objref_hash( content_type_id, object_id, hash ): raise Http404("I can't find that" ) obj = get_object( content_type_id, object_id ) if privacy: if request.user.is_anonymous(): return redirect_to_login(request.path) if not request.user.is_staff: try: if not obj.create_user == request.user: return HttpResponseForbidden("only the person who created the object can view who has viewed it"); except: return HttpResponseForbidden("you can't watch that object"); try: oc = ObjectCounter.objects.get( content_type__id = content_type_id, object_id = object_id ) except ObjectCounter.DoesNotExist: oc = None odc = ObjectDateCounter.objects.filter( content_type__id= content_type_id, object_id = object_id ).order_by('effective_date') dates={} last=None date_max=0 for i in odc: if last is None: last = i.effective_date if i.effective_date < last: last = i.effective_date if date_max < i.unique_views: date_max = i.unique_views dates[ i.effective_date ] = i.unique_views today = datetime.date.today() darr=[] if last is not None: while today > last: try: darr.append( ( last, dates[ last ]) ) except: darr.append( (last,0 )) last = last + datetime.timedelta(1) ohc = ObjectHourCounter.objects.filter( content_type__id= content_type_id, object_id = object_id ).order_by('effective_date') hours={} last=None hour_max=0 for i in ohc: if last is None: last = i.effective_date if i.effective_date < last: last = i.effective_date if hour_max < i.unique_views: hour_max = i.unique_views hours[ i.effective_date ] = i.unique_views harr=[] now = datetime.datetime.now() if last is not None: while now > last: try: harr.append( ( last, hours[ last ]) ) except: harr.append( (last,0 )) last = last + datetime.timedelta( hours=1 ) if not template_name: template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower()) if template_name_field: template_name_list = [getattr(obj, template_name_field), template_name] t = template_loader.select_template(template_name_list) else: t = template_loader.get_template(template_name) c = RequestContext(request, { template_object_name: obj, 'overall': oc, 'dates': darr, 'hours': harr, 'odc': odc, 'ohc': ohc, }, context_processors) for key, value in extra_context.items(): if callable(value): c[key] = value() else: c[key] = value response = HttpResponse(t.render(c), mimetype=mimetype) return response def by_user( request, slug=None, template_name="counter/by_user.html", template_name_field=None, template_loader=loader, extra_lookup_kwargs={}, context_processors=None, template_object_name ='object', extra_context=None, mimetype=None, privacy=True): if extra_context is None: extra_context = {} if request.user.is_anonymous(): return redirect_to_login(request.path) if request.user.is_staff: if slug is None: user = request.user else: user = User.objects.get( username = slug ) else: user = request.user odc = ObjectDateUserCounter.objects.filter( user = user ).order_by('-effective_date')[:30] if not template_name: template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower()) if template_name_field: template_name_list = [getattr(obj, template_name_field), template_name] t = template_loader.select_template(template_name_list) else: t = template_loader.get_template(template_name) c = RequestContext(request, { template_object_name: user, 'odc': odc, }, context_processors) for key, value in extra_context.items(): if callable(value): c[key] = value() else: c[key] = value response = HttpResponse(t.render(c), mimetype=mimetype) return response def by_session( request, session_key=None, template_name="counter/by_session.html", template_name_field=None, template_loader=loader, extra_lookup_kwargs={}, context_processors=None, template_object_name ='object', extra_context={}, mimetype=None, privacy=True): if not request.user.is_anonymous(): if not request.user.is_staff: session_key = request.session.session_key if session_key is None: session_key = request.session.session_key odc = ObjectDateUserCounter.objects.filter( session_key = session_key ).order_by('-effective_date')[:30] if template_name_field: template_name_list = [getattr(obj, template_name_field), template_name] t = template_loader.select_template(template_name_list) else: t = template_loader.get_template(template_name) c = RequestContext(request, { template_object_name: session_key, 'odc': odc, }, context_processors) for key, value in extra_context.items(): if callable(value): c[key] = value() else: c[key] = value response = HttpResponse(t.render(c), mimetype=mimetype) return response def build_popular_object_list( poptype="hours",amount=24, limit=40, offset=0, content_type_id=None ): if poptype == "hours": u = ObjectHourCounter.most_popular( hours=amount, limit=limit, offset=offset, content_type_id = content_type_id ) elif poptype == "days": u = ObjectDateCounter.most_popular( days=amount, limit=limit, offset=offset, content_type_id = content_type_id ) else: u = ObjectCounter.most_popular( limit=limit, offset=offset, content_type_id = content_type_id ) ids = u['rows'] objects=[] for id in ids: # XXX optimize this so that it only does a single query per content-type try: objects.append( (get_object( id[0],id[1]), id[2])) except ObjectDoesNotExist: pass # print u return (u['count'], objects) def popular(request, models="", amount=None, poptype="hours", paginate_by=10, page=None,base="", allow_empty=False, template_name="counter/popular_list.html", template_loader=loader, extra_context=None, context_processors=None, template_object_name='object', mimetype=None): if extra_context is None: extra_context = {} else: extra_context = extra_context.copy() if amount is not None: amount = int(amount) ids=[] if models is not None: for model in models.split(","): ids.append( get_content_type_id_by_modelname(model)) if not page: page = request.GET.get('page', 1) try: page = int(page) except ValueError: page = 1 basepath = request.path[:request.path.rfind(base)] if poptype == 'hours': feedpath = "%s%sh/%d/feed/" % (basepath,base,amount) elif poptype == 'days': feedpath = "%s%sd/%d/feed/" % (basepath,base,amount) else: feedpath = "%s%so/feed/" % (basepath,base) total, object_list = build_popular_object_list( poptype, amount, offset=(page-1)*paginate_by, limit=paginate_by, content_type_id=ids ) c = RequestContext(request, { '%s_list' % template_object_name: object_list, 'is_paginated': True, 'feedpath': feedpath, 'results_per_page': paginate_by, 'has_next': page*paginate_by < total, 'has_previous': page > 1, 'page': page, 'next': page + 1, 'base': base, 'basepath':basepath, 'previous': page - 1, 'pages': int(total / paginate_by)+1, 'hits' : total, }, context_processors) for key, value in extra_context.items(): if callable(value): c[key] = value() else: c[key] = value c['basepath']=basepath t = template_loader.get_template(template_name) return HttpResponse(t.render(c), mimetype=mimetype) def popular_feed(request, feedclass=feedgenerator.Atom1Feed, base="/popular/", models="", amount=None, poptype="hours", limit=40, content_type_id=None, user_id=None, hash=None, session_key = None ): if content_type_id is not None and verify_objref_hash( content_type_id, user_id, hash ): try: request.user = User.objects.get(pk=user_id) except (KeyError, User.DoesNotExist): pass else: if session_key: try: request.session = Session.objects.get(pk=session_key ) except (KeyError, Session.DoesNotExist): pass site = Site.objects.get_current() if amount is not None: amount = int(amount) ids=[] if models is not None: for model in models.split(","): ids.append( get_content_type_id_by_modelname(model)) total, object_list = build_popular_object_list( poptype, amount, offset=0, limit=limit, content_type_id=ids ) feed = feedclass( title="%s: popular items" % site.name, link="http://%s/" % site.domain, description="popular items on %s" % site.name, feed_url='http://%s/%s/' % (site.domain, base )) for tuple in object_list: obj = tuple[0] post_link = "http://%s%s" % ( site.domain, obj.get_absolute_url() ) email = "nobody@example.com" unique_id = "http://%s/%s/" % ( site.domain, obj.get_absolute_url() ) feed.add_item( title = str(obj).decode('utf-8'), link = post_link, description = truncate_words(strip_tags( obj.description_html.decode('utf-8')),150), author_email = email, author_name = 'not yet', pubdate = obj.creation_date, unique_id = unique_id.decode('utf-8'), categories = [tag.tag.name.decode('utf-8') for tag in obj.summary_tags.order_by('-weight')[:30]]) response = HttpResponse(mimetype=feed.mime_type) # per host caching patch_vary_headers(response, ['Host']) feed.write(response, 'utf-8') return response