- {{ address }}
+ {{ form.address }}
{% for field in form %}
- {% if field|fieldtype == 'RadioSelect' %}
+ {% if field|fieldtype_is:'RadioSelect' %}
{% for choice in field %}
diff --git a/src/postorius/templates/postorius/user/list_options.html b/src/postorius/templates/postorius/user/list_options.html
index 7ae2657..f15fc0b 100644
--- a/src/postorius/templates/postorius/user/list_options.html
+++ b/src/postorius/templates/postorius/user/list_options.html
@@ -4,21 +4,28 @@
{% load bootstrap_tags %}
{% block head_title %}
-{% trans 'Member options' %} | {{ list.fqdn_listname }} - {{ block.super }}
+{% trans 'Member options' %} | {{ mlist.fqdn_listname }} - {{ block.super }}
{% endblock %}
{% block content %}
-{% trans 'Subscription options for' %} {{ list.fqdn_listname }}
-
-
-{% trans 'Use this form to change the email used for this subscription' %}:
-
-
-
-
+
+ {% user_nav 'settings_list' 'Subscription settings' %}
+
+
{% trans 'Subscription options for' %} {{ mlist.fqdn_listname }}
+
+
+
+ {% trans 'Use this form to change the email used for this subscription' %}:
+
+
+
+
+
+
+
{% endblock content %}
diff --git a/src/postorius/templates/postorius/user/mailman_settings.html b/src/postorius/templates/postorius/user/mailman_settings.html
index 5e83bc0..ae9661c 100644
--- a/src/postorius/templates/postorius/user/mailman_settings.html
+++ b/src/postorius/templates/postorius/user/mailman_settings.html
@@ -19,7 +19,7 @@
{% trans 'You are not yet subscribed to any lists, so you have no Mailman preferences.' %}
{% else %}
{% endif %}
diff --git a/src/postorius/templates/postorius/user/subscription_preferences.html b/src/postorius/templates/postorius/user/subscription_preferences.html
index 29da1b7..635b28b 100644
--- a/src/postorius/templates/postorius/user/subscription_preferences.html
+++ b/src/postorius/templates/postorius/user/subscription_preferences.html
@@ -12,7 +12,7 @@
{% user_nav 'settings_list' 'Subscription settings' %}
- {% if not zipped_data or nolists %}
+ {% if formset|length == 0 %}
{% trans 'No preferences available' %}
@@ -24,7 +24,7 @@
{{ formset.management_form }}
- {% for form, subscription in zipped_data %}
+ {% for form in formset %}
{% if forloop.first %}
@@ -37,10 +37,14 @@
{% endif %}
-
- {{ subscription.list_id }}
+
+
+
+ {{ form.list_id }}
+
+
{% for field in form %}
- {% if field|fieldtype == 'RadioSelect' %}
+ {% if field|fieldtype_is:'RadioSelect' %}
{% for choice in field %}
diff --git a/src/postorius/tests/mailman_api_tests/test_user.py b/src/postorius/tests/mailman_api_tests/test_user.py
index b3597a1..8352a4f 100644
--- a/src/postorius/tests/mailman_api_tests/test_user.py
+++ b/src/postorius/tests/mailman_api_tests/test_user.py
@@ -61,7 +61,6 @@
response = self.client.get(reverse('user_address_preferences'))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.context["formset"]), 3)
- self.assertEqual(len(response.context["zipped_data"]), 3)
def test_preferences_none(self):
# Mailman does not accept None values for boolean preferences. When
@@ -129,8 +128,7 @@
self.client.login(username='user', password='testpass')
response = self.client.get(reverse('user_mailmansettings'))
self.assertEquals(response.status_code, 200)
- self.assertIsInstance(response.context['settingsform'],
- UserPreferences)
+ self.assertIsInstance(response.context['form'], UserPreferences)
def test_presence_of_form_in_user_subscription_preferences(self):
self.client.login(username='user', password='testpass')
@@ -138,8 +136,8 @@
pre_confirmed=True, pre_approved=True)
response = self.client.get(reverse('user_subscription_preferences'))
self.assertEquals(response.status_code, 200)
- self.assertIsNotNone(response.context['zipped_data'])
- self.assertEquals(len(response.context['zipped_data']), 1)
+ self.assertIsNotNone(response.context['formset'])
+ self.assertEquals(len(response.context['formset']), 1)
def test_presence_of_form_in_user_list_options(self):
self.client.login(username='user', password='testpass')
diff --git a/src/postorius/urls.py b/src/postorius/urls.py
index 957428a..0cb9e10 100644
--- a/src/postorius/urls.py
+++ b/src/postorius/urls.py
@@ -81,7 +81,7 @@
user_views.UserMailmanSettingsView.as_view(),
name='user_mailmansettings'),
url(r'^accounts/list-options/(?P[^/]+)/$',
- user_views.user_list_options,
+ user_views.UserListOptionsView.as_view(),
name='user_list_options'),
# /domains/
url(r'^domains/$', domain_views.domain_index, name='domain_index'),
diff --git a/src/postorius/views/generic.py b/src/postorius/views/generic.py
index 851d1cd..425de56 100644
--- a/src/postorius/views/generic.py
+++ b/src/postorius/views/generic.py
@@ -22,9 +22,7 @@
from django.views.generic import TemplateView
from django_mailman3.lib.mailman import get_mailman_client
-from postorius.models import (List, MailmanUser, MailmanApiError,
- Mailman404Error)
-from postorius import utils
+from postorius.models import List
from postorius.auth.utils import set_user_access_props
@@ -59,55 +57,3 @@
if 'template' in kwargs:
self.template = kwargs['template']
return super(MailingListView, self).dispatch(request, *args, **kwargs)
-
-
-class MailmanUserView(TemplateView, MailmanClientMixin):
-
- """A generic view for everything based on a mailman.client
- user object.
-
- Sets self.mm_user to user object if user_id in **kwargs.
- """
-
- def _get_first_address(self, user_obj):
- for address in user_obj.addresses:
- return address
-
- def _get_user(self, user_id):
- try:
- user_obj = MailmanUser.objects.get(address=user_id)
- except Mailman404Error:
- user_obj = None
- # replace display_name with first address if display_name is not set
- if user_obj is not None:
- if (user_obj.display_name == 'None' or
- user_obj.display_name is None):
- user_obj.display_name = ''
- user_obj.first_address = self._get_first_address(user_obj)
- return user_obj
-
- def _get_memberships(self):
- memberships = []
- for m in self.mm_user.subscriptions:
- if m.role != "member":
- continue
- memberships.append(m)
- return memberships
-
- def dispatch(self, request, *args, **kwargs):
- # get the user object.
- user_id = None
- if 'user_id' in kwargs:
- user_id = kwargs['user_id']
- elif request.user.is_authenticated():
- user_id = request.user.email
- if user_id is not None:
- try:
- self.mm_user = self._get_user(user_id)
- except MailmanApiError:
- return utils.render_api_error(request)
-
- # set the template
- if 'template' in kwargs:
- self.template = kwargs['template']
- return super(MailmanUserView, self).dispatch(request, *args, **kwargs)
diff --git a/src/postorius/views/user.py b/src/postorius/views/user.py
index a03f485..ef3180b 100644
--- a/src/postorius/views/user.py
+++ b/src/postorius/views/user.py
@@ -25,197 +25,169 @@
from django.forms import formset_factory
from django.contrib import messages
from django.contrib.auth.decorators import login_required
-from django.shortcuts import redirect, render
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.utils.translation import gettext as _
+from django.views.generic import FormView
from django.http import Http404
from postorius import utils
-from postorius.models import (
- MailmanApiError, List, MailmanUser, Mailman404Error)
-from postorius.forms import UserPreferences, ChangeSubscriptionForm
-from postorius.views.generic import MailmanUserView
+from postorius.models import MailmanApiError, List, MailmanUser
+from postorius.forms import (
+ UserPreferences, UserPreferencesFormset, ChangeSubscriptionForm)
+from postorius.views.generic import MailmanClientMixin
logger = logging.getLogger(__name__)
-class UserMailmanSettingsView(MailmanUserView):
- """The logged-in user's global Mailman Preferences."""
+class UserPreferencesView(FormView, MailmanClientMixin):
+ """Generic view for the logged-in user's various preferences."""
+
+ form_class = UserPreferences
+
+ def get_context_data(self, **kwargs):
+ data = super(UserPreferencesView, self).get_context_data(**kwargs)
+ data['mm_user'] = self.mm_user
+ return data
+
+ def get_form_kwargs(self):
+ kwargs = super(UserPreferencesView, self).get_form_kwargs()
+ kwargs['preferences'] = self._get_preferences()
+ return kwargs
+
+ def _set_view_attributes(self, request, *args, **kwargs):
+ self.mm_user = MailmanUser.objects.get_or_create_from_django(
+ request.user)
@method_decorator(login_required)
- def post(self, request):
+ def dispatch(self, request, *args, **kwargs):
+ self._set_view_attributes(request, *args, **kwargs)
+ return super(UserPreferencesView, self).dispatch(
+ request, *args, **kwargs)
+
+ def form_valid(self, form):
try:
- mm_user = MailmanUser.objects.get(address=request.user.email)
- form = UserPreferences(request.POST)
- if form.is_valid():
- preferences = mm_user.preferences
- for key in form.fields.keys():
- if form.cleaned_data[key] is not None:
- # None: nothing set yet. Remember to remove this test
- # when Mailman accepts None as a "reset to default"
- # value.
- preferences[key] = form.cleaned_data[key]
- preferences.save()
- messages.success(request,
- _('Your preferences have been updated.'))
- else:
- messages.error(request, _('Something went wrong.'))
- except MailmanApiError:
- return utils.render_api_error(request)
- except Mailman404Error as e:
- messages.error(request, e.msg)
- return redirect("user_mailmansettings")
-
- @method_decorator(login_required)
- def get(self, request):
- try:
- mm_user = MailmanUser.objects.get_or_create_from_django(
- request.user)
- except MailmanApiError:
- return utils.render_api_error(request)
- settingsform = UserPreferences(initial=mm_user.preferences)
- return render(request, 'postorius/user/mailman_settings.html',
- {'mm_user': mm_user, 'settingsform': settingsform})
+ form.save()
+ except HTTPError as e:
+ messages.error(self.request, e.msg)
+ if form.has_changed():
+ messages.success(
+ self.request, _('Your preferences have been updated.'))
+ else:
+ messages.info(self.request, _('Your preferences did not change.'))
+ return super(UserPreferencesView, self).form_valid(form)
-class UserAddressPreferencesView(MailmanUserView):
+class UserMailmanSettingsView(UserPreferencesView):
+ """The logged-in user's global Mailman preferences."""
+
+ form_class = UserPreferences
+ template_name = 'postorius/user/mailman_settings.html'
+ success_url = reverse_lazy('user_mailmansettings')
+
+ def _get_preferences(self):
+ return self.mm_user.preferences
+
+
+class UserAddressPreferencesView(UserPreferencesView):
"""The logged-in user's address-based Mailman Preferences."""
- @method_decorator(login_required)
- def post(self, request):
- try:
- mm_user = MailmanUser.objects.get(address=request.user.email)
- formset_class = formset_factory(UserPreferences)
- formset = formset_class(request.POST)
- if formset.is_valid():
- for form, address in zip(formset.forms, mm_user.addresses):
- preferences = address.preferences
- for key in form.fields.keys():
- if (key in form.cleaned_data and
- form.cleaned_data[key] is not None):
- # None: nothing set yet. Remember to remove this
- # test when Mailman accepts None as a
- # "reset to default" value.
- preferences[key] = form.cleaned_data[key]
- preferences.save()
- messages.success(request,
- _('Your preferences have been updated.'))
- else:
- messages.error(request, _('Something went wrong.'))
- except MailmanApiError:
- return utils.render_api_error(request)
- except HTTPError as e:
- messages.error(request, e.msg)
- return redirect("user_address_preferences")
+ template_name = 'postorius/user/address_preferences.html'
+ success_url = reverse_lazy('user_address_preferences')
- @method_decorator(login_required)
- def get(self, request):
- try:
- helperform = UserPreferences()
- mm_user = MailmanUser.objects.get(address=request.user.email)
- addresses = mm_user.addresses
- AFormset = formset_factory(UserPreferences, extra=len(addresses))
- formset = AFormset()
- zipped_data = zip(formset.forms, addresses)
- for form, address in zipped_data:
- form.initial = address.preferences
- except MailmanApiError:
- return utils.render_api_error(request)
- except Mailman404Error:
- return render(request, 'postorius/user/address_preferences.html',
- {'nolists': 'true'})
- return render(request, 'postorius/user/address_preferences.html',
- {'mm_user': mm_user, 'addresses': addresses,
- 'helperform': helperform, 'formset': formset,
- 'zipped_data': zipped_data})
+ def get_form_class(self):
+ return formset_factory(
+ UserPreferences, formset=UserPreferencesFormset, extra=0)
+
+ def _get_preferences(self):
+ return [address.preferences for address in self.mm_user.addresses]
+
+ def get_context_data(self, **kwargs):
+ data = super(UserAddressPreferencesView, self).get_context_data(
+ **kwargs)
+ data['formset'] = data.pop('form')
+ for form, address in zip(
+ data['formset'].forms, self.mm_user.addresses):
+ form.address = address
+ return data
-@login_required
-def user_list_options(request, list_id):
- mlist = List.objects.get_or_404(fqdn_listname=list_id)
- mm_user = MailmanUser.objects.get(address=request.user.email)
- subscription = None
- for s in mm_user.subscriptions:
- if s.role == 'member' and s.list_id == list_id:
- subscription = s
- break
- if not subscription:
- raise Http404(_('Subscription does not exist'))
- preferences = subscription.preferences
- if request.method == 'POST':
- form = UserPreferences(request.POST)
- if form.is_valid():
- for key in form.cleaned_data.keys():
- if form.cleaned_data[key] is not None:
- # None: nothing set yet. Remember to remove this test
- # when Mailman accepts None as a "reset to default"
- # value.
- preferences[key] = form.cleaned_data[key]
- preferences.save()
- messages.success(request, _('Your preferences have been updated.'))
- return redirect('user_list_options', list_id)
- else:
- messages.error(request, _('Something went wrong.'))
- else:
- form = UserPreferences(initial=subscription.preferences)
- user_emails = EmailAddress.objects.filter(
- user=request.user, verified=True).order_by(
- "email").values_list("email", flat=True)
- subscription_form = ChangeSubscriptionForm(
- user_emails, initial={'email': subscription.email})
- return render(request, 'postorius/user/list_options.html',
- {'form': form, 'list': mlist,
- 'change_subscription_form': subscription_form})
+class UserListOptionsView(UserPreferencesView):
+ """The logged-in user's subscription preferences."""
+
+ form_class = UserPreferences
+ template_name = 'postorius/user/list_options.html'
+
+ def _get_subscription(self):
+ subscription = None
+ for s in self.mm_user.subscriptions:
+ if s.role == 'member' and s.list_id == self.mlist.list_id:
+ subscription = s
+ break
+ if not subscription:
+ raise Http404(_('Subscription does not exist'))
+ return subscription
+
+ def _set_view_attributes(self, request, *args, **kwargs):
+ super(UserListOptionsView, self)._set_view_attributes(
+ request, *args, **kwargs)
+ self.mlist = List.objects.get_or_404(fqdn_listname=kwargs['list_id'])
+ self.subscription = self._get_subscription()
+
+ def _get_preferences(self):
+ return self.subscription.preferences
+
+ def get_context_data(self, **kwargs):
+ data = super(UserListOptionsView, self).get_context_data(**kwargs)
+ data['mlist'] = self.mlist
+ user_emails = EmailAddress.objects.filter(
+ user=self.request.user, verified=True).order_by(
+ "email").values_list("email", flat=True)
+ data['change_subscription_form'] = ChangeSubscriptionForm(
+ user_emails, initial={'email': self.subscription.email})
+ return data
+
+ def get_success_url(self):
+ return reverse(
+ 'user_list_options', kwargs=dict(list_id=self.mlist.list_id))
-class UserSubscriptionPreferencesView(MailmanUserView):
+class UserSubscriptionPreferencesView(UserPreferencesView):
"""The logged-in user's subscription-based Mailman Preferences."""
- @method_decorator(login_required)
- def post(self, request):
- try:
- subscriptions = self._get_memberships()
- formset_class = formset_factory(UserPreferences)
- formset = formset_class(request.POST)
- if formset.is_valid():
- for form, subscription in zip(formset.forms, subscriptions):
- preferences = subscription.preferences
- for key in form.cleaned_data.keys():
- if form.cleaned_data[key] is not None:
- # None: nothing set yet. Remember to remove this
- # test when Mailman accepts None as a
- # "reset to default" value.
- preferences[key] = form.cleaned_data[key]
- preferences.save()
- messages.success(request,
- _('Your preferences have been updated.'))
- else:
- messages.error(request, _('Something went wrong.'))
- except MailmanApiError:
- return utils.render_api_error(request)
- except HTTPError as e:
- messages.error(request, e.msg)
- return redirect("user_subscription_preferences")
+ template_name = 'postorius/user/subscription_preferences.html'
+ success_url = reverse_lazy('user_subscription_preferences')
- @method_decorator(login_required)
- def get(self, request):
- try:
- subscriptions = self._get_memberships()
- Mformset = formset_factory(
- UserPreferences, extra=len(subscriptions))
- formset = Mformset()
- zipped_data = zip(formset.forms, subscriptions)
- for form, subscription in zipped_data:
- form.initial = subscription.preferences
- except MailmanApiError:
- return utils.render_api_error(request)
- except Mailman404Error:
- return render(request,
- 'postorius/user/subscription_preferences.html',
- {'nolists': 'true'})
- return render(request, 'postorius/user/subscription_preferences.html',
- {'zipped_data': zipped_data, 'formset': formset})
+ def _get_subscriptions(self):
+ subscriptions = []
+ for s in self.mm_user.subscriptions:
+ if s.role != 'member':
+ continue
+ subscriptions.append(s)
+ return subscriptions
+
+ def _set_view_attributes(self, request, *args, **kwargs):
+ super(UserSubscriptionPreferencesView, self)._set_view_attributes(
+ request, *args, **kwargs)
+ self.subscriptions = self._get_subscriptions()
+
+ def get_form_class(self):
+ return formset_factory(
+ UserPreferences, formset=UserPreferencesFormset, extra=0)
+
+ def _get_preferences(self):
+ return [sub.preferences for sub in self.subscriptions]
+
+ def get_context_data(self, **kwargs):
+ data = super(UserSubscriptionPreferencesView, self).get_context_data(
+ **kwargs)
+ data['formset'] = data.pop('form')
+ for form, subscription in zip(
+ data['formset'].forms, self.subscriptions):
+ form.list_id = subscription.list_id
+ return data
@login_required