1457: Этап №5: Со скайпа - Импорт подписчиков

remotes/origin/stage5
Alexander Burdeiny 10 years ago
parent ae475ba3fb
commit d7b0973ca3
  1. 74
      emencia/django/newsletter/admin_forms.py
  2. 1
      emencia/django/newsletter/admin_urls.py
  3. 66
      emencia/django/newsletter/utils/excel.py
  4. 49
      emencia/django/newsletter/views/admin_views.py
  5. 7
      templates/admin/newsletters/contact_list.html
  6. 23
      templates/admin/newsletters/mailing_list_object.html

@ -70,9 +70,12 @@ class ContactSettingsForm(forms.ModelForm):
class MailingListForm(forms.ModelForm): class MailingListForm(forms.ModelForm):
theme_choices = [(item.id, item.name) for item in Theme.objects.language().all()]
excel_file = forms.FileField(label=_(u'Импортировать подписчиков'), required=False) excel_file = forms.FileField(label=_(u'Импортировать подписчиков'), required=False)
add_from_themes = forms.MultipleChoiceField(label=_(u'Добавить подписчиков по тематикам'), required=False,
choices=theme_choices)
theme_for_filter = forms.MultipleChoiceField(label=_(u'Тематики'), required=False, theme_for_filter = forms.MultipleChoiceField(label=_(u'Тематики'), required=False,
choices=[(item.id, item.name) for item in Theme.objects.language().all()]) choices=theme_choices)
class Meta: class Meta:
model = MailingList model = MailingList
@ -80,25 +83,60 @@ class MailingListForm(forms.ModelForm):
def save(self, commit=True): def save(self, commit=True):
ml = super(MailingListForm, self).save(commit=True) ml = super(MailingListForm, self).save(commit=True)
data = self.cleaned_data # data = self.cleaned_data
f = data['excel_file'] # f = data['excel_file']
if f: # if f:
contact_list = list(Contact.objects.all()) # # contact_list = list(Contact.objects.all())
book = xlrd.open_workbook(file_contents=f.read()) # book = xlrd.open_workbook(file_contents=f.read())
sheet = book.sheet_by_index(0) # sheet = book.sheet_by_index(0)
excel_emails = {sheet.row_values(row_number)[0]: sheet.row_values(row_number)[1] for row_number in range(1, sheet.nrows)} # excel_emails = {sheet.row_values(row_number)[0]: sheet.row_values(row_number)[1] for row_number in range(1, sheet.nrows)}
valid_contacts = [] # valid_contacts = []
# for contact in contact_list: # # for contact in contact_list:
# if contact.email in excel_emails: # # if contact.email in excel_emails:
# valid_contacts.append(contact) # # valid_contacts.append(contact)
for email, first_name in excel_emails.iteritems(): # for email, first_name in excel_emails.iteritems():
valid_contacts.append(Contact.objects.create( # valid_contacts.append(Contact.objects.create(
email=email, first_name=first_name, # email=email, first_name=first_name,
valid=True, activated=True)) # valid=True, activated=True))
ml.subscribers = valid_contacts # ml.subscribers = valid_contacts
ml.save() # ml.save()
return ml return ml
def get_contact_list(self, qs):
excel_file = self.cleaned_data['excel_file']
contact_items = dict(qs.values_list('email', 'pk'))
if excel_file:
book = xlrd.open_workbook(file_contents=excel_file.read())
sheet = book.sheet_by_index(0)
for i in range(1, sheet.nrows):
email = sheet.row_values(i)[0]
first_name = sheet.row_values(i)[1]
exponent_practicum = sheet.row_values(i)[2]
organiser_practicum = sheet.row_values(i)[3]
if email not in contact_items:
try:
c = Contact.objects.get(email=email)
c.contactsettings.exponent_practicum = exponent_practicum
c.contactsettings.organiser_practicum = organiser_practicum
c.contactsettings.save()
except Contact.DoesNotExist:
c = Contact.objects.create(email=email, first_name=first_name, activated=True)
cs = ContactSettings(
contact=c,
exponent_practicum=exponent_practicum,
organiser_practicum=organiser_practicum,
)
cs.save()
contact_items[email] = c.pk
ids = set(contact_items.values())
if self.cleaned_data['add_from_themes']:
ct_from_themes = Contact.objects\
.filter(
contactsettings__theme__in=self.cleaned_data['add_from_themes']
).distinct().values_list('pk', flat=True)
ids.update(ct_from_themes)
return ids
class NewsletterForm(forms.ModelForm): class NewsletterForm(forms.ModelForm):
test_contacts = forms.ModelMultipleChoiceField(label=_(u'Тестовые контакты'), required=False, test_contacts = forms.ModelMultipleChoiceField(label=_(u'Тестовые контакты'), required=False,

@ -40,6 +40,7 @@ urlpatterns = patterns('',
url(r'^mailinglist/all/$', MailingListView.as_view(), name='newsletters_mailinglist'), url(r'^mailinglist/all/$', MailingListView.as_view(), name='newsletters_mailinglist'),
url(r'^mailinglist/(?P<pk>\d+)/edit/', UpdateMailingList.as_view(), name='newsletters_mailinglist_update'), url(r'^mailinglist/(?P<pk>\d+)/edit/', UpdateMailingList.as_view(), name='newsletters_mailinglist_update'),
url(r'^mailinglist/(?P<pk>\d+)/', DeleteMailingList.as_view(), name='newsletters_mailinglist_delete'), url(r'^mailinglist/(?P<pk>\d+)/', DeleteMailingList.as_view(), name='newsletters_mailinglist_delete'),
url(r'^mailinglist/filter/', CreateMailingList.as_view(), {'filter': True}, name='newsletters_mailinglist_create_filter'),
url(r'^mailinglist/', CreateMailingList.as_view(), name='newsletters_mailinglist_create'), url(r'^mailinglist/', CreateMailingList.as_view(), name='newsletters_mailinglist_create'),
url(r'^contact/(?P<pk>\d+)/edit/', UpdateContact.as_view(), name='newsletters_contact_update'), url(r'^contact/(?P<pk>\d+)/edit/', UpdateContact.as_view(), name='newsletters_contact_update'),

@ -2,55 +2,53 @@
"""ExcelResponse for emencia.django.newsletter""" """ExcelResponse for emencia.django.newsletter"""
# Based on http://www.djangosnippets.org/snippets/1151/ # Based on http://www.djangosnippets.org/snippets/1151/
import datetime import datetime
from django.http import HttpResponse
from django.db.models.query import QuerySet
from django.db.models.query import ValuesQuerySet
# from ..models import ContactSettings # from ..models import ContactSettings
from collections import OrderedDict from collections import OrderedDict
from functions.translate import fill_trans_fields_r
from django.db.models.query import QuerySet, ValuesQuerySet
from django.http import HttpResponse, HttpResponseRedirect
from theme.models import Theme from theme.models import Theme
from city.models import City
from country.models import Country, Area
from functions.translate import fill_trans_fields_r
from ..models import ContactSettings
class ExcelResponse(HttpResponse): class ExcelResponse(HttpResponse):
"""ExcelResponse feeded by queryset""" """ExcelResponse feeded by queryset"""
def __init__(self, request, data, output_name='excel_data', headers=None, sheet_name = "Sheet1", default_style=None,
def __init__(self, data, output_name='excel_data', headers=None, sheet_name = "Sheet1", default_style=None,
force_csv=False, encoding='utf8'): force_csv=False, encoding='utf8'):
self.request = request
valid_data = False valid_data = False
qs = data.prefetch_related('contactsettings', 'contactsettings__theme', 'contactsettings__area') contact_ids = list(data.values_list('pk', flat=True))
# if isinstance(data, ValuesQuerySet): qs = ContactSettings.objects.filter(contact_id__in=contact_ids)
# data = list(data) if not qs.count():
# elif isinstance(data, QuerySet): return HttpResponseRedirect(self.request.META['HTTP_REFERER'])
# data = list(data.values()) qs = qs.prefetch_related(
'contact', 'theme', 'area', 'city', 'country',
# print(data) )
# if 'settings' in headers:
data = [] data = []
areas = dict(Area.objects.language('ru').all().values_list('pk', 'name'))
countries = dict(Country.objects.language('ru').all().values_list('pk', 'name'))
cities = dict(City.objects.language('ru').all().values_list('pk', 'name'))
themes = dict(Theme.objects.language('ru').all().values_list('pk', 'name')) themes = dict(Theme.objects.language('ru').all().values_list('pk', 'name'))
for item in qs: for item in qs:
data.append([ data.append([
item.email, item.contact.email,
item.first_name, item.contact.first_name,
item.contactsettings.exponent_practicum, item.exponent_practicum,
item.contactsettings.organiser_practicum, item.organiser_practicum,
item.creation_date.strftime('%d.%m.%Y'), ', '.join([areas.get(x) for x in set(item.area.values_list('pk', flat=True))]),
item.modification_date.strftime('%d.%m.%Y'), ', '.join([countries.get(x) for x in set(item.country.values_list('pk', flat=True))]),
', '.join([getattr(fill_trans_fields_r(obj=x, lang='ru'), 'name', '') for x in item.contactsettings.area.all()]), ', '.join([cities.get(x) for x in set(item.city.values_list('pk', flat=True))]),
', '.join([themes.get(x.pk) for x in item.contactsettings.theme.all()]), ', '.join([themes.get(x) for x in set(item.theme.values_list('pk', flat=True))]),
item.contact.creation_date.strftime('%d.%m.%Y'),
item.contact.modification_date.strftime('%d.%m.%Y'),
]) ])
headers = ('email', 'first_name', 'приактикум экспонента', 'практикум организатор', 'дата подписки', 'дата изменения', 'гео', 'темы') headers = ('email', 'first_name', 'приактикум экспонента', 'практикум организатор', 'гео', 'страна', 'город', 'темы', 'дата подписки', 'дата изменения')
# if hasattr(data, '__getitem__'):
# if isinstance(data[0], dict):
# if headers is None:
# headers = data[0].keys()
# data = [[row[col] for col in headers] for row in data]
data.insert(0, headers) data.insert(0, headers)
# if hasattr(data[0], '__getitem__'):
# valid_data = True
# assert valid_data is True, "ExcelResponse requires a sequence of sequences"
import StringIO import StringIO
output = StringIO.StringIO() output = StringIO.StringIO()

@ -144,7 +144,7 @@ class ExportContacts(FormView):
qs, title = form.filter() qs, title = form.filter()
if qs.count(): if qs.count():
columns = ('email', 'first_name') columns = ('email', 'first_name')
return ExcelResponse(qs, title, columns,'contacts') return ExcelResponse(request, qs, title, columns,'contacts')
return HttpResponseRedirect(self.request.META['HTTP_REFERER']) return HttpResponseRedirect(self.request.META['HTTP_REFERER'])
@ -170,42 +170,47 @@ class DeleteMailingList(DeleteView):
success_url = reverse_lazy('newsletters_mailinglist') success_url = reverse_lazy('newsletters_mailinglist')
class UpdateMailingList(UpdateView): class MailingListMixin(object):
model = MailingList model = MailingList
form_class = MailingListForm form_class = MailingListForm
template_name = 'admin/newsletters/mailing_list_object.html' template_name = 'admin/newsletters/mailing_list_object.html'
success_url = '/admin/newsletters/mailinglist/all/' success_url = '/admin/newsletters/mailinglist/all/'
def get_success_url(self): def dispatch(self, request, *args, **kwargs):
return self.success_url self.filter = kwargs.get('filter', False)
return super(MailingListMixin, self).dispatch(request, *args, **kwargs)
def form_valid(self, form): def form_valid(self, form):
filter_form = ContactFilterForm(self.request.GET)
if not self.object:
contacts = Contact.objects.none()
if self.filter and filter_form.is_valid():
contacts, _ = filter_form.filter()
else:
contacts = self.object.subscribers.all()
obj = form.save() obj = form.save()
obj.subscribers = form.get_contact_list(contacts)
themes = form.cleaned_data.get('theme_for_filter')
if themes:
obj.subscribers.add(*list(Contact.objects.filter(contactsettings__theme__in=themes).distinct()))
return HttpResponseRedirect(self.success_url) return HttpResponseRedirect(self.success_url)
def get_context_data(self, **kwargs):
context = super(MailingListMixin, self).get_context_data(**kwargs)
form = ContactFilterForm(self.request.GET)
class CreateMailingList(CreateView): context['filter_form'] = form
model = MailingList if form.is_valid():
form_class = MailingListForm qs, _ = form.filter()
template_name = 'admin/newsletters/mailing_list_object.html' context['contact_count'] = qs.count()
success_url = '/admin/newsletters/mailinglist/all/' context['filter_params'] = self.filter
return context
def form_valid(self, form):
obj = form.save()
# filter_form = ContactFilterForm(self.request.GET)
# if filter_form.is_valid():
# contacts, _ = filter_form.filter()
# obj.subscribers = contacts
# obj.save()
class CreateMailingList(MailingListMixin, CreateView):
pass
return HttpResponseRedirect(self.success_url)
class UpdateMailingList(MailingListMixin, UpdateView):
pass
class NewsletterCreate(CreateView): class NewsletterCreate(CreateView):

@ -120,7 +120,8 @@
<div class="controls"> <div class="controls">
<button id="submit" class="btn btn-primary">Фильтровать</button> <button id="submit" class="btn btn-primary">Фильтровать</button>
<a href="{% url 'export_contacts' %}" id="export" class="btn yellow">Экспорт<i class="icon-circle-arrow-down"></i></a> <a href="{% url 'export_contacts' %}" id="export" class="btn yellow">Экспорт<i class="icon-circle-arrow-down"></i></a>
<a href="{% url 'newsletters_mailinglist_create' %}" id="mailinglist" class="btn btn-success" data-toggle="tooltip" data-placement="top" title="Создает новый список рассылки с отфильтрованими контактами">Сп.рассылки <i class="icon-list"></i></a> <a href="{% url 'newsletters_mailinglist_create_filter' %}" id="mailinglist" class="btn btn-success" data-toggle="tooltip" data-placement="top" title="Создает новый список рассылки с отфильтрованими контактами"><i class="icon-plus"></i>Создать список рассылки из фильтра</i></a>
<a href="{% url 'newsletters_mailinglist_create' %}" class="btn btn-success" data-toggle="tooltip" data-placement="top" title="Создает новый список рассылки"><i class="icon-plus"></i>Создать список рассылки</i></a>
</div> </div>
</div> </div>
</div> </div>
@ -199,9 +200,9 @@
event.preventDefault(); event.preventDefault();
window.location = "{% url 'export_contacts' %}" + get_param; window.location = "{% url 'export_contacts' %}" + get_param;
}); });
$('#mailinglist').on('click', function(event){ $('a#mailinglist').on('click', function(event){
event.preventDefault(); event.preventDefault();
window.location = "{% url 'newsletters_mailinglist_create' %}" + get_param; window.location = $(this).attr('href') + get_param;
}); });
$('#id_created_from').datetimepicker({ $('#id_created_from').datetimepicker({
todayHighlight: true, todayHighlight: true,

@ -1,5 +1,6 @@
{% extends 'admin/base.html' %} {% extends 'admin/base.html' %}
{% load static %} {% load static %}
{% load i18n %}
{% block body %} {% block body %}
@ -8,8 +9,28 @@
<div class="box span10"> <div class="box span10">
<div class="box-header well"> <div class="box-header well">
<h2><i class="icon-pencil"></i>{% if object %}Изменения{% else %}Создание{% endif %} списка рассылок</h2> <h2><i class="icon-pencil"></i>{% if object %}{% trans "Изменение" %}{% else %}{% trans "Создание" %}{% endif %} {% trans "списка рассылок" %}</h2>
</div> </div>
{% if filter_params %}
{% if not filter_form.errors %}
<div class="alert alert-success" role="alert">
{% blocktrans with count=contact_count %}
<i class="icon-info-sign"></i>Отфильтровано {{ count }} контактов
{% endblocktrans %}
</div>
{% else %}
<div class="alert alert-warning" role="alert">
<i class="icon-info-sign"></i>{% trans "Ошибка фильтрации контактов." %}
</div>
{% endif %}
{% endif %}
{% if form.instance.pk %}
<div class="alert alert-info" role="alert">
{% blocktrans with count=form.instance.subscribers_count %}
<i class="icon-info-sign"></i>Контактов на текущий момент - {{ count }}
{% endblocktrans %}
</div>
{% endif %}
<div class="box-content"> <div class="box-content">
{% for field in form %} {% for field in form %}
<div class="control-group {% if field.errors %}error{% endif %}"> <div class="control-group {% if field.errors %}error{% endif %}">

Loading…
Cancel
Save