In daily work email branding is important because it will call your customer to action.
MailFactory comes with a little tool that helps you to test your emails.
To do that, we generate a Django Form so that you may provide a context for your email.
Here's how you can customize your administration form.
You just need to enable the urls:
urlpatterns = (
# ...
url(r'^admin/mails/', include('mail_factory.urls')),
url(r'^admin/', include(admin.site.urls)),
# ...
)
Then you can connect to /admin/mails/ to try out your emails.
These two calls are equivalent:
from mail_factory import factory, BaseMail
class InvitationMail(BaseMail):
template_name = "invitation"
params = ['user']
factory.register(InvitationMail)
from mail_factory import factory, MailForm, BaseMail
class InvitationMail(BaseMail):
template_name = "invitation"
params = ['user']
factory.register(InvitationMail, MailForm)
We may also want to build a very specific form for our email.
Let's say we have a share this page email, with a custom message:
from mail_factory import factory, BaseMail, MailForm
class SharePageMail(BaseMail):
template_name = "share_page"
params = ['user', 'message', 'date']
class SharePageMailForm(MailForm):
user = forms.ModelChoiceField(queryset=User.objects.all())
message = forms.CharField(widget=forms.Textarea)
date = forms.DateTimeField()
factory.register(SharePageMail, SharePageMailForm)
You can define Meta.initial
to automatically provide a context for
your mail.
import datetime
import uuid
from django import forms
from django.conf import settings
from django.urls import reverse_lazy as reverse
from mail_factory import factory, MailForm, BaseMail
class ShareBucketMail(BaseMail):
template_name = 'share_bucket'
params = ['first_name', 'last_name', 'comment', 'expiration_date',
'activation_url']
def activation_url():
return '%s%s' % (
settings.SITE_URL, reverse('share:index',
args=[str(uuid.uuid4()).replace('-', '')]))
class ShareBucketForm(MailForm):
expiration_date = forms.DateField()
class Meta:
initial = {'first_name': 'Thibaut',
'last_name': 'Dupont',
'comment': 'I shared with you documents we talked about.',
'expiration_date': datetime.date.today,
'activation_url': activation_url}
factory.register(ShareBucketMail, ShareBucketForm)
Then the mail form will be autopopulated with this data.
By default, all email params are represented as a forms.CharField()
, which
uses a basic text input.
Let's create a project wide BaseMailForm
that uses a ModelChoiceField
on auth.models.User
each time a user
param is needed in the email.
from django.contrib.auth.models import User
from django import forms
from mail_factory.forms import MailForm
class BaseMailForm(MailForm):
def get_field_for_param(self, param):
if param == 'user':
return forms.ModelChoiceField(
queryset=User.objects.order_by('last_name', 'first_name'))
return super(BaseMailForm, self).get_field_for_param(param)
Now you need to inherit from this BaseMailForm
to make use of it for your
custom mail forms:
class MyCustomMailForm(BaseMailForm):
# your own customizations here
If you want this BaseMailForm
to be used automatically when registering a
mail with no custom form, here's how to do it:
from mail_factory import MailFactory
class BaseMailFactory(MailFactory):
mail_form = BaseMailForm
factory = BaseMailFactory
And use this new factory everywhere in your code instead of
mail_factory.factory
.
Sometimes however, you don't need or want to render the email, having to provide some real data (eg a user, a site, some complex model...).
The emails may be written by your sales or marketing team, set up by your designer, and all of those don't want to cope with the setting up of real data.
All they want is to be able to preview the email, in the different languages available.
This is where email previewing is useful.
Previewing is available straight away thanks to sane defaults. It uses the
data returned by get_preview_data
to add (possibly) non valid data to the
context used to preview the mail.
This data will override any data that was returned by get_context_data
,
which in turn uses the form's Meta.initial, and in last resort, returns "###".
The preview can thus use fake data: let's take the second example from this
page, the SharePageMail
:
import datetime
from django.contrib.auth.models import User
from django.conf import settings
from mail_factory import factory, MailForm
class SharePageMailForm(MailForm):
user = forms.ModelChoiceField(queryset=User.objects.all())
message = forms.CharField(widget=forms.Textarea)
date = forms.DateTimeField()
class Meta:
initial = {'message': 'Some message'}
def get_preview_data(self, **kwargs):
data = super(SharePageMailForm, self).get_preview_data(**kwargs)
data['date'] = datetime.date.today()
# create on-the-fly fake User, not saved in database: not valid data
# but still added to context for previewing
data['user'] = User(first_name='John', last_name='Doe')
return data
factory.register(SharePageMail, SharePageMailForm)
With this feature, when displaying the mail form in the admin (to render the
email with real data), the email will also be previewed in the different
available languages with the fake data provided by the form's
get_preview_data
, which overrides the data returned by
get_context_data
.