From d1ca63840909a7dc78ea40dc8ffc3e84a508f45d Mon Sep 17 00:00:00 2001 From: Ivan Kovalkovskyi Date: Wed, 21 Oct 2015 16:21:39 +0300 Subject: [PATCH] newsletter statistics --- emencia/django/newsletter/admin_urls.py | 9 +-- .../django/newsletter/views/admin_views.py | 28 ++++++++- functions/forms.py | 17 +++-- .../admin/newsletters/newsletter_history.html | 1 + .../admin/newsletters/newsletter_list.html | 2 +- .../admin/newsletters/newsletter_stat.html | 62 +++++++++++++++++++ 6 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 templates/admin/newsletters/newsletter_stat.html diff --git a/emencia/django/newsletter/admin_urls.py b/emencia/django/newsletter/admin_urls.py index 90afd4d5..4007fc9b 100644 --- a/emencia/django/newsletter/admin_urls.py +++ b/emencia/django/newsletter/admin_urls.py @@ -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\d+)/edit/', NewsletterUpdate.as_view(), name='newsletters_newsletters_update'), + url(r'^newsletters/(?P\d+)/edit/$', NewsletterUpdate.as_view(), name='newsletters_newsletters_update'), url(r'^newsletters/(?P\d+)/history/', NewsletterHistory.as_view(), name='newsletters_newsletters_history'), - url(r'^newsletters/(?P\d+)/test/', + url(r'^newsletters/(?P\d+)/statistics/', NewsletterStatistics.as_view(), name='newsletters_newsletters_stat'), + url(r'^newsletters/(?P\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'), diff --git a/emencia/django/newsletter/views/admin_views.py b/emencia/django/newsletter/views/admin_views.py index d31d0f09..1a7f4f2f 100644 --- a/emencia/django/newsletter/views/admin_views.py +++ b/emencia/django/newsletter/views/admin_views.py @@ -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 diff --git a/functions/forms.py b/functions/forms.py index e011dda3..cb19d3f5 100644 --- a/functions/forms.py +++ b/functions/forms.py @@ -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 diff --git a/templates/admin/newsletters/newsletter_history.html b/templates/admin/newsletters/newsletter_history.html index f024ef90..f9a64245 100644 --- a/templates/admin/newsletters/newsletter_history.html +++ b/templates/admin/newsletters/newsletter_history.html @@ -11,6 +11,7 @@