1462: Этап №5: Рассылка - Гео фильтры

полностью переписан бэкенд страницы редактирования настроек пользователя
remotes/origin/stage5
Alexander Burdeiny 10 years ago
parent c2e3b5b551
commit 93d24125d7
  1. 94
      accounts/views.py
  2. 21
      emencia/django/newsletter/forms.py
  3. 90
      functions/custom_views.py
  4. 17
      templates/admin/newsletters/mailing_list.html
  5. 29
      templates/client/accounts/settings.html

@ -2,7 +2,7 @@
import dateutil.relativedelta as rdelta import dateutil.relativedelta as rdelta
import json import json
import datetime import datetime
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse, reverse_lazy
import calendar as python_calendar import calendar as python_calendar
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponseBadRequest from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponseBadRequest
@ -11,7 +11,7 @@ from django.utils.translation import ugettext as _, get_language
from django_messages.forms import SendForm from django_messages.forms import SendForm
from django.views.generic import TemplateView, FormView from django.views.generic import TemplateView, FormView
from django.conf import settings from django.conf import settings
from functions.custom_views import ListView from functions.custom_views import ListView, CreateUpdateView
from functions.views_help import dates_range, get_user from functions.views_help import dates_range, get_user
from sorl.thumbnail import get_thumbnail from sorl.thumbnail import get_thumbnail
from exposition.models import Exposition from exposition.models import Exposition
@ -29,80 +29,60 @@ from emencia.django.newsletter.forms import SubscribeSettingsForm
from emencia.django.newsletter.models import Contact, ContactSettings from emencia.django.newsletter.models import Contact, ContactSettings
class SettingsView(TemplateView): class SettingsView(CreateUpdateView):
""" """
display template with user settings like: display template with user settings like:
password, email notifications, social settings, subscription password, email notifications, social settings, subscription
""" """
form_class = SubscribeSettingsForm
template_name = 'client/accounts/settings.html' template_name = 'client/accounts/settings.html'
success_url = reverse_lazy('accounts_settings')
def get_announce_form(self): def get_object(self):
user = self.request.user user = self.request.user
try: try:
contact = user.contact_set.get(email=user.username) self.contact = Contact.objects.get(user=user)
except Contact.DoesNotExist: except Contact.DoesNotExist:
try: try:
contact = Contact.objects.get(email=user.username) self.contact = Contact.objects.get(email=user.username, user__isnull=True)
contact.user = user self.contact.user = user
contact.save() self.contact.save()
except Contact.DoesNotExist: except Contact.DoesNotExist:
contact = None self.contact = None
return None
if not contact: obj = self.contact.contactsettings or ContactSettings.objects.create(
return SubscribeSettingsForm() contact=self.contact,
setting = contact.contactsettings exponent_practicum=False, organiser_practicum=False)
initial = {'email': contact.email} return obj
initial['city'] = ','.join(['%s:%s'%(item.id, item.name) for item in set(setting.city.all())]) def form_valid(self, form):
if setting.exponent_practicum or setting.organiser_practicum or setting.theme.exists(): if not self.contact:
initial['get_announce'] = True email = form.cleaned_data['email']
# north america check self.contact = Contact.objects.create_contact(email, self.request.user)
if setting.area.filter(id=SubscribeSettingsForm.NA_ID).exists(): form.activation_send = True
initial['na_expo'] = True self.object = form.save(commit=False)
# asia check self.object.contact = self.contact
if setting.area.filter(id=SubscribeSettingsForm.ASIA_ID).exists(): self.object.save()
initial['asia_expo'] = True form.save_m2m()
# europe check form.save_additional_fields(self.object)
if setting.area.filter(id=SubscribeSettingsForm.EUROPE_ID).exists(): form.make_pretty_city_val()
initial['europe_expo'] = True return self.render_to_response(self.get_context_data(form=form))
form = SubscribeSettingsForm(instance=setting, initial=initial) def get_form_kwargs(self):
return form kwargs = super(SettingsView, self).get_form_kwargs()
kwargs.update({
'initial': {'email': getattr(self.contact, 'email', self.request.user.email)},
'contact': self.contact,
})
return kwargs
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(SettingsView, self).get_context_data(**kwargs) context = super(SettingsView, self).get_context_data(**kwargs)
context['change_password_form'] = ChangePasswordForm() context['change_password_form'] = ChangePasswordForm()
context['subscribe'] = self.get_announce_form()
return context return context
def save_announce_settings(request):
if request.POST:
user = request.user
email = request.POST.get('email') or user.username
# check if setting subscription already exist
try:
contact, created = user.contact_set.get(email=email), False
except Contact.DoesNotExist:
contact, created = Contact.objects.create_contact(email, user, create_setting=True), True
setting = contact.contactsettings
form = SubscribeSettingsForm(request.POST, instance=setting)
if form.is_valid():
setting = form.save(commit=False)
setting.contact = contact
setting.save()
form.save_m2m()
form.save_additional_fields(setting)
else:
errors = form.errors
# todo: subscribe settings error handle
#not_valid
return HttpResponseRedirect(reverse('accounts_settings'))
class CalendarView(TemplateView): class CalendarView(TemplateView):
""" """
display template with user calendar(one month) display template with user calendar(one month)

@ -295,8 +295,11 @@ class SubscribeSettingsForm(AbstractSubscribeForm):
europe_expo = forms.BooleanField(required=False, label=_(u'Выставки Европы')) europe_expo = forms.BooleanField(required=False, label=_(u'Выставки Европы'))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(SubscribeSettingsForm, self).__init__(*args, **kwargs) self.contact = kwargs.pop('contact')
self.activation_send = False
lang = translation.get_language() lang = translation.get_language()
self.cities_choices = dict(City.objects.language(lang).all().values_list('pk', 'name'))
super(SubscribeSettingsForm, self).__init__(*args, **kwargs)
self.fields['theme'] = forms.MultipleChoiceField( self.fields['theme'] = forms.MultipleChoiceField(
choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Theme).all()], choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Theme).all()],
required=False, required=False,
@ -305,6 +308,13 @@ class SubscribeSettingsForm(AbstractSubscribeForm):
choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Country).all()], choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Country).all()],
required=False, required=False,
widget=forms.SelectMultiple(attrs={'placeholder': _(u'Страны'), 'id': 'id_sub_set_country'})) widget=forms.SelectMultiple(attrs={'placeholder': _(u'Страны'), 'id': 'id_sub_set_country'}))
if self.instance.pk:
self.initial['get_announce'] = self.instance.exponent_practicum or self.instance.organiser_practicum or self.instance.theme.exists()
self.initial['city'] = ','.join(['%s:%s'%(pk, self.cities_choices.get(pk)) for pk in set(self.instance.city.all().values_list('pk', flat=True))])
def make_pretty_city_val(self):
self.data = self.data.copy()
self.data['city'] = ','.join(['%s:%s'%(pk, self.cities_choices.get(pk)) for pk in set(self.instance.city.all().values_list('pk', flat=True))])
def save_additional_fields(self, settings): def save_additional_fields(self, settings):
get_announce = self.cleaned_data.get('get_announce') get_announce = self.cleaned_data.get('get_announce')
@ -342,6 +352,7 @@ class SubscribeSettingsForm(AbstractSubscribeForm):
contactsettings.country.clear() contactsettings.country.clear()
for country in self.cleaned_data['country']: for country in self.cleaned_data['country']:
contactsettings.country.add(country) contactsettings.country.add(country)
contactsettings.city.clear()
for city in self.cleaned_data['city']: for city in self.cleaned_data['city']:
contactsettings.city.add(city) contactsettings.city.add(city)
@ -354,6 +365,14 @@ class SubscribeSettingsForm(AbstractSubscribeForm):
return contactsettings return contactsettings
def clean_email(self): def clean_email(self):
if not self.contact:
return super(SubscribeSettingsForm, self).clean_email()
email = self.cleaned_data['email']
if self.contact.email != email:
self.contact.activated = False
self.contact.send_activation()
self.save()
self.activation_send = True
return self.cleaned_data['email'] return self.cleaned_data['email']

@ -1,27 +1,49 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.shortcuts import render_to_response import random
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.core.context_processors import csrf from accounts.models import User
from django.core.urlresolvers import reverse_lazy from city.models import City
from company.models import Company
from conference.models import Conference
from country.models import Country
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required from django.contrib.admin.views.decorators import staff_member_required
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage, InvalidPage from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.core.paginator import (
EmptyPage,
InvalidPage,
PageNotAnInteger,
Paginator
)
from django.core.urlresolvers import reverse_lazy
from django.db.models.deletion import ProtectedError from django.db.models.deletion import ProtectedError
from django.db.models.loading import get_model
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.utils.translation import get_language as lang
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic import ListView as OldListView
#forms and models from django.views.generic import DetailView, RedirectView
from django.views.generic.detail import (
SingleObjectMixin,
SingleObjectTemplateResponseMixin
)
from django.views.generic.edit import ModelFormMixin, ProcessFormView
from exposition.models import Exposition
from file.forms import FileModelForm from file.forms import FileModelForm
from file.models import TmpFile from file.models import TmpFile
from theme.models import Tag
from accounts.models import User
from functions.forms import AdminSearchForm from functions.forms import AdminSearchForm
from django.utils.translation import get_language as lang from functions.views_help import split_params
from haystack.query import EmptySearchQuerySet
from hvad.utils import get_translation_aware_manager from hvad.utils import get_translation_aware_manager
#python from meta.models import MetaSetting
import random from meta.views import Meta
from photoreport.models import Photoreport
from django.views.generic import ListView as OldListView from seminar.models import Seminar
from theme.models import Tag, Theme
from webinar.models import Webinar
class ListView(OldListView): class ListView(OldListView):
@ -91,8 +113,6 @@ def filtered_list(request, objects, template, item_per_page=settings.ADMIN_PAGIN
return render_to_response(template, {'objects': objects, 'search_form': AdminSearchForm()}) return render_to_response(template, {'objects': objects, 'search_form': AdminSearchForm()})
from django.db.models.loading import get_model
from theme.models import Theme
@staff_member_required @staff_member_required
def objects_list(request, Model, template, item_per_page=settings.ADMIN_PAGINATION): def objects_list(request, Model, template, item_per_page=settings.ADMIN_PAGINATION):
@ -235,18 +255,8 @@ def delete_object(request, Model, Form, url, prev_page,):
return render_to_response('delete.html', args) return render_to_response('delete.html', args)
#-----class------------------
from django.views.generic import DetailView
from functions.views_help import split_params
from city.models import City
from exposition.models import Exposition
from conference.models import Conference
from seminar.models import Seminar
from webinar.models import Webinar
from company.models import Company
from photoreport.models import Photoreport
class ExpoMixin(object): class ExpoMixin(object):
@ -271,8 +281,6 @@ single_page_filter = {Exposition:'event', Conference:'event', Seminar:'event', W
from meta.models import MetaSetting
from meta.views import Meta
class ExpoListView(ExpoMixin, ListView): class ExpoListView(ExpoMixin, ListView):
""" """
""" """
@ -359,7 +367,6 @@ class ExpoListView(ExpoMixin, ListView):
context['meta'] = m context['meta'] = m
return context return context
from country.models import Country
class EventDetail(ExpoMixin, DetailView): class EventDetail(ExpoMixin, DetailView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
@ -367,7 +374,6 @@ class EventDetail(ExpoMixin, DetailView):
return obj return obj
from haystack.query import EmptySearchQuerySet
class ExpoSearchView(ListView): class ExpoSearchView(ListView):
paginate_by = settings.CLIENT_PAGINATION paginate_by = settings.CLIENT_PAGINATION
@ -408,12 +414,6 @@ class ExpoSearchView(ListView):
return context return context
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.http import Http404
from django.views.generic import RedirectView
from django.views.generic.detail import SingleObjectMixin
class SimpleObjectChangeView(RedirectView, SingleObjectMixin): class SimpleObjectChangeView(RedirectView, SingleObjectMixin):
model = None model = None
url = None url = None
@ -500,3 +500,19 @@ class AjaxableResponseMixin(object):
return JsonResponse(data) return JsonResponse(data)
else: else:
return response return response
class CreateUpdateView(SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView):
def get_object(self, queryset=None):
try:
return super(CreateUpdateView,self).get_object(queryset)
except AttributeError:
return None
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).post(request, *args, **kwargs)

@ -1,10 +1,11 @@
{% extends 'admin/base.html' %} {% extends 'admin/base.html' %}
{% load i18n %}
{% block body %} {% block body %}
<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>{% trans "Списки рассылок" %}</h2>
</div> </div>
<div class="box-content"> <div class="box-content">
@ -20,9 +21,9 @@
<thead> <thead>
<tr> <tr>
<th>Название</th> <th>{% trans "Название" %}</th>
<th>Подписчиков</th> <th>{% trans "Подписчиков" %}</th>
<th>Отписалось</th> <th>{% trans "Отписалось" %}</th>
<th>&nbsp;</th> <th>&nbsp;</th>
<th>&nbsp;</th> <th>&nbsp;</th>
<th>&nbsp;</th> <th>&nbsp;</th>
@ -35,14 +36,14 @@
<td>{{ item.subscribers_count }}</td> <td>{{ item.subscribers_count }}</td>
<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 %}">{% trans "Изменить" %}</a> </td>
<td><a href="{% url 'newsletters_mailinglist_delete' item.id %}">Удалить</a> </td> <td><a href="{% url 'newsletters_mailinglist_delete' item.id %}">{% trans "Удалить" %}</a> </td>
<td><a href="{% url 'newsletters_contact_list' %}?mailinglist={{ item.id }}">Подписчики</a> </td> <td><a href="{% url 'newsletters_contact_list' %}?mailinglist={{ item.id }}">{% trans "Подписчики" %}</a> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<a class="btn btn-success" href="{% url 'newsletters_mailinglist_create' %}"><i class="icon-plus-sign icon-white"></i> Добавить новый список</a> <a class="btn btn-success" href="{% url 'newsletters_mailinglist_create' %}"><i class="icon-plus-sign icon-white"></i> {% trans "Добавить новый список" %}</a>
</div> </div>
{# pagination #} {# pagination #}
{% include 'admin/includes/admin_pagination.html' with page_obj=object_list %} {% include 'admin/includes/admin_pagination.html' with page_obj=object_list %}

@ -115,7 +115,8 @@
<div class="set-sect subscribe"> <div class="set-sect subscribe">
<header>{% trans 'настройка подписки' %}</header> <header>{% trans 'настройка подписки' %}</header>
<div class="set-sect-body"> <div class="set-sect-body">
<form action="{% url 'account_save_announce_settings' %}" method="post">{% csrf_token %} <form action="." method="post">
{% csrf_token %}
<ul class="tabs clearfix"> <ul class="tabs clearfix">
<li class="active"><a class="icon-big-email" href="#">{% trans 'по e-mail' %}</a></li> <li class="active"><a class="icon-big-email" href="#">{% trans 'по e-mail' %}</a></li>
@ -127,7 +128,7 @@
<div class="mf-announces clearfix"> <div class="mf-announces clearfix">
<div class="mf-subj-checks-title"> <div class="mf-subj-checks-title">
<label class="check"> <label class="check">
{{ subscribe.get_announce }} {{ form.get_announce }}
{% trans 'Получать анонсы' %}</label> {% trans 'Получать анонсы' %}</label>
</div> </div>
@ -135,36 +136,36 @@
<div class="mf-line mail"> <div class="mf-line mail">
<div class="mf-field">{{ subscribe.email }}</div> <div class="mf-field">{{ form.email }}</div>
<div class="mf-msg"></div> <div class="mf-msg">{{ form.email.errors }}</div>
</div> </div>
<div class="mf-line country"> <div class="mf-line country">
<div class="mf-field"> <div class="mf-field">
{{ subscribe.country }} {{ form.country }}
</div> </div>
<div class="mf-msg"></div> <div class="mf-msg">{{ form.country.errors }}</div>
</div> </div>
<div class="mf-line city"> <div class="mf-line city">
<div class="mf-field"> <div class="mf-field">
{{ subscribe.city }} {{ form.city }}
</div> </div>
<div class="mf-msg"></div> <div class="mf-msg">{{ form.city.errors }}</div>
</div> </div>
<div class="mf-line subj"> <div class="mf-line subj">
<div class="mf-field"> <div class="mf-field">
{{ subscribe.theme }} {{ form.theme }}
</div> </div>
<div class="mf-msg"></div> <div class="mf-msg">{{ form.theme.errors }}</div>
</div> </div>
<div class="mf-line period"> <div class="mf-line period">
<div class="mf-field"> <div class="mf-field">
{{ subscribe.periodic }} {{ form.periodic }}
</div> </div>
<div class="mf-msg"></div> <div class="mf-msg">{{ form.periodic.errors }}</div>
</div> </div>
</div> </div>
</div> </div>
@ -172,11 +173,11 @@
<hr /> <hr />
<div class="mf-line"> <div class="mf-line">
<label class="check">{{ subscribe.exponent_practicum }}{% trans '«Практикум экспонента»' %} <i>({% trans 'учимся эффективно участвовать в выставках и грамотно пиарить свою компанию на событиях' %})</i></label> <label class="check">{{ form.exponent_practicum }}{% trans '«Практикум экспонента»' %} <i>({% trans 'учимся эффективно участвовать в выставках и грамотно пиарить свою компанию на событиях' %})</i></label>
</div> </div>
<div class="mf-line"> <div class="mf-line">
<label class="check">{{ subscribe.organiser_practicum }}{% trans '«Практикум организатора событий»' %} <i>({% trans 'Создаем, наполняем и продвигаем собственные ивэнты' %})</i></label> <label class="check">{{ form.organiser_practicum }}{% trans '«Практикум организатора событий»' %} <i>({% trans 'Создаем, наполняем и продвигаем собственные ивэнты' %})</i></label>
</div> </div>
</li> </li>

Loading…
Cancel
Save