view email_list/forms.py @ 162:27b38cc65ca4

Set defaults for BooleanFields. THis suppresses a warning in Django 1.7 since the default changed in Django 1.6.
author Brian Neal <bgneal@gmail.com>
date Thu, 02 Apr 2015 19:03:46 -0500
parents 0a8942306b04
children
line wrap: on
line source
"""
Forms for the email_list application.

"""
from django import forms
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.mail import send_mail, send_mass_mail
from django.template.loader import render_to_string

from email_list.models import Subscriber


SUBSCRIBE_OPTS = [('sub', 'Subscribe'), ('unsub', 'Unsubscribe')]

ALREADY_SUBSCRIBED = "This email address is already subscribed."
NOT_SUBSCRIBED = "This email address is not on our list."


class SubscriberForm(forms.Form):
    name = forms.CharField(required=False,
            widget=forms.TextInput(attrs={
                    'class': 'form-control',
                    'placeholder': 'Your name (optional)'}))
    email = forms.EmailField(widget=forms.TextInput(attrs={
                    'class': 'form-control',
                    'type': 'email',
                    'placeholder': 'Your email address'}))
    location = forms.CharField(required=False,
            widget=forms.TextInput(attrs={
                     'class': 'form-control',
                     'placeholder': 'City, State (optional)'}))
    option = forms.ChoiceField(choices=SUBSCRIBE_OPTS,
            widget=forms.Select(attrs={'class': 'form-control'}))

    def clean(self):
        """
        This method ensures the appropriate action can be carried out and raises
        a validation error if not.

        """
        cleaned_data = super(SubscriberForm, self).clean()
        email = cleaned_data.get('email')
        option = cleaned_data.get('option')

        if not email or not option:
            return cleaned_data

        if option == 'sub':
            # is the user already subscribed (active)?
            try:
                subscriber = Subscriber.objects.get(email=email)
            except Subscriber.DoesNotExist:
                subscriber = Subscriber(email=email,
                        name=cleaned_data['name'],
                        location=cleaned_data['location'])
            else:
                if subscriber.is_active():
                    raise forms.ValidationError(ALREADY_SUBSCRIBED)
        else:
            # is the user already unsubscribed or not subscribed?
            try:
                subscriber = Subscriber.objects.get(email=email)
            except Subscriber.DoesNotExist:
                raise forms.ValidationError(NOT_SUBSCRIBED)

        # save the subscriber away for a future process() call
        self.subscriber = subscriber

        return cleaned_data

    def is_subscribe(self):
        """
        This function can be called after an is_valid() call to determine if the
        request was for a subscribe or unsubscribe.

        """
        return self.cleaned_data['option'] == 'sub'

    def process(self):
        """
        Call this function if is_valid() returns True. It carries out the user's
        subscription request.

        """
        if self.is_subscribe():
            self.subscriber.set_pending()
        else:
            self.subscriber.set_leaving()

        self.subscriber.save()
        send_email(self.subscriber)


class AdminEmailForm(forms.Form):
    subject = forms.CharField(max_length=255, required=True, label='Subject:',
        widget=forms.TextInput(attrs={'class': 'vTextField required',
            'size': '120'}))
    message = forms.CharField(label='Message:',
        widget=forms.Textarea(attrs={'class': 'vLargeTextField required'}))

    def __init__(self, *args, **kwargs):
        initial = kwargs.pop('initial', {})
        if 'subject' not in initial:
            initial['subject'] = '[%s] ' % settings.BAND_CONFIG['BAND_NAME']
            kwargs['initial'] = initial

        super(AdminEmailForm, self).__init__(*args, **kwargs)

    def save(self):
        """
        Call this function if is_valid() to send the mass email.
        Returns the number of mails sent.

        """
        subject = self.cleaned_data['subject']
        message = self.cleaned_data['message']
        return send_mail_to_subscribers(subject, message)


def send_email(subscriber):
    """
    This function sends out the appropriate email for the given subscriber.

    """
    config = settings.BAND_CONFIG
    band = config['BAND_NAME']
    from_email = config['BAND_EMAIL']

    url = "http://%s%s" % (config['BAND_DOMAIN'],
            reverse('email_list-confirm', kwargs={'key': subscriber.key}))

    if subscriber.is_pending():
        email_template = 'email_list/email_subscribe.txt'
    else:
        email_template = 'email_list/email_unsubscribe.txt'

    msg = render_to_string(email_template, {
        'band': band,
        'url': url,
        'band_domain': config['BAND_DOMAIN'],
        })

    subject = "[%s] Mailing List Confirmation" % band

    send_mail(subject, msg, from_email, [subscriber.email])


def send_mail_to_subscribers(subject, message):
    """
    Send an email to each mailing list subscriber with the given subject and
    message.
    Returns the number of messages sent.

    """
    config = settings.BAND_CONFIG
    unsubscribe_url = "http://%s%s" % (config['BAND_DOMAIN'],
              reverse('email_list-main'))

    msg = render_to_string('email_list/mailing_list.txt', {
        'band': config['BAND_NAME'],
        'unsubscribe_url': unsubscribe_url,
        'message': message,
        })

    mail_data = [(subject, msg, config['BAND_EMAIL'], [subscriber]) for
            subscriber in Subscriber.objects.values_list('email', flat=True)]

    send_mass_mail(mail_data)
    return len(mail_data)