You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

157 lines
6.7 KiB

"""Views for emencia.django.newsletter statistics"""
import csv
from datetime import timedelta
from django.db.models import Q
from django.http import HttpResponse
from django.template import RequestContext
from django.utils.encoding import smart_str
from django.utils.translation import ugettext as _
from django.shortcuts import get_object_or_404
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.template.defaultfilters import date
from emencia.django.newsletter.utils.ofc import Chart
from emencia.django.newsletter.models import Newsletter
from emencia.django.newsletter.models import ContactMailingStatus
from emencia.django.newsletter.utils.statistics import get_newsletter_top_links
from emencia.django.newsletter.utils.statistics import get_newsletter_statistics
from emencia.django.newsletter.utils.statistics import get_newsletter_opening_statistics
from emencia.django.newsletter.utils.statistics import get_newsletter_clicked_link_statistics
BG_COLOR = '#ffffff'
GRID_COLOR = '#eeeeee'
AXIS_COLOR = '#666666'
BAR_COLOR_1 = '#5b80b2'
BAR_COLOR_2 = '#ff3333'
BAR_COLOR_3 = '#9459b4'
BAR_COLOR_4 = '#5eca71'
def get_statistics_period(newsletter):
status = ContactMailingStatus.objects.filter(Q(status=ContactMailingStatus.OPENED) |
Q(status=ContactMailingStatus.OPENED_ON_SITE) |
Q(status=ContactMailingStatus.LINK_OPENED),
newsletter=newsletter)
if not status:
return []
start_date = newsletter.sending_date.date()
end_date = status.latest('creation_date').creation_date.date()
period = []
for i in range((end_date - start_date).days + 1):
period.append(start_date + timedelta(days=i))
return period
@login_required
def view_newsletter_statistics(request, slug):
"""Display the statistics of a newsletters"""
opts = Newsletter._meta
newsletter = get_object_or_404(Newsletter, slug=slug)
context = {'title': _('Statistics of %s') % newsletter.__unicode__(),
'object': newsletter,
'opts': opts,
'object_id': newsletter.pk,
'app_label': opts.app_label,
'stats': get_newsletter_statistics(newsletter),
'period': get_statistics_period(newsletter)}
return render_to_response('newsletter/newsletter_statistics.html',
context, context_instance=RequestContext(request))
@login_required
def view_newsletter_report(request, slug):
newsletter = get_object_or_404(Newsletter, slug=slug)
status = ContactMailingStatus.objects.filter(newsletter=newsletter,
creation_date__gte=newsletter.sending_date)
links = set([s.link for s in status.exclude(link=None)])
def header_line(links):
link_cols = [smart_str(link.title) for link in links]
return [smart_str(_('first name')), smart_str(_('last name')),
smart_str(_('email')), smart_str(_('openings'))] + link_cols
def contact_line(contact, links):
contact_status = status.filter(contact=contact)
link_cols = [contact_status.filter(status=ContactMailingStatus.LINK_OPENED,
link=link).count() for link in links]
openings = contact_status.filter(Q(status=ContactMailingStatus.OPENED) |
Q(status=ContactMailingStatus.OPENED_ON_SITE)).count()
return [smart_str(contact.first_name), smart_str(contact.last_name),
smart_str(contact.email), openings] + link_cols
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=report-%s.csv' % newsletter.slug
writer = csv.writer(response)
writer.writerow(header_line(links))
for contact in newsletter.mailing_list.expedition_set():
writer.writerow(contact_line(contact, links))
return response
@login_required
def view_newsletter_density(request, slug):
newsletter = get_object_or_404(Newsletter, slug=slug)
status = ContactMailingStatus.objects.filter(newsletter=newsletter,
creation_date__gte=newsletter.sending_date)
context = {'object': newsletter,
'top_links': get_newsletter_top_links(status)['top_links']}
return render_to_response('newsletter/newsletter_density.html',
context, context_instance=RequestContext(request))
@login_required
def view_newsletter_charts(request, slug):
newsletter = get_object_or_404(Newsletter, slug=slug)
start = int(request.POST.get('start', 0))
end = int(request.POST.get('end', 6))
recipients = newsletter.mailing_list.expedition_set().count()
sending_date = newsletter.sending_date.date()
labels, clicks_by_day, openings_by_day = [], [], []
for i in range(start, end + 1):
day = sending_date + timedelta(days=i)
day_status = ContactMailingStatus.objects.filter(newsletter=newsletter,
creation_date__day=day.day,
creation_date__month=day.month,
creation_date__year=day.year)
opening_stats = get_newsletter_opening_statistics(day_status, recipients)
click_stats = get_newsletter_clicked_link_statistics(day_status, recipients, 0)
# Labels
labels.append(date(day, 'D d M y').capitalize())
# Values
openings_by_day.append(opening_stats['total_openings'])
clicks_by_day.append(click_stats['total_clicked_links'])
b1 = Chart(type='bar_3d', colour=BAR_COLOR_1,
text=_('Total openings'), tip=_('#val# openings'),
on_show={'type': 'grow-up'}, values=openings_by_day)
b2 = Chart(type='bar_3d', colour=BAR_COLOR_2,
text=_('Total clicked links'), tip=_('#val# clicks'),
on_show={'type': 'grow-up'}, values=clicks_by_day)
chart = Chart(bg_colour=BG_COLOR)
chart.title.text = _('Consultation histogram')
chart.title.style = '{font-size: 16px; color: #666666; text-align: center; font-weight: bold;}'
chart.y_axis = {'colour': AXIS_COLOR, 'grid-colour': GRID_COLOR,
'min': 0, 'max': max(openings_by_day + clicks_by_day) + 2,
'steps': max(openings_by_day) / 5}
chart.x_axis = {'colour': AXIS_COLOR, 'grid-colour': GRID_COLOR,
'3d': 5, 'labels': {'labels': labels, 'rotate': 60}}
chart.elements = [b1, b2]
return HttpResponse(chart.render())