Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add identifier to EmailTemplate #324

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

next
----
* Add unique `identifier` field to model `EmailTemplate`. It can be used to access templates from Python code
and leaves the `name` field as a human readable representation of that template.

Version 3.5.2 (2020-11-05)
--------------------------
* Fixed an issue where Post Office's admin interface doesn't show. Thanks @christianciu!
Expand Down
31 changes: 21 additions & 10 deletions post_office/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from django.urls import reverse
from django.utils.html import format_html
from django.utils.text import Truncator
from django.utils.translation import gettext_lazy as _
from django.utils.translation import gettext_lazy as _, get_language

from .fields import CommaSeparatedEmailField
from .models import Attachment, Log, Email, EmailTemplate, STATUS
Expand Down Expand Up @@ -241,7 +241,7 @@ class EmailTemplateAdminForm(forms.ModelForm):

class Meta:
model = EmailTemplate
fields = ['name', 'description', 'subject', 'content', 'html_content', 'language',
fields = ['language', 'name', 'description', 'subject', 'content', 'html_content',
'default_template']

def __init__(self, *args, **kwargs):
Expand All @@ -250,13 +250,21 @@ def __init__(self, *args, **kwargs):
if instance and instance.language:
self.fields['language'].disabled = True

def get_initial_for_field(self, field, field_name):
"""
For new translated templates, copy the name from the default email template.
"""
if field_name == 'name' and self.instance and self.instance.id is None and 'default_template' in self.fields:
return self.fields['default_template'].parent_instance.name
return super().get_initial_for_field(field, field_name)


class EmailTemplateInline(admin.StackedInline):
form = EmailTemplateAdminForm
formset = EmailTemplateAdminFormSet
model = EmailTemplate
extra = 0
fields = ('language', 'subject', 'content', 'html_content',)
fields = ['language', 'name', 'description', 'subject', 'content', 'html_content']
formfield_overrides = {
models.CharField: {'widget': SubjectField}
}
Expand All @@ -268,11 +276,11 @@ def get_max_num(self, request, obj=None, **kwargs):
# @admin.register(EmailTemplate)
class EmailTemplateAdmin(admin.ModelAdmin):
form = EmailTemplateAdminForm
list_display = ('name', 'description_shortened', 'subject', 'languages_compact', 'created')
search_fields = ('name', 'description', 'subject')
list_display = ['translated_name', 'identifier', 'subject', 'languages_compact', 'created']
search_fields = ['name', 'identifier', 'description', 'subject']
fieldsets = [
(None, {
'fields': ('name', 'description'),
'fields': ('name', 'description', 'identifier'),
}),
(_("Default Content"), {
'fields': ('subject', 'content', 'html_content'),
Expand All @@ -286,10 +294,13 @@ class EmailTemplateAdmin(admin.ModelAdmin):
def get_queryset(self, request):
return self.model.objects.filter(default_template__isnull=True)

def description_shortened(self, instance):
return Truncator(instance.description.split('\n')[0]).chars(200)
description_shortened.short_description = _("Description")
description_shortened.admin_order_field = 'description'
def translated_name(self, instance):
try:
return instance.translated_templates.get(language=get_language()).name
except EmailTemplate.DoesNotExist:
return instance.name
translated_name.short_description = _("Name")
translated_name.admin_order_field = 'name'

def languages_compact(self, instance):
languages = [tt.language for tt in instance.translated_templates.order_by('language')]
Expand Down
37 changes: 37 additions & 0 deletions post_office/migrations/0010_auto_20200723_1131.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 2.2.10 on 2020-07-23 09:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('post_office', '0009_requeued_mode'),
]

operations = [
migrations.AddField(
model_name='emailtemplate',
name='identifier',
field=models.CharField(blank=True, help_text='Unique template identifier', max_length=50, null=True, unique=True, verbose_name='Identifier'),
),
migrations.AlterField(
model_name='attachment',
name='emails',
field=models.ManyToManyField(related_name='attachments', to='post_office.Email', verbose_name='Emails'),
),
migrations.AlterField(
model_name='email',
name='expires_at',
field=models.DateTimeField(blank=True, help_text="Email won't be sent after this timestamp", null=True, verbose_name='Expires'),
),
migrations.AlterField(
model_name='email',
name='scheduled_time',
field=models.DateTimeField(blank=True, db_index=True, help_text='The scheduled sending time', null=True, verbose_name='Scheduled Time'),
),
migrations.AlterUniqueTogether(
name='emailtemplate',
unique_together=set(),
),
]
7 changes: 2 additions & 5 deletions post_office/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ class EmailTemplate(models.Model):
name = models.CharField(_('Name'), max_length=255, help_text=_("e.g: 'welcome_email'"))
description = models.TextField(_('Description'), blank=True,
help_text=_("Description of this template."))
identifier = models.CharField(_('Identifier'), max_length=50, unique=True, blank=True, null=True,
help_text=_("Unique template identifier"))
created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
subject = models.CharField(max_length=255, blank=True,
Expand All @@ -265,7 +267,6 @@ class EmailTemplate(models.Model):

class Meta:
app_label = 'post_office'
unique_together = ('name', 'language', 'default_template')
verbose_name = _("Email Template")
verbose_name_plural = _("Email Templates")
ordering = ['name']
Expand All @@ -277,10 +278,6 @@ def natural_key(self):
return (self.name, self.language, self.default_template)

def save(self, *args, **kwargs):
# If template is a translation, use default template's name
if self.default_template and not self.name:
self.name = self.default_template.name

template = super().save(*args, **kwargs)
cache.delete(self.name)
return template
Expand Down
7 changes: 4 additions & 3 deletions post_office/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,10 @@ def test_attachments_email_message_with_mimetype(self):
[('test.txt', 'test file content', 'text/plain')])

def test_translated_template_uses_default_templates_name(self):
template = EmailTemplate.objects.create(name='name')
id_template = template.translated_templates.create(language='id')
self.assertEqual(id_template.name, template.name)
template = EmailTemplate.objects.create(name='name', identifier='identifier')
id_template = template.translated_templates.create(name='Nama', language='id')
self.assertEqual(id_template.name, 'Nama')
self.assertEqual(id_template.identifier, None)

def test_models_repr(self):
self.assertEqual(repr(EmailTemplate(name='test', language='en')),
Expand Down