remotes/origin/1203
Nazar Kotjuk 10 years ago
commit 10120a6833
  1. 7
      emencia/django/newsletter/admin_urls.py
  2. 80
      emencia/django/newsletter/forms.py
  3. 27
      emencia/django/newsletter/views/admin_views.py
  4. 1
      import_xls/admin.py
  5. 8
      import_xls/import_forms.py
  6. 60
      templates/admin/import templates/import_contacts.html
  7. 2
      templates/admin/newsletters/confirm_delete.html
  8. 29
      templates/admin/newsletters/contact_list.html
  9. 12
      templates/admin/newsletters/mailing_list.html

@ -1,9 +1,8 @@
from django.conf.urls import url from django.conf.urls import url
from django.conf.urls import include
from django.conf.urls import patterns from django.conf.urls import patterns
from django.http import HttpResponse
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
urlpatterns = patterns('', urlpatterns = patterns('',
@ -17,10 +16,12 @@ 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/', 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'),
url(r'^contact/(?P<pk>\d+)/delete/', DeleteContact.as_view(), name='newsletters_contact_delete'), url(r'^contact/(?P<pk>\d+)/delete/', DeleteContact.as_view(), name='newsletters_contact_delete'),
url(r'^contact/all/$', ContactList.as_view(), name='newsletters_contact_list'), url(r'^contact/all/$', ContactList.as_view(), name='newsletters_contact_list'),
url(r'^contact/export/$', ExportContacts.as_view(), name='export_contacts'), url(r'^contact/export/$', ExportContacts.as_view(), name='export_contacts'),
url(r'^contact/import/$', ImportContacts.as_view(), name='import_newsletters_contacts'),
) )

@ -87,28 +87,56 @@ class ContactSettingsForm(forms.ModelForm):
class ContactFilterForm(forms.Form): class ContactFilterForm(forms.Form):
email = forms.EmailField(label="Email", max_length=255, required=False, email = forms.EmailField(
widget=forms.TextInput(attrs={'class':'input-xlarge search-query','placeholder':'Email'})) label="Email",
theme = forms.MultipleChoiceField(label="Тематика", choices = [(t.id, t.name) for t in Theme.objects.language()]) max_length=255,
country = forms.MultipleChoiceField(label="Страна", required=False,
choices = [(c.id, c.name) for c in list(set(Country.objects.language('ru').all()))], widget=forms.TextInput(attrs={'class':'input-xlarge search-query','placeholder': 'Email'})
required=False) )
area = forms.MultipleChoiceField(label="Area", choices = [(c.id, c.name) for c in list(set(Area.objects.language()))], theme = forms.MultipleChoiceField(
required=False) label="Тематика",
choices=[(t.id, t.name) for t in Theme.objects.language()],
required=False
)
country = forms.MultipleChoiceField(
label="Страна",
choices=[(c.id, c.name) for c in list(set(Country.objects.language('ru').all()))],
required=False
)
city = forms.MultipleChoiceField(
label="Город",
choices=[(c.id, c.name) for c in list(set(City.objects.language('ru').filter(contactsettings__isnull=False)))],
required=False
)
area = forms.MultipleChoiceField(
label="Area", choices=[(c.id, c.name) for c in list(set(Area.objects.language()))],
required=False
)
mailinglist = forms.ChoiceField(
choices=[(ml.id, ml.name) for ml in MailingList.objects.all()],
label="Список рассылки",
required=False
)
active = forms.BooleanField(label="Подтверждена подписка", required=False) active = forms.BooleanField(label="Подтверждена подписка", required=False)
valid = forms.BooleanField(label="Валидный Email", required=False) valid = forms.BooleanField(label="Валидный Email", required=False)
def filter(self): def filter(self):
title = 'contact list ' title = 'contact list '
qs = Contact.objects.all() qs = Contact.objects.all()
if self.cleaned_data.get('mailinglist'):
qs = qs.filter(mailinglist_subscriber__id=self.cleaned_data['mailinglist'])
title += " mailinglist: %s" % MailingList.objects.get(id=self.cleaned_data['mailinglist']).name
if self.cleaned_data.get('country'):
qs = qs.filter(contactsettings__country__id__in=self.cleaned_data['country'])
title += " countries: %s" % ','.join([obj.url for obj in Country.objects.language().filter(id__in=self.cleaned_data['country'])])
if self.cleaned_data.get('email'): if self.cleaned_data.get('email'):
qs = qs.filter(email__icontains=self.cleaned_data['email']) qs = qs.filter(email__icontains=self.cleaned_data['email'])
if self.cleaned_data.get('theme'): if self.cleaned_data.get('theme'):
qs = qs.filter(contactsettings__theme__id__in=self.cleaned_data['theme']) qs = qs.filter(contactsettings__theme__id__in=self.cleaned_data['theme'])
title += " themes: %s" % ','.join([obj.url for obj in Theme.objects.language().filter(id__in=self.cleaned_data['theme'])]) title += " themes: %s" % ','.join([obj.url for obj in Theme.objects.language().filter(id__in=self.cleaned_data['theme'])])
if self.cleaned_data.get('country'): if self.cleaned_data.get('city'):
qs = qs.filter(contactsettings__country__id__in=self.cleaned_data['country']) qs = qs.filter(contactsettings__city__id__in=self.cleaned_data['city'])
title += " countries: %s" % ','.join([obj.url for obj in Country.objects.language().filter(id__in=self.cleaned_data['country'])]) title += " cities: %s" % ','.join([obj.url for obj in Country.objects.language().filter(id__in=self.cleaned_data['country'])])
if self.cleaned_data.get('area'): if self.cleaned_data.get('area'):
qs = qs.filter(contactsettings__area__id__in=self.cleaned_data['area']) qs = qs.filter(contactsettings__area__id__in=self.cleaned_data['area'])
title += " geo area: %s" % ','.join([tr(obj.name) for obj in Area.objects.language('en').filter(id__in=self.cleaned_data['area'])]) title += " geo area: %s" % ','.join([tr(obj.name) for obj in Area.objects.language('en').filter(id__in=self.cleaned_data['area'])])
@ -122,6 +150,36 @@ class ContactFilterForm(forms.Form):
return qs, title return qs, title
import xlrd
COUNTRY_CHOICES = [(c.id, c.name) for c in list(set(Country.objects.language('ru').all()))]
COUNTRY_CHOICES.insert(0, ('', 'Страна'))
class ContactImportForm(forms.Form):
excel_file = forms.FileField(label='Выберите файл')
activated = forms.BooleanField(label="Активные", required=False)
is_tester = forms.BooleanField(label="Тестовые", required=False)
country = forms.ChoiceField(label="Страна", choices=COUNTRY_CHOICES, required=False)
def save(self):
data = self.cleaned_data
country_id = self.cleaned_data.get('country')
country = None
if country_id:
country = Country.objects.get(id=country_id)
activated = data['activated']
is_tester = data['is_tester']
f = data['excel_file']
book = xlrd.open_workbook(file_contents=f.read())
sheet = book.sheet_by_index(0)
row_list = [sheet.row_values(row_number) for row_number in range(1,sheet.nrows)]
contact_list = []
for row in row_list:
contact_list.append(Contact(first_name=row[0], email=row[1], activated=activated, tester=is_tester))
Contact.objects.bulk_create(contact_list)
Contact.objects.filter(first_name__in=[c[0] for c in contact_list]).update(contactsettings__country=country)
class AbstractSubscribeForm(forms.ModelForm): class AbstractSubscribeForm(forms.ModelForm):
email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'})) email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))

@ -11,7 +11,7 @@ from HTMLParser import HTMLParseError
from emencia.django.newsletter.models import Contact, ContactSettings, MailingList, Newsletter, Attachment from emencia.django.newsletter.models import Contact, ContactSettings, MailingList, Newsletter, Attachment
from emencia.django.newsletter.admin_forms import ContactSettingsForm, MailingListForm, NewsletterForm, AttachmentForm from emencia.django.newsletter.admin_forms import ContactSettingsForm, MailingListForm, NewsletterForm, AttachmentForm
from emencia.django.newsletter.mailer import Mailer from emencia.django.newsletter.mailer import Mailer
from ..forms import ContactFilterForm from ..forms import ContactFilterForm, ContactImportForm
from ..utils.excel import ExcelResponse from ..utils.excel import ExcelResponse
from functions.admin_views import paginate_results from functions.admin_views import paginate_results
@ -93,6 +93,12 @@ class MailingListView(ListView):
template_name = 'admin/newsletters/mailing_list.html' template_name = 'admin/newsletters/mailing_list.html'
class DeleteMailingList(DeleteView):
model = MailingList
template_name = 'admin/newsletters/confirm_delete.html'
success_url = reverse_lazy('newsletters_mailinglist')
class UpdateMailingList(UpdateView): class UpdateMailingList(UpdateView):
model = MailingList model = MailingList
form_class = MailingListForm form_class = MailingListForm
@ -106,6 +112,15 @@ class CreateMailingList(CreateView):
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 form_valid(self, form):
obj = form.save()
form = ContactFilterForm(self.request.GET)
if form.is_valid():
contacts, _ = form.filter()
obj.subscribers = contacts
obj.save()
return HttpResponseRedirect(self.success_url)
from django.forms.models import modelformset_factory from django.forms.models import modelformset_factory
@ -214,3 +229,13 @@ class ExportContacts(FormView):
columns = ('first_name', 'email') columns = ('first_name', 'email')
return ExcelResponse(qs, title, columns,'contacts') return ExcelResponse(qs, title, columns,'contacts')
return HttpResponseRedirect(self.request.META['HTTP_REFERER']) return HttpResponseRedirect(self.request.META['HTTP_REFERER'])
class ImportContacts(FormView):
form_class = ContactImportForm
success_url = reverse_lazy("newsletters_contact_list")
template_name = 'admin/import templates/import_contacts.html'
def form_valid(self, form):
form.save()
return HttpResponseRedirect(self.get_success_url())

@ -41,7 +41,6 @@ class ImportView(FormView):
return render_to_response(self.template_name, context) return render_to_response(self.template_name, context)
class ExportView(FormView): class ExportView(FormView):
""" """
abstract class abstract class

@ -21,6 +21,7 @@ class ImportForm(forms.Form):
model = None model = None
excel_file = forms.FileField(label='Выберите файл') excel_file = forms.FileField(label='Выберите файл')
language = forms.ChoiceField(label='Выберите язык', choices=languages) language = forms.ChoiceField(label='Выберите язык', choices=languages)
def save_file(self): def save_file(self):
data = self.cleaned_data data = self.cleaned_data
lang = data['language'] lang = data['language']
@ -31,13 +32,12 @@ class ImportForm(forms.Form):
# all field names in excel file (must be in second row) # all field names in excel file (must be in second row)
field_names = [name for name in row_list[1]] field_names = [name for name in row_list[1]]
for row_number, row in enumerate(row_list): for row_number, row in enumerate(row_list):
# go through all rows in file # go through all rows in file
if row_number > 1: if row_number > 1:
# first two fields are verbose name and name # first two fields are verbose name and name
if row[0] != '': if row[0] != '':
# in first column ids # in first column ids
try: try:
object = self.model.objects.language(lang).get(id=int(row[0])) object = self.model.objects.language(lang).get(id=int(row[0]))

@ -0,0 +1,60 @@
{% extends 'admin/base.html' %}
{% load static %}
{% block body %}
<form method="post" class="form-horizontal" enctype="multipart/form-data"> {% csrf_token %}
{# excel_file #}
<div class="control-group {% if form.excel_file.errors %}error{% endif %}">
<label class="control-label">{{ form.excel_file.label }}:</label>
<div class="controls">
{{ form.excel_file }}
<span class="help-inline">{{ form.excel_file.errors }}</span>
</div>
</div>
{# country #}
<div class="control-group {% if form.country.errors %}error{% endif %}">
<label class="control-label">{{ form.country.label }}:</label>
<div class="controls">
{{ form.country }}
<span class="help-inline">{{ form.country.errors }}</span>
</div>
</div>
{# activated #}
<div class="control-group {% if form.activated.errors %}error{% endif %}">
<label class="control-label">{{ form.activated.label }}:</label>
<div class="controls">
{{ form.activated }}
<span class="help-inline">{{ form.activated.errors }}</span>
</div>
</div>
{# is_tester #}
<div class="control-group {% if form.is_tester.errors %}error{% endif %}">
<label class="control-label">{{ form.is_tester.label }}:</label>
<div class="controls">
{{ form.is_tester }}
<span class="help-inline">{{ form.is_tester.errors }}</span>
</div>
</div>
<div class="controls">
<input class="btn btn-large btn-primary" type="submit" value="Импорт">
<input class="btn btn-large" type="reset" value="Отмена">
</div>
</form>
{% endblock %}
{% block scripts %}
<link rel="stylesheet" href="{% static 'js/select/select2.css' %}">
<script src="{% static 'js/select2.min.js' %}"></script>
<script>
$(document).ready(function(){
$("#id_country").select2({width:"element", placeholder:"Страна"});
});
</script>
{% endblock %}

@ -3,7 +3,7 @@
{% block body %} {% block body %}
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<div class="controls"> <div class="controls">
<p>Вы точно хотите удалить "{{ object.contact.name }}" ?</p> <p>Вы точно хотите удалить "{{ object.contact.name }}{{ object.name }}" ?</p>
<input class="btn btn-large btn-danger delete" type="submit" value="Да" /> <input class="btn btn-large btn-danger delete" type="submit" value="Да" />
<a class="btn btn-large btn-primary" href = {% url 'newsletters_contact_list' %}>Нет</a> <a class="btn btn-large btn-primary" href = {% url 'newsletters_contact_list' %}>Нет</a>
</div> </div>

@ -4,7 +4,7 @@
<div class="box span10"> <div class="box span10">
<div class="box-header well"> <div class="box-header well">
<h2><i class="icon-arrow-down"></i>Список контактов</h2> <h2><i class="icon-arrow-down"></i>Список контактов <a class="btn" href="{% url 'import_newsletters_contacts' %}">Импорт</a></h2>
</div> </div>
<div class="box-content"> <div class="box-content">
<form class="form-horizontal" method="get"> <form class="form-horizontal" method="get">
@ -37,6 +37,14 @@
</div> </div>
</div> </div>
<!-- City -->
<div class="control-group">
<label class="control-label" for="id_city">{{ form.city.label }}</label>
<div class="controls">
{{ form.city }}
</div>
</div>
<!-- Area --> <!-- Area -->
<div class="control-group"> <div class="control-group">
<label class="control-label" for="id_area">{{ form.area.label }}</label> <label class="control-label" for="id_area">{{ form.area.label }}</label>
@ -45,6 +53,14 @@
</div> </div>
</div> </div>
<!-- Mailing list -->
<div class="control-group">
<label class="control-label" for="id_mailinglist">{{ form.mailinglist.label }}</label>
<div class="controls">
{{ form.mailinglist }}
</div>
</div>
<!-- Submit newsletter --> <!-- Submit newsletter -->
<div class="control-group"> <div class="control-group">
<label class="control-label" for="id_active">{{ form.active.label }}</label> <label class="control-label" for="id_active">{{ form.active.label }}</label>
@ -66,8 +82,9 @@
<label class="control-label" for="submit"></label> <label class="control-label" for="submit"></label>
<div class="controls"> <div class="controls">
<button id="submit" class="btn btn-primary">Filter</button> <button id="submit" class="btn btn-primary">Фильтровать </button>
<a href="{% url 'export_contacts' %}" id="export" class="btn btn-warning">Export to xls <i class="icon-circle-arrow-down"></i></a> <a href="{% url 'export_contacts' %}" id="export" class="btn btn-warning">Экспорт в xls <i class="icon-circle-arrow-down"></i></a>
<a href="{% url 'newsletters_mailinglist_create' %}" id="mailinglist" class="btn btn-success">Создать сп. рассылки <i class="icon-list"></i></a>
</div> </div>
</div> </div>
</div> </div>
@ -125,7 +142,9 @@
$(document).ready(function () { $(document).ready(function () {
$("#id_theme").select2({width: 283, placeholder: 'Тематики'}); $("#id_theme").select2({width: 283, placeholder: 'Тематики'});
$("#id_country").select2({width: 283, placeholder: 'Страны'}); $("#id_country").select2({width: 283, placeholder: 'Страны'});
$("#id_city").select2({width: 283, placeholder: 'Города'});
$("#id_area").select2({width: 283, placeholder: 'Географическая зона'}); $("#id_area").select2({width: 283, placeholder: 'Географическая зона'});
$("#id_mailinglist").select2({width: 283, placeholder: 'Список рассылки'});
var get_param = window.location.search; var get_param = window.location.search;
if (!get_param) { if (!get_param) {
$('.toggled').collapse('hide'); $('.toggled').collapse('hide');
@ -136,6 +155,10 @@
$('#export').on('click', function(event){ $('#export').on('click', function(event){
event.preventDefault(); event.preventDefault();
window.location = "{% url 'export_contacts' %}" + get_param; window.location = "{% url 'export_contacts' %}" + get_param;
});
$('#mailinglist').on('click', function(event){
event.preventDefault();
window.location = "{% url 'newsletters_mailinglist_create' %}" + get_param;
}) })
}) })
</script> </script>

@ -9,6 +9,14 @@
<div class="box-content"> <div class="box-content">
<table class="table table-hover"> <table class="table table-hover">
<colgroup>
<col width="30%">
<col width="20%">
<col width="20%">
<col width="10%">
<col width="10%">
<col width="10%">
</colgroup>
<thead> <thead>
<tr> <tr>
@ -16,6 +24,8 @@
<th>Подписчиков</th> <th>Подписчиков</th>
<th>Отписалось</th> <th>Отписалось</th>
<th>&nbsp;</th> <th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -26,6 +36,8 @@
<td>{{ item.unsubscribers_count }}</td> <td>{{ item.unsubscribers_count }}</td>
<td><a href="{% url 'newsletters_mailinglist_update' item.id %}">Изменить</a> </td> <td><a href="{% url 'newsletters_mailinglist_update' item.id %}">Изменить</a> </td>
<td><a href="{% url 'newsletters_mailinglist_delete' item.id %}">Удалить</a> </td>
<td><a href="{% url 'newsletters_contact_list' %}?mailinglist={{ item.id }}">Подписчики</a> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

Loading…
Cancel
Save