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 django.conf.urls import patterns
from emencia.django.newsletter.views.admin_views import ContactList, UpdateContact, MailingListView, UpdateMailingList,\ from emencia.django.newsletter.views.admin_views import ContactList, UpdateContact, MailingListView, UpdateMailingList,\
CreateMailingList, NewsletterListView, NewsletterCreate, ExportContacts, DeleteContact, NewsletterUpdate, \ CreateMailingList, NewsletterListView, NewsletterCreate, ExportContacts, DeleteContact, NewsletterUpdate, \
DeleteMailingList, ImportContacts, NewsletterHistory DeleteMailingList, ImportContacts, NewsletterHistory, NewsletterStatistics
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^newsletters/all/$', NewsletterListView.as_view(), name='newsletters_newsletters_list'), 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+)/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', 'emencia.django.newsletter.views.admin_views.send_test_newsletter',
name='newsletters_newsletters_send_test'), 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'), url(r'^mailinglist/all/$', MailingListView.as_view(), name='newsletters_mailinglist'),

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- 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.conf import settings
from django.utils import translation from django.utils import translation
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -240,6 +240,32 @@ class NewsletterHistory(ListView):
context['choices'] = ContactMailingStatus.STATUS_CHOICES context['choices'] = ContactMailingStatus.STATUS_CHOICES
return context 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): class ExportContacts(FormView):
form_class = ContactFilterForm form_class = ContactFilterForm

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

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

@ -32,7 +32,7 @@
<td><a href="{% url 'newsletters_newsletters_send_test' item.id %}">тест</a> </td> <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_update' item.id %}">Изменить</a> </td>
<td><a href="{% url 'newsletters_newsletters_history' 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> </tr>
{% endfor %} {% endfor %}
</tbody> </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