You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
11 KiB
250 lines
11 KiB
# -*- coding: utf-8 -*-
|
|
import xlrd
|
|
from collections import namedtuple
|
|
import re
|
|
|
|
from ckeditor.widgets import CKEditorWidget
|
|
from django import forms
|
|
from django.utils import translation
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
|
|
from emencia.django.newsletter.models import (
|
|
Attachment,
|
|
Contact,
|
|
ContactSettings,
|
|
MailingList,
|
|
Newsletter,
|
|
NewsletterRecommend,
|
|
|
|
)
|
|
from theme.models import Theme
|
|
from city.models import City
|
|
from country.models import Area, Country
|
|
from exposition.models import Exposition
|
|
from haystack.query import SearchQuerySet
|
|
|
|
|
|
class ContactSettingsForm(forms.ModelForm):
|
|
city = forms.CharField(label=_(u'Город'), widget=forms.HiddenInput() ,required=False)
|
|
periodic = forms.ChoiceField(choices=ContactSettings.PERIODIC_CHOICES,
|
|
label=_(u'Периодичность отправки'))
|
|
first_name = forms.CharField(label=_('first name'))
|
|
subscriber = forms.BooleanField(label=_('subscriber'), required=False)
|
|
valid = forms.BooleanField(label=_('valid email'), required=False)
|
|
tester = forms.BooleanField(label=_('contact tester'), required=False)
|
|
country = forms.MultipleChoiceField(choices=[(c.id,c.name) for c in list(set(Country.objects.language().all()))], required=False)
|
|
area = forms.MultipleChoiceField(choices=[(a.id, a.name) for a in list(set(Area.objects.language().all()))], required=False)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(ContactSettingsForm, self).__init__(*args, **kwargs)
|
|
instance = getattr(self, 'instance', None)
|
|
if instance:
|
|
lang = translation.get_language()
|
|
self.fields['city'].widget.attrs['data-init-text'] = [(item.id, item.name) for item in list(instance.city.filter(translations__language_code=lang))]
|
|
|
|
class Meta:
|
|
model = ContactSettings
|
|
fields = ('periodic', 'exponent_practicum', 'organiser_practicum', 'theme', 'area', 'country', 'city', )
|
|
|
|
def save(self, commit=True):
|
|
contactsettings = super(ContactSettingsForm, self).save(commit=False)
|
|
old_save_m2m = self.save_m2m
|
|
if commit:
|
|
contactsettings.save()
|
|
contact = contactsettings.contact
|
|
contact.first_name = self.cleaned_data['first_name']
|
|
contact.subscriber = self.cleaned_data['subscriber']
|
|
contact.valid = self.cleaned_data['valid']
|
|
contact.tester = self.cleaned_data['tester']
|
|
contact.save()
|
|
return contactsettings
|
|
|
|
def clean_periodic(self):
|
|
|
|
return int(self.cleaned_data['periodic'])
|
|
|
|
def clean_city(self):
|
|
cities = self.cleaned_data.get('city')
|
|
if cities:
|
|
res = []
|
|
for id in cities.split(','):
|
|
try:
|
|
res.append(int(id))
|
|
except ValueError:
|
|
continue
|
|
return City.objects.filter(id__in=res)
|
|
else:
|
|
return City.objects.none()
|
|
|
|
|
|
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)
|
|
add_from_themes = forms.MultipleChoiceField(label=_(u'Добавить подписчиков по тематикам'), required=False,
|
|
choices=theme_choices)
|
|
theme_for_filter = forms.MultipleChoiceField(label=_(u'Тематики'), required=False,
|
|
choices=theme_choices)
|
|
|
|
class Meta:
|
|
model = MailingList
|
|
fields = ('name', 'description', 'theme_for_filter')
|
|
|
|
def save(self, commit=True):
|
|
ml = super(MailingListForm, self).save(commit=True)
|
|
# data = self.cleaned_data
|
|
# f = data['excel_file']
|
|
# if f:
|
|
# # contact_list = list(Contact.objects.all())
|
|
# book = xlrd.open_workbook(file_contents=f.read())
|
|
# 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)}
|
|
# valid_contacts = []
|
|
# # for contact in contact_list:
|
|
# # if contact.email in excel_emails:
|
|
# # valid_contacts.append(contact)
|
|
# for email, first_name in excel_emails.iteritems():
|
|
# valid_contacts.append(Contact.objects.create(
|
|
# email=email, first_name=first_name,
|
|
# valid=True, activated=True))
|
|
# ml.subscribers = valid_contacts
|
|
# ml.save()
|
|
return ml
|
|
|
|
|
|
def get_contact_list(self, qs):
|
|
headers_map = namedtuple("Headers", ['email', 'first_name', 'exponent_practicum', 'organiser_practicum', 'geo', 'country', 'city', 'theme', 'time1', 'time2'])
|
|
excel_file = self.cleaned_data['excel_file']
|
|
contact_items = dict(qs.values_list('email', 'pk'))
|
|
ids = set(contact_items.values())
|
|
|
|
if excel_file:
|
|
book = xlrd.open_workbook(file_contents=excel_file.read())
|
|
sheet = book.sheet_by_index(0)
|
|
countries = {}
|
|
cities = {}
|
|
themes = {}
|
|
field_models = {
|
|
'country': {'model': Country, 'cached': {}},
|
|
'city': {'model': City, 'cached': {}},
|
|
'theme': {'model': Theme, 'cached': {}}
|
|
}
|
|
for i in range(1, sheet.nrows):
|
|
item = headers_map(*sheet.row(i))
|
|
# 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:
|
|
c, created = Contact.objects.get_or_create(email=item.email.value.strip())
|
|
c.first_name = item.first_name.value.strip() or c.first_name
|
|
c.activated = True
|
|
c.save()
|
|
ids.add(c.pk)
|
|
contactsettings, _created = ContactSettings.objects.get_or_create(contact_id=c.pk)
|
|
contactsettings.exponent_practicum = item.exponent_practicum.value
|
|
contactsettings.organiser_practicum = item.organiser_practicum.value
|
|
for field, data in field_models.iteritems():
|
|
# model = data['model']
|
|
# cached = data['cached']
|
|
cell = getattr(item, field)
|
|
values = cell.value.split(';')
|
|
names_to_fetch = []
|
|
pks = set()
|
|
# print(cell)
|
|
# print(field)
|
|
# for x in values:
|
|
# print(x)
|
|
# import pdb; pdb.set_trace()
|
|
for val in values:
|
|
val_stripped = val.strip()
|
|
_pk = data['cached'].get(val_stripped, None)
|
|
if _pk is None:
|
|
names_to_fetch.append(val_stripped)
|
|
else:
|
|
pks.add(_pk)
|
|
# print(names_to_fetch)
|
|
# print(data['model'])
|
|
if names_to_fetch:
|
|
# _pks = dict([(x.name_ru, x.pk) for x in SearchQuerySet().models(data['model']).filter(name__in=values)])
|
|
sqs = SearchQuerySet().models(data['model']).filter(name_ru__in=values).load_all()
|
|
_pks = dict([(x.object.name, x.pk) for x in sqs])
|
|
|
|
# print(_pks)
|
|
data['cached'].update(_pks)
|
|
pks.update(_pks.values())
|
|
# print(data['cached'])
|
|
if pks:
|
|
_field = getattr(contactsettings, field)
|
|
_field.add(*pks)
|
|
# print(pks)
|
|
contactsettings.save()
|
|
# p = re.compile(r'([^\(pk=\d+\)]*\(pk=(?P<pk>\d+)\))')
|
|
# p.finditer():
|
|
# ...
|
|
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):
|
|
test_contacts = forms.ModelMultipleChoiceField(label=_(u'Тестовые контакты'), required=False,
|
|
queryset=Contact.objects.filter(tester=True))
|
|
content = forms.CharField(label=_('content'), widget=CKEditorWidget(config_name='newsletters'), required=False)
|
|
content2 = forms.CharField(label=_('Content B'), widget=CKEditorWidget(config_name='newsletters'), required=False)
|
|
|
|
class Meta:
|
|
model = Newsletter
|
|
fields = ('preheader', 'title', 'content', 'ab_testing', 'ab_first_stage', 'preheader2', 'title2', 'content2', 'mailing_list', 'theme_for_filter', 'test_contacts', 'header_sender',
|
|
'header_reply', 'status', 'sending_date', 'slug')
|
|
widgets = {
|
|
'ab_first_stage': forms.widgets.TextInput(attrs={'type':'number', 'min': 5, 'max': 100}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(NewsletterForm, self).__init__(*args, **kwargs)
|
|
|
|
# добавляем поле для возможности указания варианта финальной рассылки (А-В тестирование)
|
|
if self.instance.pk and self.instance.ab_testing and self.instance.ab_final_stage:
|
|
self._meta.fields = (
|
|
'preheader', 'title', 'content', 'ab_testing',
|
|
'ab_first_stage', 'preheader2', 'title2', 'content2', 'mailing_list',
|
|
'theme_for_filter', 'test_contacts', 'header_sender',
|
|
'header_reply', 'ab_final_choice', 'status', 'sending_date',
|
|
'slug')
|
|
field = forms.ChoiceField(
|
|
label=_(u'Вариант в финальную рассылку'),
|
|
choices=Newsletter.AB_FINAL_CHOICE,
|
|
initial=self.instance.ab_final_choice or Newsletter.A)
|
|
self.fields.insert(self.fields.keyOrder.index('status'), 'ab_final_choice', field)
|
|
|
|
if self.instance and self.instance.mailing_list_id:
|
|
self.fields['theme_for_filter'].queryset = self.instance.mailing_list.theme_for_filter.all()
|
|
self.initial['ab_first_stage'] = self.initial.get('ab_first_stage') or 10
|
|
|
|
|
|
class AttachmentForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Attachment
|
|
fields = ('title', 'file_attachment')
|
|
|
|
|
|
class NewsletterRecommendForm(forms.ModelForm):
|
|
verbose = _(u'Создание/Редактирование рекомендации')
|
|
exposition = forms.IntegerField(label=_(u'Выставка'), widget=forms.HiddenInput(), required=False)
|
|
|
|
class Meta:
|
|
model = NewsletterRecommend
|
|
fields = ('theme', 'exposition', 'fr', 'to')
|
|
|
|
def clean_exposition(self):
|
|
expo_id = self.cleaned_data['exposition']
|
|
try:
|
|
expo = Exposition.objects.get(id=expo_id)
|
|
except Exposition.DoesNotExist:
|
|
raise forms.ValidationError(_(u'Такой выставки не существует'))
|
|
return expo
|
|
|