From 624ec2ed88f0d48fd0efbf9960e8e0483039d38e Mon Sep 17 00:00:00 2001 From: Drew Larson Date: Mon, 29 May 2017 13:26:32 -0600 Subject: [PATCH] Add members to Mailchimp list with interests (#59) --- .../bikeshop/settings/development.py | 5 +++- .../bikeshop/settings/production.py | 2 ++ bikeshop_project/registration/__init__.py | 1 + bikeshop_project/registration/apps.py | 4 +++ bikeshop_project/registration/forms.py | 6 ++-- bikeshop_project/registration/handlers.py | 30 +++++++++++++++++++ .../migrations/0005_auto_20170528_2339.py | 28 +++++++++++++++++ bikeshop_project/registration/models.py | 12 +++++++- .../templates/edit_member_form.html | 20 +++++++++---- .../registration/templates/member_form.html | 10 +++++++ .../registration/tests/test_views.py | 6 ++-- requirements/base.txt | 4 ++- 12 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 bikeshop_project/registration/handlers.py create mode 100644 bikeshop_project/registration/migrations/0005_auto_20170528_2339.py diff --git a/bikeshop_project/bikeshop/settings/development.py b/bikeshop_project/bikeshop/settings/development.py index 2d8ddb2..ada4260 100644 --- a/bikeshop_project/bikeshop/settings/development.py +++ b/bikeshop_project/bikeshop/settings/development.py @@ -53,4 +53,7 @@ MIDDLEWARE_CLASSES.insert(0, 'django.middleware.common.CommonMiddleware') # noq CORS_ORIGIN_ALLOW_ALL = True -ALLOWED_HOSTS = ['workstand.docker','localhost'] +ALLOWED_HOSTS = ['workstand.docker', 'localhost'] + +MAILCHIMP_API_KEY = '78ee4eb990c5646256aac6c3b6a4e966-us7' +MAILCHIMP_USERNAME = 'drew@bcbc.bike' diff --git a/bikeshop_project/bikeshop/settings/production.py b/bikeshop_project/bikeshop/settings/production.py index 704c3a0..5cd41d6 100644 --- a/bikeshop_project/bikeshop/settings/production.py +++ b/bikeshop_project/bikeshop/settings/production.py @@ -65,3 +65,5 @@ ROLLBAR = { rollbar.init(**ROLLBAR) +MAILCHIMP_API_KEY = 'c6bba083fb5adc45a317dfb149d3676a-us7' +MAILCHIMP_USERNAME = 'drew@bcbc.bike' diff --git a/bikeshop_project/registration/__init__.py b/bikeshop_project/registration/__init__.py index e69de29..7e6a996 100644 --- a/bikeshop_project/registration/__init__.py +++ b/bikeshop_project/registration/__init__.py @@ -0,0 +1 @@ +default_app_config = 'registration.apps.RegistrationConfig' diff --git a/bikeshop_project/registration/apps.py b/bikeshop_project/registration/apps.py index 127d8e4..4c08a2a 100644 --- a/bikeshop_project/registration/apps.py +++ b/bikeshop_project/registration/apps.py @@ -3,3 +3,7 @@ from django.apps import AppConfig class RegistrationConfig(AppConfig): name = 'registration' + + def ready(self): + import registration.handlers + diff --git a/bikeshop_project/registration/forms.py b/bikeshop_project/registration/forms.py index 51bc6f1..ebcbaee 100644 --- a/bikeshop_project/registration/forms.py +++ b/bikeshop_project/registration/forms.py @@ -1,4 +1,4 @@ -from django.forms import ModelForm, EmailInput, TextInput, DateInput, CheckboxInput, BooleanField, Textarea, DateField +from django.forms import ModelForm, EmailInput, TextInput, DateInput, CheckboxInput, BooleanField, Textarea, DateField, CheckboxSelectMultiple from django.utils import timezone from registration.models import Member @@ -18,12 +18,14 @@ class MemberForm(ModelForm): exclude = ('waiver',) fields = ['email', 'email_consent', 'first_name', 'last_name', 'preferred_name', 'date_of_birth', 'guardian_name', 'phone', 'street', 'city', 'province', 'country', 'post_code', 'waiver', - 'banned', 'suspended', 'notes'] + 'banned', 'suspended', 'notes', 'involvement'] widgets = { 'email': EmailInput(attrs={'class': 'mdl-textfield__input'}), 'email_consent': CheckboxInput(attrs={'class': 'mdl-checkbox__input'}), 'first_name': TextInput(attrs={'class': 'mdl-textfield__input'}), 'last_name': TextInput(attrs={'class': 'mdl-textfield__input'}), + 'involvement': CheckboxSelectMultiple(choices=Member.involvement_choices, + attrs={'class': 'mdl-checkbox__input'}), 'preferred_name': TextInput(attrs={'class': 'mdl-textfield__input'}), 'guardian_name': DateInput(attrs={'class': 'mdl-textfield__input', 'disabled': 'disabled'}), 'phone': TextInput(attrs={'class': 'mdl-textfield__input', 'pattern': '[0-9]*'}), diff --git a/bikeshop_project/registration/handlers.py b/bikeshop_project/registration/handlers.py new file mode 100644 index 0000000..5f33b10 --- /dev/null +++ b/bikeshop_project/registration/handlers.py @@ -0,0 +1,30 @@ +import hashlib + +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.conf import settings +from mailchimp3 import MailChimp +from requests import HTTPError + +from registration.models import Member + + +@receiver(post_save, sender=Member, dispatch_uid='member.save_member') +def update_mailchimp(sender, instance, **kwargs): + if instance.email: + involvement = {id: True for id in instance.involvement} + client = MailChimp(settings.MAILCHIMP_USERNAME, settings.MAILCHIMP_API_KEY) + try: + response = client.lists.members.create_or_update('1c664549e2', + hashlib.md5(bytes(instance.email, 'utf-8')).hexdigest(), { + 'email_address': instance.email, + 'status': 'subscribed' if instance.email_consent else 'unsuscribed', + 'status_if_new': 'subscribed' if instance.email_consent else 'unsuscribed', + 'merge_fields': { + 'FNAME': instance.first_name, + 'LNAME': instance.last_name, + }, + 'interests': involvement + }) + except HTTPError as error: + pass \ No newline at end of file diff --git a/bikeshop_project/registration/migrations/0005_auto_20170528_2339.py b/bikeshop_project/registration/migrations/0005_auto_20170528_2339.py new file mode 100644 index 0000000..060f360 --- /dev/null +++ b/bikeshop_project/registration/migrations/0005_auto_20170528_2339.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2017-05-28 23:39 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import multiselectfield.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('registration', '0004_auto_20170518_0332'), + ] + + operations = [ + migrations.AddField( + model_name='member', + name='involvement', + field=multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('ac6922146d', 'General (receive email)'), ('3a5a719017', 'Volunteering'), ('0ebb0b5468', 'Events'), ('84309225e7', 'Workshops'), ('c96d389517', 'Shop')], max_length=54, null=True), + ), + migrations.AlterField( + model_name='member', + name='user', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/bikeshop_project/registration/models.py b/bikeshop_project/registration/models.py index 0a42612..4780846 100644 --- a/bikeshop_project/registration/models.py +++ b/bikeshop_project/registration/models.py @@ -1,6 +1,7 @@ from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager, PermissionsMixin) from django.db import models +from multiselectfield import MultiSelectField class CustomUserManager(BaseUserManager): @@ -70,8 +71,16 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): class Member(models.Model): + involvement_choices = ( + ('21cd9799b6', 'General (receive email)'), + ('3a5a719017', 'Volunteering'), + ('0ebb0b5468', 'Events'), + ('84309225e7', 'Workshops'), + ('c96d389517', 'Shop'), + ) + user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, - null=True) + null=True, blank=True) email = models.EmailField( verbose_name='email address', max_length=255, @@ -98,6 +107,7 @@ class Member(models.Model): banned = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) modified_at = models.DateTimeField(auto_now=True) + involvement = MultiSelectField(choices=involvement_choices, null=True, blank=True) def get_full_name(self): # The user is identified by their email address diff --git a/bikeshop_project/registration/templates/edit_member_form.html b/bikeshop_project/registration/templates/edit_member_form.html index 19e68ef..6c33255 100644 --- a/bikeshop_project/registration/templates/edit_member_form.html +++ b/bikeshop_project/registration/templates/edit_member_form.html @@ -63,11 +63,21 @@ {% endif %}
- -
+

Involvement

+ {% for checkbox in form.involvement %} + + {% endfor %} + +
+

Receive Email

+ +
diff --git a/bikeshop_project/registration/templates/member_form.html b/bikeshop_project/registration/templates/member_form.html index 7bb28f9..41a1f07 100644 --- a/bikeshop_project/registration/templates/member_form.html +++ b/bikeshop_project/registration/templates/member_form.html @@ -86,8 +86,18 @@ {% else %} Invalid email. {% endif %} + +
+

Involvement

+ {% for checkbox in form.involvement %} + + {% endfor %}
+

Receive Email