# -*- coding: utf-8 -*- import xlrd from collections import namedtuple import re from city.models import City from ckeditor.widgets import CKEditorWidget from country.models import Area, Country 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 ) from theme.models import Theme 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() for val in values: val = val.strip() _pk = data['cached'].get(val, None) if _pk is None: names_to_fetch.append(val) else: pks.add(_pk) if names_to_fetch: _pks = dict(data['model'].objects.language().filter(name__in=values).values_list('name', 'pk')) data['cached'].update(_pks) pks.update(_pks.values()) if pks: _field = getattr(contactsettings, field) _field.add(*pks) contactsettings.save() # p = re.compile(r'([^\(pk=\d+\)]*\(pk=(?P\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')) 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')