newsletter statistics

remotes/origin/1203
Ivan Kovalkovskyi 10 years ago
parent 94700c72e6
commit d1ca638409
  1. 9
      emencia/django/newsletter/admin_urls.py
  2. 28
      emencia/django/newsletter/views/admin_views.py
  3. 17
      functions/forms.py
  4. 1
      templates/admin/newsletters/newsletter_history.html
  5. 2
      templates/admin/newsletters/newsletter_list.html
  6. 62
      templates/admin/newsletters/newsletter_stat.html

@ -2,17 +2,18 @@ from django.conf.urls import url
from django.conf.urls import patterns
from emencia.django.newsletter.views.admin_views import ContactList, UpdateContact, MailingListView, UpdateMailingList,\
CreateMailingList, NewsletterListView, NewsletterCreate, ExportContacts, DeleteContact, NewsletterUpdate, \
DeleteMailingList, ImportContacts, NewsletterHistory
DeleteMailingList, ImportContacts, NewsletterHistory, NewsletterStatistics
urlpatterns = patterns('',
url(r'^newsletters/all/$', NewsletterListView.as_view(), name='newsletters_newsletters_list'),
url(r'^newsletters/(?P<pk>\d+)/edit/', NewsletterUpdate.as_view(), name='newsletters_newsletters_update'),
url(r'^newsletters/(?P<pk>\d+)/edit/$', NewsletterUpdate.as_view(), name='newsletters_newsletters_update'),
url(r'^newsletters/(?P<pk>\d+)/history/', NewsletterHistory.as_view(), name='newsletters_newsletters_history'),
url(r'^newsletters/(?P<pk>\d+)/test/',
url(r'^newsletters/(?P<pk>\d+)/statistics/', NewsletterStatistics.as_view(), name='newsletters_newsletters_stat'),
url(r'^newsletters/(?P<pk>\d+)/test/$',
'emencia.django.newsletter.views.admin_views.send_test_newsletter',
name='newsletters_newsletters_send_test'),
url(r'^newsletters/', NewsletterCreate.as_view(), name='newsletters_newsletters_create'),
url(r'^newsletters/$', NewsletterCreate.as_view(), name='newsletters_newsletters_create'),
url(r'^mailinglist/all/$', MailingListView.as_view(), name='newsletters_mailinglist'),

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from django.views.generic import CreateView, ListView, UpdateView, DeleteView, FormView
from django.views.generic import CreateView, ListView, UpdateView, DeleteView, FormView, DetailView
from django.conf import settings
from django.utils import translation
from django.utils.translation import ugettext_lazy as _
@ -240,6 +240,32 @@ class NewsletterHistory(ListView):
context['choices'] = ContactMailingStatus.STATUS_CHOICES
return context
class NewsletterStatistics(DetailView):
model = Newsletter
template_name = 'admin/newsletters/newsletter_stat.html'
def get_context_data(self, **kwargs):
context = super(NewsletterStatistics, self).get_context_data(**kwargs)
sent = self.object.contactmailingstatus_set.filter(status=ContactMailingStatus.SENT).count()
errors = self.object.contactmailingstatus_set.filter(status=ContactMailingStatus.ERROR).count()
opened = self.object.contactmailingstatus_set.filter(status=ContactMailingStatus.OPENED).count()
unsubscribed = self.object.contactmailingstatus_set.filter(status=ContactMailingStatus.UNSUBSCRIPTION).count()
no_data = self.object.contactmailingstatus_set.filter(status=ContactMailingStatus.ANNOUNCE_NO_DATA).count()
links = self.object.contactmailingstatus_set.filter(status=ContactMailingStatus.LINK_OPENED).count()
CMS = ContactMailingStatus
opened_percent = 0 if opened or sent == 0 else (float(opened)/sent)*100
unsub_percent = 0 if unsubscribed or sent == 0 else (float(unsubscribed)/sent)*100
stat = {
'sent':{'data':sent, 'filter':""},
'errors':{ 'data':errors, 'filter':CMS.ERROR},
'opened':{'data': opened, 'filter': CMS.OPENED, 'percent': opened_percent},
'unsub':{'data': unsubscribed, 'filter': CMS.UNSUBSCRIPTION, 'percent': unsub_percent},
'no_data':{'data': no_data, 'filter': CMS.ANNOUNCE_NO_DATA},
'links':{'data': links, 'filter': CMS.LINK_OPENED}}
context.update({'stat': stat})
return context
class ExportContacts(FormView):
form_class = ContactFilterForm

@ -97,10 +97,10 @@ class TranslatableModelForm(forms.ModelForm):
if field.name not in veto_fields}
for code, name in settings.LANGUAGES:
# todo: fix requirements - where field is required default language must be required to)
for tr_field in self.translatable_fields:
field = fkwargs[tr_field].formfield()
field.required = False
if code != get_language():
field.required = False
self.fields[tr_field+"_"+code] = field
def clean(self):
@ -126,14 +126,13 @@ class TranslatableModelForm(forms.ModelForm):
translations = {obj.language_code: obj for obj in list(inst.translations.all())}
for lang in self.data_by_lang:
if lang is not init_lang:
try:
tr = translations[lang]
except KeyError:
# there are no available translation in db
tr = inst.translate(lang)
translation = translations.get(lang)
# there are no available translation in db
if not translation:
translation = inst.translate(lang)
for key, value in self.data_by_lang[lang].iteritems():
setattr(tr, key, value)
tr.save()
setattr(translation, key, value)
translation.save()
self.instance = inst.lazy_translation_getter(init_lang)
return self.instance

@ -11,6 +11,7 @@
<div class="form-group">
<select class="form-control" name="filter" id="filter">
<option>Фильтровать</option>
<option value="">Все</option>
{% for id, name in choices%}
<option class="opt" value="{{ id }}">{{ name }}</option>
{% endfor %}

@ -32,7 +32,7 @@
<td><a href="{% url 'newsletters_newsletters_send_test' item.id %}">тест</a> </td>
<td><a href="{% url 'newsletters_newsletters_update' item.id %}">Изменить</a> </td>
<td><a href="{% url 'newsletters_newsletters_history' item.id %}">История</a> </td>
<td>{% if item.status == item.SENT or item.status == item.CANCELED %}<a href="#">Статистика</a>{% endif %}</td>
<td>{% if item.status == item.SENT or item.status == item.CANCELED %}<a href="{% url 'newsletters_newsletters_stat' item.id %}">Статистика</a>{% endif %}</td>
</tr>
{% endfor %}
</tbody>

@ -0,0 +1,62 @@
{% extends 'admin/base.html' %}
{% load staticfiles %}
{% block body %}
<div class="box span10">
<div class="box-header well">
<h2><i class="icon-arrow-down"></i>Статистика для {{ newsletter.title }}</h2>
</div>
<div class="box-content">
<table class="table table-hover table table-bordered table-striped">
<colgroup>
<col width="45%">
<col width="45%">
<col width="10%">
</colgroup>
<thead>
<tr>
<th>Название</th>
<th>Количество писем</th>
<th>&nbsp</th>
</tr>
</thead>
<tbody>
<tr>
<td>Отправлено</td>
<td>{{ stat.sent.data }}</td>
<td><a href="{% url 'newsletters_newsletters_history' object.id %}?filter={{ stat.sent.filter }}">Подробно</a></td>
</tr>
<tr>
<td>Ошибок</td>
<td>{{ stat.errors.data }}</td>
<td><a href="{% url 'newsletters_newsletters_history' object.id %}?filter={{ stat.errors.filter }}">Подробно</a></td>
</tr>
<tr>
<td>Открыто</td>
<td>{{ stat.opened.data }} {% if stat.opened.percent %} ({{ stat.opened.percent|floatformat:"0" }}%) {% endif %}</td>
<td><a href="{% url 'newsletters_newsletters_history' object.id %}?filter={{ stat.opened.filter }}">Подробно</a></td>
</tr>
<tr>
<td>Отписалось</td>
<td>{{ stat.unsub.data }} {% if stat.unsub.percent %} ({{ stat.unsub.percent|floatformat:"0" }}%) {% endif %}</td>
<td><a href="{% url 'newsletters_newsletters_history' object.id %}?filter={{ stat.unsub.filter }}">Подробно</a></td>
</tr>
<tr>
<td>Нет данных</td>
<td>{{ stat.no_data.data }}</td>
<td><a href="{% url 'newsletters_newsletters_history' object.id %}?filter={{ stat.no_data.filter }}">Подробно</a></td>
</tr>
<tr>
<td>Переходов по ссылкам</td>
<td>{{ stat.links.data }}</td>
<td><a href="{% url 'newsletters_newsletters_history' object.id %}?filter={{ stat.links.filter }}">Подробно</a></td>
</tr>
</tbody>
</table>
</div>
</div>
{% endblock %}
Loading…
Cancel
Save