Browse Source

Add members to Mailchimp list with interests (#59)

feature/upgrade-admin-visits
Drew Larson 8 years ago
committed by GitHub
parent
commit
624ec2ed88
  1. 5
      bikeshop_project/bikeshop/settings/development.py
  2. 2
      bikeshop_project/bikeshop/settings/production.py
  3. 1
      bikeshop_project/registration/__init__.py
  4. 4
      bikeshop_project/registration/apps.py
  5. 6
      bikeshop_project/registration/forms.py
  6. 30
      bikeshop_project/registration/handlers.py
  7. 28
      bikeshop_project/registration/migrations/0005_auto_20170528_2339.py
  8. 12
      bikeshop_project/registration/models.py
  9. 20
      bikeshop_project/registration/templates/edit_member_form.html
  10. 10
      bikeshop_project/registration/templates/member_form.html
  11. 6
      bikeshop_project/registration/tests/test_views.py
  12. 2
      requirements/base.txt

5
bikeshop_project/bikeshop/settings/development.py

@ -53,4 +53,7 @@ MIDDLEWARE_CLASSES.insert(0, 'django.middleware.common.CommonMiddleware') # noq
CORS_ORIGIN_ALLOW_ALL = True 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'

2
bikeshop_project/bikeshop/settings/production.py

@ -65,3 +65,5 @@ ROLLBAR = {
rollbar.init(**ROLLBAR) rollbar.init(**ROLLBAR)
MAILCHIMP_API_KEY = 'c6bba083fb5adc45a317dfb149d3676a-us7'
MAILCHIMP_USERNAME = 'drew@bcbc.bike'

1
bikeshop_project/registration/__init__.py

@ -0,0 +1 @@
default_app_config = 'registration.apps.RegistrationConfig'

4
bikeshop_project/registration/apps.py

@ -3,3 +3,7 @@ from django.apps import AppConfig
class RegistrationConfig(AppConfig): class RegistrationConfig(AppConfig):
name = 'registration' name = 'registration'
def ready(self):
import registration.handlers

6
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 django.utils import timezone
from registration.models import Member from registration.models import Member
@ -18,12 +18,14 @@ class MemberForm(ModelForm):
exclude = ('waiver',) exclude = ('waiver',)
fields = ['email', 'email_consent', 'first_name', 'last_name', 'preferred_name', 'date_of_birth', fields = ['email', 'email_consent', 'first_name', 'last_name', 'preferred_name', 'date_of_birth',
'guardian_name', 'phone', 'street', 'city', 'province', 'country', 'post_code', 'waiver', 'guardian_name', 'phone', 'street', 'city', 'province', 'country', 'post_code', 'waiver',
'banned', 'suspended', 'notes'] 'banned', 'suspended', 'notes', 'involvement']
widgets = { widgets = {
'email': EmailInput(attrs={'class': 'mdl-textfield__input'}), 'email': EmailInput(attrs={'class': 'mdl-textfield__input'}),
'email_consent': CheckboxInput(attrs={'class': 'mdl-checkbox__input'}), 'email_consent': CheckboxInput(attrs={'class': 'mdl-checkbox__input'}),
'first_name': TextInput(attrs={'class': 'mdl-textfield__input'}), 'first_name': TextInput(attrs={'class': 'mdl-textfield__input'}),
'last_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'}), 'preferred_name': TextInput(attrs={'class': 'mdl-textfield__input'}),
'guardian_name': DateInput(attrs={'class': 'mdl-textfield__input', 'disabled': 'disabled'}), 'guardian_name': DateInput(attrs={'class': 'mdl-textfield__input', 'disabled': 'disabled'}),
'phone': TextInput(attrs={'class': 'mdl-textfield__input', 'pattern': '[0-9]*'}), 'phone': TextInput(attrs={'class': 'mdl-textfield__input', 'pattern': '[0-9]*'}),

30
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

28
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),
),
]

12
bikeshop_project/registration/models.py

@ -1,6 +1,7 @@
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager, from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager,
PermissionsMixin) PermissionsMixin)
from django.db import models from django.db import models
from multiselectfield import MultiSelectField
class CustomUserManager(BaseUserManager): class CustomUserManager(BaseUserManager):
@ -70,8 +71,16 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
class Member(models.Model): 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, user = models.OneToOneField(CustomUser, on_delete=models.CASCADE,
null=True) null=True, blank=True)
email = models.EmailField( email = models.EmailField(
verbose_name='email address', verbose_name='email address',
max_length=255, max_length=255,
@ -98,6 +107,7 @@ class Member(models.Model):
banned = models.BooleanField(default=False) banned = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True) modified_at = models.DateTimeField(auto_now=True)
involvement = MultiSelectField(choices=involvement_choices, null=True, blank=True)
def get_full_name(self): def get_full_name(self):
# The user is identified by their email address # The user is identified by their email address

20
bikeshop_project/registration/templates/edit_member_form.html

@ -63,11 +63,21 @@
{% endif %} {% endif %}
</div> </div>
<div> <div>
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="{{ form.email_consent.id_for_label }}"> <h3 class="template__header mdl-typography--body-2">Involvement</h3>
{{ form.email_consent }} {% for checkbox in form.involvement %}
<span class="mdl-checkbox__label">{{ form.email_consent.label }}</span> <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="{{ checkbox.id_for_label }}">
</label> {{ checkbox }}
</div> <span class="mdl-checkbox__label">{{ checkbox.label }}</span>
</label>
{% endfor %}
</div>
<div>
<h3 class="template__header mdl-typography--body-2">Receive Email</h3>
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="{{ form.email_consent.id_for_label }}">
{{ form.email_consent }}
<span class="mdl-checkbox__label">{{ form.email_consent.label }}</span>
</label>
</div>
</div> </div>
</div> </div>

10
bikeshop_project/registration/templates/member_form.html

@ -86,8 +86,18 @@
{% else %} {% else %}
<span class="mdl-textfield__error">Invalid email.</span> <span class="mdl-textfield__error">Invalid email.</span>
{% endif %} {% endif %}
</div>
<div>
<h3 class="template__header mdl-typography--body-2">Involvement</h3>
{% for checkbox in form.involvement %}
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="{{ checkbox.id_for_label }}">
{{ checkbox }}
<span class="mdl-checkbox__label">{{ checkbox.label }}</span>
</label>
{% endfor %}
</div> </div>
<div> <div>
<h3 class="template__header mdl-typography--body-2">Receive Email</h3>
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="{{ form.email_consent.id_for_label }}"> <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="{{ form.email_consent.id_for_label }}">
{{ form.email_consent }} {{ form.email_consent }}
<span class="mdl-checkbox__label">{{ form.email_consent.label }}</span> <span class="mdl-checkbox__label">{{ form.email_consent.label }}</span>

6
bikeshop_project/registration/tests/test_views.py

@ -83,8 +83,8 @@ class TestMemberSearchView(TestCase):
if self.query in result['name']]) if self.query in result['name']])
def test_search_name_with_space(self): def test_search_name_with_space(self):
mommy.make(Member, first_name="Test", last_name="Person") mommy.make(Member, first_name="Some", last_name="Thing")
url = reverse('member_search', kwargs=dict(query='Test Person')) url = reverse('member_search', kwargs=dict(query='Some Th'))
c = Client() c = Client()
c.force_login(self.user) c.force_login(self.user)
response = c.get(url) response = c.get(url)
@ -96,7 +96,7 @@ class TestMemberSearchView(TestCase):
# Check if our made up first name is in the name returned. # Check if our made up first name is in the name returned.
self.assertTrue([result['name'] for result in results self.assertTrue([result['name'] for result in results
if 'Test Person' in result['name']]) if 'Some Thing' in result['name']])

2
requirements/base.txt

@ -12,3 +12,5 @@ django-webpack-loader
requests requests
PyYAML PyYAML
djangorestframework-jwt==1.9.0 djangorestframework-jwt==1.9.0
django-multiselectfield==0.1.4
mailchimp3==2.0.11

Loading…
Cancel
Save