src/django_opt_out/views.py
# -*- coding: utf-8 -*-
import logging
from django.conf import settings
from django.db.models import Q
from django.shortcuts import redirect, resolve_url
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateView
from django.views.generic.edit import ModelFormMixin
from django_powerbank.views import Http403
from django_powerbank.views.auth import AbstractAccessView
from pascal_templates.views import CreateView, DetailView, UpdateView
from . import forms, models, signals
from .utils import validate_password
log = logging.getLogger(__name__)
class OptOutConfirm(CreateView):
model = models.OptOut
template_name = "django_opt_out/OptOut/form.html"
form_class = forms.OptOutForm
def email_confirmed(self):
email = self.request.GET.get('email', None)
auth = self.request.GET.get('auth', None)
if email and auth:
return validate_password(email, auth)
def get_initial(self):
return self.request.GET.dict()
def get_form(self, form_class=None):
form = super(OptOutConfirm, self).get_form(form_class)
feedback = form.fields['feedback']
tags = dict(self.get_tags())
tags_filter = Q(tags__name__in=tags.keys())
if tags.get('default', True) in (True, None, '', '1', 'True', 'true', 'on'):
tags_filter |= Q(tags__isnull=True)
feedback.queryset = feedback.queryset.filter(tags_filter)
feedback.initial = list(feedback.queryset.filter(default=True).values_list('pk', flat=True))
if self.email_confirmed():
form.instance.confirmed = timezone.now()
return form
def get_context_data(self, **kwargs):
kwargs['tags'] = self.get_tags()
signals.send_signal(signals.opt_out_visited, self.__class__, view=self, request=self.request, context=kwargs)
return super(OptOutConfirm, self).get_context_data(**kwargs)
def form_valid(self, form):
# noinspection PyAttributeOutsideInit
self.object = form.save()
self.save_tags()
signals.send_signal(signals.opt_out_submitted, self.__class__, view=self, request=self.request, opt_out=self.object)
return super(ModelFormMixin, self).form_valid(form)
def get_tags(self):
for name in self.request.GET.getlist('tag', []):
yield name.split(":", 1) if ":" in name else (name, None)
def save_tags(self):
for name, value in self.get_tags():
tag = models.OptOutTag.objects.filter(name=name).first()
if tag is None:
log.warning("Tag does not exist: %s", name)
continue
self.object.tags.create(tag=tag, value=value)
def get_success_url(self):
goodbye_view = settings.OPT_OUT_GOODBYE_VIEW or "django_opt_out:OptOutSuccess"
return resolve_url(goodbye_view, pk=self.object.pk, secret=self.object.secret, email=self.object.email)
class OptOutBase(AbstractAccessView):
def check_authorization(self, *args, **kwargs):
# noinspection PyUnresolvedReferences
item = self.get_object()
email = self.kwargs['email']
secret = self.kwargs['secret']
if item.secret != secret or item.email != email:
msg = _("Request authentication failed, secret or email is incorrect.")
raise Http403(msg)
class OptOutSuccess(OptOutBase, DetailView):
model = models.OptOut
template_name = "django_opt_out/OptOut/success.html"
def post(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.delete()
signals.send_signal(signals.opt_out_deleted, self.__class__, view=self, request=self.request, opt_out=self.object)
return redirect('django_opt_out:OptOutRemoved')
class OptOutRemoved(TemplateView):
template_name = "django_opt_out/OptOut/removed.html"
class OptOutUpdate(OptOutBase, UpdateView):
model = models.OptOut
form_class = forms.OptOutForm
template_name = "django_opt_out/OptOut/form.html"
def get_form(self, form_class=None):
form = super(OptOutUpdate, self).get_form(form_class)
feedback = form.fields['feedback']
tags = self.object.tags.all().values_list('tag__pk', flat=True)
feedback.queryset = feedback.queryset.filter(Q(tags__in=tags) | Q(tags__isnull=True))
feedback.initial = list(self.object.feedback.all().values_list('pk', flat=True))
# form.fields['email'].readonly = True
return form
def get_success_url(self):
return resolve_url("django_opt_out:OptOutSuccess", self.object.pk, self.object.secret, self.object.email)