diff --git a/README.rst b/README.rst
index 71762fb..cc3f36f 100644
--- a/README.rst
+++ b/README.rst
@@ -16,6 +16,10 @@ Assumptions
Changelog
=========
+1.1.14
+------
+* Additional fields for email attachment - https://github.com/deployed/django-emailtemplates/pull/36
+
1.1.13
------
* Change default auto field to BigAutoField - https://github.com/deployed/django-emailtemplates/pull/35
diff --git a/emailtemplates/__init__.py b/emailtemplates/__init__.py
index 0020d13..1948f91 100644
--- a/emailtemplates/__init__.py
+++ b/emailtemplates/__init__.py
@@ -1,6 +1,6 @@
-default_app_config = 'emailtemplates.apps.EmailtempatesConfig'
+default_app_config = "emailtemplates.apps.EmailtempatesConfig"
-VERSION = (1, 1, 13)
+VERSION = (1, 1, 14)
# Dynamically calculate the version based on VERSION tuple
if len(VERSION) > 2 and VERSION[2] is not None:
diff --git a/emailtemplates/admin.py b/emailtemplates/admin.py
index 68a129e..a0b05a8 100644
--- a/emailtemplates/admin.py
+++ b/emailtemplates/admin.py
@@ -5,7 +5,12 @@
from django.utils.translation import gettext_lazy as _
from .forms import EmailTemplateAdminForm, MassEmailMessageForm, MassEmailAttachmentForm
-from .models import EmailTemplate, MassEmailMessage, MassEmailAttachment, EmailAttachment
+from .models import (
+ EmailTemplate,
+ MassEmailMessage,
+ MassEmailAttachment,
+ EmailAttachment,
+)
class EmailTemplateAttachmentInline(admin.TabularInline):
@@ -19,33 +24,42 @@ class EmailTemplateAdmin(admin.ModelAdmin):
"""
Admin view of EmailTemplate
"""
- list_display = ('title', 'language', 'subject',)
- list_display_links = ('title',)
- list_filter = ('title', 'language',)
- search_fields = ('title', 'subject')
+
+ list_display = (
+ "title",
+ "language",
+ "subject",
+ )
+ list_display_links = ("title",)
+ list_filter = (
+ "title",
+ "language",
+ )
+ search_fields = ("title", "subject")
form = EmailTemplateAdminForm
save_on_top = True
save_as = True
- readonly_fields = ['show_links', 'created', 'modified']
+ readonly_fields = ["show_links", "created", "modified"]
inlines = [EmailTemplateAttachmentInline]
def show_links(self, obj):
if not obj.pk:
- return ''
- return mark_safe(u'%s' % (
- reverse('email_preview', kwargs={'pk': obj.pk}), _('Show email preview')
- ))
+ return ""
+ return mark_safe(
+ '%s'
+ % (reverse("email_preview", kwargs={"pk": obj.pk}), _("Show email preview"))
+ )
show_links.allow_tags = True
- show_links.short_description = _('Actions')
+ show_links.short_description = _("Actions")
admin.site.register(EmailTemplate, EmailTemplateAdmin)
class EmailAttachmentAdmin(admin.ModelAdmin):
- list_display = ["name"]
- search_fields = ["name"]
+ list_display = ["name", "comment", "ordering"]
+ search_fields = ["name", "comment"]
admin.site.register(EmailAttachment, EmailAttachmentAdmin)
@@ -57,8 +71,8 @@ class MassEmailAttachmentInline(admin.TabularInline):
class MassEmailMessageAdmin(admin.ModelAdmin):
- list_display = ('subject', 'date_sent')
- readonly_fields = ['date_sent']
+ list_display = ("subject", "date_sent")
+ readonly_fields = ["date_sent"]
form = MassEmailMessageForm
inlines = [MassEmailAttachmentInline]
diff --git a/emailtemplates/apps.py b/emailtemplates/apps.py
index bcee402..29ff5a2 100644
--- a/emailtemplates/apps.py
+++ b/emailtemplates/apps.py
@@ -4,6 +4,6 @@
class EmailtempatesConfig(AppConfig):
- name = 'emailtemplates'
- verbose_name = _('E-MAIL TEMPLATES')
- default_auto_field = 'django.db.models.BigAutoField'
+ name = "emailtemplates"
+ verbose_name = _("E-MAIL TEMPLATES")
+ default_auto_field = "django.db.models.BigAutoField"
diff --git a/emailtemplates/email.py b/emailtemplates/email.py
index 46d2dd3..8d74408 100644
--- a/emailtemplates/email.py
+++ b/emailtemplates/email.py
@@ -1,7 +1,9 @@
# coding=utf-8
import logging
import os
+import re
from smtplib import SMTPException
+from urllib.parse import urljoin
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
@@ -11,8 +13,6 @@
from .models import now, EmailTemplate
from .registry import email_templates
-import re
-from urllib.parse import urljoin
logger = logging.getLogger(__name__)
@@ -28,9 +28,17 @@ class EmailFromTemplate(object):
Site Admins should be familiar with Django Template System.
"""
- def __init__(self, name="", from_email=settings.DEFAULT_FROM_EMAIL, base_url="",
- language=settings.LANGUAGE_CODE, subject="", template_class=EmailTemplate,
- registry_validation=True, template_object=None):
+ def __init__(
+ self,
+ name="",
+ from_email=settings.DEFAULT_FROM_EMAIL,
+ base_url="",
+ language=settings.LANGUAGE_CODE,
+ subject="",
+ template_class=EmailTemplate,
+ registry_validation=True,
+ template_object=None,
+ ):
"""
Class constructor
@@ -55,18 +63,18 @@ def __init__(self, name="", from_email=settings.DEFAULT_FROM_EMAIL, base_url="",
self.template = None
self.compiled_template = None # for storing compiled template
- self.context = {'date': now()} # default context
+ self.context = {"date": now()} # default context
self.sent = 0 # number of messages sent
self.message = ""
- self.content_subtype = 'html'
- self._template_source = 'default'
+ self.content_subtype = "html"
+ self._template_source = "default"
@property
def template_source(self):
"""Source of the template. One of the following:
- * default
- * filesystem
- * database
+ * default
+ * filesystem
+ * database
"""
return self._template_source
@@ -78,9 +86,12 @@ def __get_template_from_file(self):
try:
self.compiled_template = get_template(path)
except (TemplateDoesNotExist, IOError):
- logger.warning("Can't find %s template in the filesystem, will use very default one.", path)
+ logger.warning(
+ "Can't find %s template in the filesystem, will use very default one.",
+ path,
+ )
else:
- self._template_source = 'filesystem'
+ self._template_source = "filesystem"
def build_absolute_uri(self, url: str):
"""
@@ -106,17 +117,20 @@ def get_object(self):
try:
tmp = self.get_template_object()
except ObjectDoesNotExist:
- logger.warning("Can't find EmailTemplate object in database, using default file template.")
+ logger.warning(
+ "Can't find EmailTemplate object in database, using default file template."
+ )
break
except UnicodeError:
logger.warning(
- "Can't convert to unicode EmailTemplate object from database, using default file template.")
+ "Can't convert to unicode EmailTemplate object from database, using default file template."
+ )
break
else:
self.template = str(tmp.content)
self.subject = self.get_subject(tmp)
- self._template_source = 'database'
- logger.debug(u"Got template %s from database", self.name)
+ self._template_source = "database"
+ logger.debug("Got template %s from database", self.name)
return
# fallback
self.__get_template_from_file()
@@ -126,9 +140,9 @@ def __compile_template(self):
self.compiled_template = Template(self.template)
def get_context(self):
- self.context.update({
- "default_attachments": self.get_default_attachments(as_links=True)
- })
+ self.context.update(
+ {"default_attachments": self.get_default_attachments(as_links=True)}
+ )
return self.context
def render_message(self):
@@ -141,18 +155,22 @@ def render_message(self):
self.message = message
def get_message_object(self, send_to, attachment_paths, *args, **kwargs):
- if kwargs.get('reply_to') is None:
- defaut_reply_to_email = getattr(settings, 'DEFAULT_REPLY_TO_EMAIL', None)
+ if kwargs.get("reply_to") is None:
+ defaut_reply_to_email = getattr(settings, "DEFAULT_REPLY_TO_EMAIL", None)
if defaut_reply_to_email:
- kwargs['reply_to'] = [defaut_reply_to_email]
+ kwargs["reply_to"] = [defaut_reply_to_email]
- msg = EmailMessage(self.subject, self.message, self.from_email, send_to, *args, **kwargs)
+ msg = EmailMessage(
+ self.subject, self.message, self.from_email, send_to, *args, **kwargs
+ )
if attachment_paths:
for path in attachment_paths:
msg.attach_file(path)
return msg
- def send_email(self, send_to, attachment_paths=None, fail_silently=True, *args, **kwargs):
+ def send_email(
+ self, send_to, attachment_paths=None, fail_silently=True, *args, **kwargs
+ ):
"""
Sends email to recipient based on self object parameters.
@@ -160,7 +178,7 @@ def send_email(self, send_to, attachment_paths=None, fail_silently=True, *args,
@param send_to: recipient email
@param args: additional args passed to EmailMessage
@param kwargs: kwargs passed to EmailMessage
- @param attachment_paths: paths to attachments as received by django EmailMessage.attach_file(path) method
+ @param attachment_paths: paths to attachments as received by django EmailMessage.attach_file(path) method
@return: number of sent messages
"""
msg = self.get_message_object(send_to, attachment_paths, *args, **kwargs)
@@ -171,7 +189,7 @@ def send_email(self, send_to, attachment_paths=None, fail_silently=True, *args,
except SMTPException as e:
if not fail_silently:
raise
- logger.error(u'Problem sending email to %s: %s', send_to, e)
+ logger.error("Problem sending email to %s: %s", send_to, e)
return self.sent
@@ -188,29 +206,35 @@ def get_default_attachments(self, as_links=False):
for attachment in tmp.attachments.filter(send_as_link=as_links):
if as_links:
attachments.append(
- (attachment.get_name(), self.build_absolute_uri(attachment.attachment_file.url))
+ (
+ attachment.get_name(),
+ self.build_absolute_uri(attachment.attachment_file.url),
+ )
)
else:
attachments.append(
- (os.path.basename(attachment.attachment_file.name), attachment.attachment_file.read())
+ (
+ os.path.basename(attachment.attachment_file.name),
+ attachment.attachment_file.read(),
+ )
)
return attachments
def send(self, to, attachment_paths=None, *args, **kwargs):
"""This function does all the operations on eft object, that are necessary to send email.
- Usually one would use eft object like this:
- eft = EmailFromTemplate(name='sth/sth.html')
- eft.get_object()
- eft.render_message()
- eft.send_email(['email@example.com'])
- return eft.sent
+ Usually one would use eft object like this:
+ eft = EmailFromTemplate(name='sth/sth.html')
+ eft.get_object()
+ eft.render_message()
+ eft.send_email(['email@example.com'])
+ return eft.sent
"""
attachments = self.get_default_attachments(as_links=False)
- attachments.extend(kwargs.pop('attachments', []))
+ attachments.extend(kwargs.pop("attachments", []))
self.get_object()
self.render_message()
self.send_email(to, attachment_paths, attachments=attachments, *args, **kwargs)
if self.sent:
- logger.info(u"Mail has been sent to: %s ", to)
+ logger.info("Mail has been sent to: %s ", to)
return self.sent
diff --git a/emailtemplates/forms.py b/emailtemplates/forms.py
index e7127bb..e1fa494 100644
--- a/emailtemplates/forms.py
+++ b/emailtemplates/forms.py
@@ -16,49 +16,55 @@
class EmailTemplateAdminForm(forms.ModelForm):
- title = forms.ChoiceField(choices=lazy(email_templates.email_template_choices, list), label=_("template"))
+ title = forms.ChoiceField(
+ choices=lazy(email_templates.email_template_choices, list), label=_("template")
+ )
class Meta:
model = EmailTemplate
fields = [
- 'title',
- 'subject',
- 'content',
- 'language',
- 'created',
- 'modified',
+ "title",
+ "subject",
+ "content",
+ "language",
+ "created",
+ "modified",
]
def __init__(self, *args, **kwargs):
super(EmailTemplateAdminForm, self).__init__(*args, **kwargs)
- self.fields['title'].help_text = mark_safe(email_templates.get_form_help_text(self.initial.get('title')))
+ self.fields["title"].help_text = mark_safe(
+ email_templates.get_form_help_text(self.initial.get("title"))
+ )
if self.instance.pk:
- self.fields['title'].widget = forms.TextInput(attrs={'readonly': 'readonly', 'style': 'width:480px'})
+ self.fields["title"].widget = forms.TextInput(
+ attrs={"readonly": "readonly", "style": "width:480px"}
+ )
else:
- self.fields['content'].widget = forms.HiddenInput()
- self.fields['content'].required = False
- self.fields['subject'].widget = forms.HiddenInput()
+ self.fields["content"].widget = forms.HiddenInput()
+ self.fields["content"].required = False
+ self.fields["subject"].widget = forms.HiddenInput()
def clean_content(self):
- content = self.cleaned_data['content']
+ content = self.cleaned_data["content"]
try:
Template(content)
except TemplateSyntaxError as e:
- raise ValidationError(u"Syntax error in custom email template: %s" % e)
+ raise ValidationError("Syntax error in custom email template: %s" % e)
return content
class MassEmailAttachmentForm(forms.ModelForm):
class Meta:
model = MassEmailAttachment
- fields = ['attachment_file']
+ fields = ["attachment_file"]
class MassEmailMessageForm(forms.ModelForm):
class Meta:
model = MassEmailMessage
fields = [
- 'subject',
- 'content',
- 'date_sent',
+ "subject",
+ "content",
+ "date_sent",
]
diff --git a/emailtemplates/helpers.py b/emailtemplates/helpers.py
index 8a30796..40f0704 100644
--- a/emailtemplates/helpers.py
+++ b/emailtemplates/helpers.py
@@ -36,7 +36,7 @@ def __unicode__(self):
return 'a string containing "%s"' % self.containing
def __str__(self):
- return unicode(self).encode('utf-8')
+ return unicode(self).encode("utf-8")
__repr__ = __unicode__
@@ -60,15 +60,19 @@ def mass_mailing_recipients():
:rtype iterable
"""
- if hasattr(settings, 'MASS_EMAIL_RECIPIENTS'):
- callback_name = settings.MASS_EMAIL_RECIPIENTS.split('.')
- module_name = '.'.join(callback_name[:-1])
+ if hasattr(settings, "MASS_EMAIL_RECIPIENTS"):
+ callback_name = settings.MASS_EMAIL_RECIPIENTS.split(".")
+ module_name = ".".join(callback_name[:-1])
func_name = callback_name[-1]
module = import_module(module_name)
func = getattr(module, func_name, lambda: [])
return func()
User = get_user_model()
- if hasattr(User, 'is_active') and hasattr(User, 'email'):
- filtered_users = User.objects.filter(is_active=True).exclude(email__isnull=True).exclude(email__exact='')
- return filtered_users.values_list('email', flat=True).distinct()
+ if hasattr(User, "is_active") and hasattr(User, "email"):
+ filtered_users = (
+ User.objects.filter(is_active=True)
+ .exclude(email__isnull=True)
+ .exclude(email__exact="")
+ )
+ return filtered_users.values_list("email", flat=True).distinct()
return []
diff --git a/emailtemplates/locale/de/LC_MESSAGES/django.mo b/emailtemplates/locale/de/LC_MESSAGES/django.mo
index 28e33d9..b0eba4d 100644
Binary files a/emailtemplates/locale/de/LC_MESSAGES/django.mo and b/emailtemplates/locale/de/LC_MESSAGES/django.mo differ
diff --git a/emailtemplates/locale/de/LC_MESSAGES/django.po b/emailtemplates/locale/de/LC_MESSAGES/django.po
index 223444c..ed7e94c 100644
--- a/emailtemplates/locale/de/LC_MESSAGES/django.po
+++ b/emailtemplates/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-11-13 12:08+0100\n"
+"POT-Creation-Date: 2022-08-09 13:50+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -20,96 +20,114 @@ msgstr ""
"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n"
"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
-#: emailtemplates/admin.py:34
+#: emailtemplates/admin.py:19 emailtemplates/models.py:83
+msgid "Attachment"
+msgstr "Anlage"
+
+#: emailtemplates/admin.py:20 emailtemplates/models.py:84
+msgid "Attachments"
+msgstr "Anhänge"
+
+#: emailtemplates/admin.py:50
msgid "Show email preview"
msgstr "E-Mail-Vorschau anzeigen"
-#: emailtemplates/admin.py:38
+#: emailtemplates/admin.py:54
msgid "Actions"
msgstr "Aktionen"
-msgid "Send as link"
-msgstr "Als Link versenden"
-
#: emailtemplates/apps.py:8
msgid "E-MAIL TEMPLATES"
msgstr "E-Mail Templates"
-#: emailtemplates/forms.py:19 emailtemplates/models.py:25
+#: emailtemplates/forms.py:20 emailtemplates/models.py:29
msgid "template"
msgstr "Vorlage"
-#: emailtemplates/models.py:26 emailtemplates/models.py:76
+#: emailtemplates/models.py:27 emailtemplates/models.py:68
+#: emailtemplates/models.py:101
+msgid "ID"
+msgstr ""
+
+#: emailtemplates/models.py:30 emailtemplates/models.py:103
msgid "subject"
msgstr "Thema"
-#: emailtemplates/models.py:27 emailtemplates/models.py:77
+#: emailtemplates/models.py:31 emailtemplates/models.py:104
msgid "content"
msgstr "Inhalt"
-#: emailtemplates/models.py:28
+#: emailtemplates/models.py:33
msgid "language"
msgstr "Sprache"
-#: emailtemplates/models.py:30
+#: emailtemplates/models.py:39
+msgid "attachments"
+msgstr "anhänge"
+
+#: emailtemplates/models.py:41
msgid "created"
msgstr "erstellt"
-#: emailtemplates/models.py:31
+#: emailtemplates/models.py:42
msgid "modified"
msgstr "geändert"
-#: emailtemplates/models.py:35
+#: emailtemplates/models.py:46
msgid "Email template"
msgstr "E-Mail Template"
-#: emailtemplates/models.py:36
+#: emailtemplates/models.py:47
msgid "Email templates"
msgstr "E-Mail Templates"
-#: emailtemplates/models.py:56
+#: emailtemplates/models.py:70
msgid "name"
msgstr "Name"
-#: emailtemplates/models.py:57
+#: emailtemplates/models.py:72
msgid "Attachment file"
msgstr "Datei anhängen"
-#: emailtemplates/models.py:61
-msgid "Attachment"
-msgstr "Anlage"
+#: emailtemplates/models.py:75
+msgid "Comment"
+msgstr "Kommentar"
-#: emailtemplates/models.py:62
-msgid "Attachments"
-msgstr "Anhänge"
+#: emailtemplates/models.py:75
+msgid "visible only in admin"
+msgstr "nur im Administrationsbereich sichtbar"
+
+#: emailtemplates/models.py:77
+msgid "Ordering"
+msgstr "Bestellung"
+
+#: emailtemplates/models.py:78
+msgid "Send as link"
+msgstr "Als Link versenden"
-#: emailtemplates/models.py:65
+#: emailtemplates/models.py:87
#, python-format
msgid "Attachment: %s"
msgstr "Anlage: %s"
-#: emailtemplates/models.py:72
-msgid "email template"
-msgstr "E-Mail-Vorlage"
-
-#: emailtemplates/models.py:78
+#: emailtemplates/models.py:105
msgid "sent"
msgstr "gesendet"
-#: emailtemplates/models.py:81
+#: emailtemplates/models.py:108
msgid "Mass email message"
msgstr "Massen E-Mail"
-#: emailtemplates/models.py:82
+#: emailtemplates/models.py:109
msgid "Mass email messages"
msgstr "Massen E-Mails"
-#: emailtemplates/registry.py:68
+#: emailtemplates/registry.py:80
#, python-format
msgid "USAGE: %s"
msgstr "ANWENDUNG: %s"
-#: emailtemplates/registry.py:69
+#: emailtemplates/registry.py:83
#, python-format
msgid "CONTEXT:
%s"
msgstr "KONTEXT:
%s"
@@ -118,18 +136,31 @@ msgstr "KONTEXT:
%s"
msgid "Send to all users"
msgstr "An alle Benutzer senden"
-#: emailtemplates/views.py:51
+#: emailtemplates/tests/test_template_registry.py:60
+msgid "USAGE"
+msgstr "ANWENDUNG"
+
+#: emailtemplates/tests/test_template_registry.py:61
+msgid "CONTEXT"
+msgstr "KONTEXT"
+
+#: emailtemplates/views.py:55
msgid ""
"Mass email was already sent. Create new mail message or force sending from "
"shell."
msgstr ""
-"Die Massen-E-Mail wurde bereits gesendet. Neue E-Mail-Nachricht erstellen oder "
-"Senden aus der Shell erzwingen"
+"Die Massen-E-Mail wurde bereits gesendet. Neue E-Mail-Nachricht erstellen "
+"oder Senden aus der Shell erzwingen"
-#: emailtemplates/views.py:56
+#: emailtemplates/views.py:62
msgid "Mass email sent successfully"
msgstr "Massen-E-Mail erfolgreich gesendet"
-#: emailtemplates/views.py:58
+#: emailtemplates/views.py:65
msgid "Error occurred when trying to send mass email message."
-msgstr "Beim Versuch, eine Massen-E-Mail-Nachricht zu senden, ist ein Fehler aufgetreten"
+msgstr ""
+"Beim Versuch, eine Massen-E-Mail-Nachricht zu senden, ist ein Fehler "
+"aufgetreten"
+
+#~ msgid "email template"
+#~ msgstr "E-Mail-Vorlage"
diff --git a/emailtemplates/locale/pl/LC_MESSAGES/django.mo b/emailtemplates/locale/pl/LC_MESSAGES/django.mo
index 95ddb56..faff1a1 100644
Binary files a/emailtemplates/locale/pl/LC_MESSAGES/django.mo and b/emailtemplates/locale/pl/LC_MESSAGES/django.mo differ
diff --git a/emailtemplates/locale/pl/LC_MESSAGES/django.po b/emailtemplates/locale/pl/LC_MESSAGES/django.po
index 2f05833..bfd7766 100644
--- a/emailtemplates/locale/pl/LC_MESSAGES/django.po
+++ b/emailtemplates/locale/pl/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-11-13 12:08+0100\n"
+"POT-Creation-Date: 2022-08-09 13:50+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -20,96 +20,114 @@ msgstr ""
"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n"
"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
-#: emailtemplates/admin.py:34
+#: emailtemplates/admin.py:19 emailtemplates/models.py:83
+msgid "Attachment"
+msgstr "Załącznik"
+
+#: emailtemplates/admin.py:20 emailtemplates/models.py:84
+msgid "Attachments"
+msgstr "Załączniki"
+
+#: emailtemplates/admin.py:50
msgid "Show email preview"
msgstr "Pokaż podgląd wiadomości"
-#: emailtemplates/admin.py:38
+#: emailtemplates/admin.py:54
msgid "Actions"
msgstr "Akcje"
-msgid "Send as link"
-msgstr "Wyślij jako link"
-
#: emailtemplates/apps.py:8
msgid "E-MAIL TEMPLATES"
msgstr "Szblony wiadomości E-mail"
-#: emailtemplates/forms.py:19 emailtemplates/models.py:25
+#: emailtemplates/forms.py:20 emailtemplates/models.py:29
msgid "template"
msgstr "szablon"
-#: emailtemplates/models.py:26 emailtemplates/models.py:76
+#: emailtemplates/models.py:27 emailtemplates/models.py:68
+#: emailtemplates/models.py:101
+msgid "ID"
+msgstr ""
+
+#: emailtemplates/models.py:30 emailtemplates/models.py:103
msgid "subject"
msgstr "tytuł"
-#: emailtemplates/models.py:27 emailtemplates/models.py:77
+#: emailtemplates/models.py:31 emailtemplates/models.py:104
msgid "content"
msgstr "zawartość"
-#: emailtemplates/models.py:28
+#: emailtemplates/models.py:33
msgid "language"
msgstr "język"
-#: emailtemplates/models.py:30
+#: emailtemplates/models.py:39
+msgid "attachments"
+msgstr "załączniki"
+
+#: emailtemplates/models.py:41
msgid "created"
msgstr "utworzono"
-#: emailtemplates/models.py:31
+#: emailtemplates/models.py:42
msgid "modified"
msgstr "zmodyfikowano"
-#: emailtemplates/models.py:35
+#: emailtemplates/models.py:46
msgid "Email template"
msgstr "Szablon wiadomości"
-#: emailtemplates/models.py:36
+#: emailtemplates/models.py:47
msgid "Email templates"
msgstr "Szablony wiadomości"
-#: emailtemplates/models.py:56
+#: emailtemplates/models.py:70
msgid "name"
msgstr "nazwa"
-#: emailtemplates/models.py:57
+#: emailtemplates/models.py:72
msgid "Attachment file"
msgstr "Plik załącznika"
-#: emailtemplates/models.py:61
-msgid "Attachment"
-msgstr "Załącznik"
+#: emailtemplates/models.py:75
+msgid "Comment"
+msgstr "Komentarz"
-#: emailtemplates/models.py:62
-msgid "Attachments"
-msgstr "Załączniki"
+#: emailtemplates/models.py:75
+msgid "visible only in admin"
+msgstr "widoczne tylko w panelu administracyjnym"
+
+#: emailtemplates/models.py:77
+msgid "Ordering"
+msgstr "Kolejność"
+
+#: emailtemplates/models.py:78
+msgid "Send as link"
+msgstr "Wyślij jako link"
-#: emailtemplates/models.py:65
+#: emailtemplates/models.py:87
#, python-format
msgid "Attachment: %s"
msgstr "Załącznik: %s"
-#: emailtemplates/models.py:72
-msgid "email template"
-msgstr "szablon email"
-
-#: emailtemplates/models.py:78
+#: emailtemplates/models.py:105
msgid "sent"
msgstr "wysłano"
-#: emailtemplates/models.py:81
+#: emailtemplates/models.py:108
msgid "Mass email message"
msgstr "Wiadomość grupowa"
-#: emailtemplates/models.py:82
+#: emailtemplates/models.py:109
msgid "Mass email messages"
msgstr "Wiadomości grupowe"
-#: emailtemplates/registry.py:68
+#: emailtemplates/registry.py:80
#, python-format
msgid "USAGE: %s"
msgstr "UŻYCIE: %s"
-#: emailtemplates/registry.py:69
+#: emailtemplates/registry.py:83
#, python-format
msgid "CONTEXT:
%s"
msgstr "KONTEKST:
%s"
@@ -118,7 +136,15 @@ msgstr "KONTEKST:
%s"
msgid "Send to all users"
msgstr "Wyślij do wszystkich użytkowników"
-#: emailtemplates/views.py:51
+#: emailtemplates/tests/test_template_registry.py:60
+msgid "USAGE"
+msgstr "UŻYCIE"
+
+#: emailtemplates/tests/test_template_registry.py:61
+msgid "CONTEXT"
+msgstr "KONTEKST"
+
+#: emailtemplates/views.py:55
msgid ""
"Mass email was already sent. Create new mail message or force sending from "
"shell."
@@ -126,10 +152,13 @@ msgstr ""
"Wiadomość grupowa została już wysłana. Utwórz nową lub wymuś wysłanie z "
"konsoli shell."
-#: emailtemplates/views.py:56
+#: emailtemplates/views.py:62
msgid "Mass email sent successfully"
msgstr "Wiadomość grupowa wysłana pomyślnie"
-#: emailtemplates/views.py:58
+#: emailtemplates/views.py:65
msgid "Error occurred when trying to send mass email message."
msgstr "Wystąpił błąd podczas próby wysłania wiadomości grupowej."
+
+#~ msgid "email template"
+#~ msgstr "szablon email"
diff --git a/emailtemplates/migrations/0001_initial.py b/emailtemplates/migrations/0001_initial.py
index 867c720..45b95b1 100644
--- a/emailtemplates/migrations/0001_initial.py
+++ b/emailtemplates/migrations/0001_initial.py
@@ -10,24 +10,164 @@ class Migration(migrations.Migration):
initial = True
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
- name='EmailTemplate',
+ name="EmailTemplate",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('title', models.CharField(choices=[(b'accounts/activation.html', b'accounts/activation.html'), (b'project/introduction_project_mail_1d.html', b'project/introduction_project_mail_1d.html'), (b'project/notice_original_deletion_3days.html', b'project/notice_original_deletion_3days.html'), (b'accounts/password_reset_email.html', b'accounts/password_reset_email.html'), (b'accounts/email_verification.html', b'accounts/email_verification.html'), (b'share/invitation.html', b'share/invitation.html'), (b'orders/cancelled_payment.html', b'orders/cancelled_payment.html'), (b'project/new_template_available.html', b'project/new_template_available.html'), (b'supports/feedback_email.html', b'supports/feedback_email.html'), (b'invitations/invite_friend.html', b'invitations/invite_friend.html'), (b'project/introduction_project_mail_2d.html', b'project/introduction_project_mail_2d.html'), (b'share/invitation_subject.html', b'share/invitation_subject.html'), (b'orders/delivered.html', b'orders/delivered.html'), (b'project/project_action_notification.html', b'project/project_action_notification.html'), (b'project/notice_original_deletion_1week.html', b'project/notice_original_deletion_1week.html'), (b'accounts/welcome.html', b'accounts/welcome.html'), (b'project/download_zip.html', b'project/download_zip.html'), (b'orders/in_production.html', b'orders/in_production.html'), (b'project/notice_original_deletion_1month.html', b'project/notice_original_deletion_1month.html'), (b'accounts/introducing_email_4d.html', b'accounts/introducing_email_4d.html'), (b'orders/reorder_incentive_mail.html', b'orders/reorder_incentive_mail.html'), (b'project/project_action_like_comment_notification.html', b'project/project_action_like_comment_notification.html'), (b'accounts/introducing_email_2d.html', b'accounts/introducing_email_2d.html'), (b'project/package_expired.html', b'project/package_expired.html'), (b'project/package_upgrade.html', b'project/package_upgrade.html'), (b'project/introduction_project_mail_7d.html', b'project/introduction_project_mail_7d.html'), (b'subscriptions/subscription_email.html', b'subscriptions/subscription_email.html'), (b'accounts/introducing_email_3d.html', b'accounts/introducing_email_3d.html'), (b'accounts/introducing_email_1d.html', b'accounts/introducing_email_1d.html'), (b'supports/support_request.html', b'supports/support_request.html'), (b'supports/support_confirm.html', b'supports/support_confirm.html')], max_length=255, verbose_name='template')),
- ('subject', models.CharField(blank=True, max_length=255, verbose_name='subject')),
- ('content', models.TextField(verbose_name='content')),
- ('language', models.CharField(choices=[(b'de', b'German')], default=b'de', max_length=10, verbose_name='language')),
- ('created', models.DateTimeField(default=django.utils.timezone.now)),
- ('modified', models.DateTimeField(default=django.utils.timezone.now)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "title",
+ models.CharField(
+ choices=[
+ (b"accounts/activation.html", b"accounts/activation.html"),
+ (
+ b"project/introduction_project_mail_1d.html",
+ b"project/introduction_project_mail_1d.html",
+ ),
+ (
+ b"project/notice_original_deletion_3days.html",
+ b"project/notice_original_deletion_3days.html",
+ ),
+ (
+ b"accounts/password_reset_email.html",
+ b"accounts/password_reset_email.html",
+ ),
+ (
+ b"accounts/email_verification.html",
+ b"accounts/email_verification.html",
+ ),
+ (b"share/invitation.html", b"share/invitation.html"),
+ (
+ b"orders/cancelled_payment.html",
+ b"orders/cancelled_payment.html",
+ ),
+ (
+ b"project/new_template_available.html",
+ b"project/new_template_available.html",
+ ),
+ (
+ b"supports/feedback_email.html",
+ b"supports/feedback_email.html",
+ ),
+ (
+ b"invitations/invite_friend.html",
+ b"invitations/invite_friend.html",
+ ),
+ (
+ b"project/introduction_project_mail_2d.html",
+ b"project/introduction_project_mail_2d.html",
+ ),
+ (
+ b"share/invitation_subject.html",
+ b"share/invitation_subject.html",
+ ),
+ (b"orders/delivered.html", b"orders/delivered.html"),
+ (
+ b"project/project_action_notification.html",
+ b"project/project_action_notification.html",
+ ),
+ (
+ b"project/notice_original_deletion_1week.html",
+ b"project/notice_original_deletion_1week.html",
+ ),
+ (b"accounts/welcome.html", b"accounts/welcome.html"),
+ (
+ b"project/download_zip.html",
+ b"project/download_zip.html",
+ ),
+ (
+ b"orders/in_production.html",
+ b"orders/in_production.html",
+ ),
+ (
+ b"project/notice_original_deletion_1month.html",
+ b"project/notice_original_deletion_1month.html",
+ ),
+ (
+ b"accounts/introducing_email_4d.html",
+ b"accounts/introducing_email_4d.html",
+ ),
+ (
+ b"orders/reorder_incentive_mail.html",
+ b"orders/reorder_incentive_mail.html",
+ ),
+ (
+ b"project/project_action_like_comment_notification.html",
+ b"project/project_action_like_comment_notification.html",
+ ),
+ (
+ b"accounts/introducing_email_2d.html",
+ b"accounts/introducing_email_2d.html",
+ ),
+ (
+ b"project/package_expired.html",
+ b"project/package_expired.html",
+ ),
+ (
+ b"project/package_upgrade.html",
+ b"project/package_upgrade.html",
+ ),
+ (
+ b"project/introduction_project_mail_7d.html",
+ b"project/introduction_project_mail_7d.html",
+ ),
+ (
+ b"subscriptions/subscription_email.html",
+ b"subscriptions/subscription_email.html",
+ ),
+ (
+ b"accounts/introducing_email_3d.html",
+ b"accounts/introducing_email_3d.html",
+ ),
+ (
+ b"accounts/introducing_email_1d.html",
+ b"accounts/introducing_email_1d.html",
+ ),
+ (
+ b"supports/support_request.html",
+ b"supports/support_request.html",
+ ),
+ (
+ b"supports/support_confirm.html",
+ b"supports/support_confirm.html",
+ ),
+ ],
+ max_length=255,
+ verbose_name="template",
+ ),
+ ),
+ (
+ "subject",
+ models.CharField(
+ blank=True, max_length=255, verbose_name="subject"
+ ),
+ ),
+ ("content", models.TextField(verbose_name="content")),
+ (
+ "language",
+ models.CharField(
+ choices=[(b"de", b"German")],
+ default=b"de",
+ max_length=10,
+ verbose_name="language",
+ ),
+ ),
+ ("created", models.DateTimeField(default=django.utils.timezone.now)),
+ ("modified", models.DateTimeField(default=django.utils.timezone.now)),
],
),
migrations.AlterUniqueTogether(
- name='emailtemplate',
- unique_together=set([('title', 'language')]),
+ name="emailtemplate",
+ unique_together=set([("title", "language")]),
),
]
diff --git a/emailtemplates/migrations/0002_auto_20170428_1442.py b/emailtemplates/migrations/0002_auto_20170428_1442.py
index 7d62a38..7af84e3 100644
--- a/emailtemplates/migrations/0002_auto_20170428_1442.py
+++ b/emailtemplates/migrations/0002_auto_20170428_1442.py
@@ -8,13 +8,115 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0001_initial'),
+ ("emailtemplates", "0001_initial"),
]
operations = [
migrations.AlterField(
- model_name='emailtemplate',
- name='title',
- field=models.CharField(choices=[(b'accounts/activation.html', b'accounts/activation.html'), (b'project/introduction_project_mail_1d.html', b'project/introduction_project_mail_1d.html'), (b'project/notice_original_deletion_3days.html', b'project/notice_original_deletion_3days.html'), (b'supports/feedback_email.html', b'supports/feedback_email.html'), (b'accounts/email_verification.html', b'accounts/email_verification.html'), (b'share/invitation.html', b'share/invitation.html'), (b'orders/cancelled_payment.html', b'orders/cancelled_payment.html'), (b'project/new_template_available.html', b'project/new_template_available.html'), (b'invitations/invite_friend.html', b'invitations/invite_friend.html'), (b'project/introduction_project_mail_2d.html', b'project/introduction_project_mail_2d.html'), (b'share/invitation_subject.html', b'share/invitation_subject.html'), (b'orders/delivered.html', b'orders/delivered.html'), (b'subscriptions/subscription_email.html', b'subscriptions/subscription_email.html'), (b'project/notice_original_deletion_1week.html', b'project/notice_original_deletion_1week.html'), (b'accounts/welcome.html', b'accounts/welcome.html'), (b'project/download_zip.html', b'project/download_zip.html'), (b'orders/in_production.html', b'orders/in_production.html'), (b'project/notice_original_deletion_1month.html', b'project/notice_original_deletion_1month.html'), (b'accounts/introducing_email_4d.html', b'accounts/introducing_email_4d.html'), (b'orders/reorder_incentive_mail.html', b'orders/reorder_incentive_mail.html'), (b'project/project_action_like_comment_notification.html', b'project/project_action_like_comment_notification.html'), (b'accounts/introducing_email_2d.html', b'accounts/introducing_email_2d.html'), (b'accounts/password_reset_email.html', b'accounts/password_reset_email.html'), (b'project/package_expired.html', b'project/package_expired.html'), (b'project/package_upgrade.html', b'project/package_upgrade.html'), (b'project/introduction_project_mail_7d.html', b'project/introduction_project_mail_7d.html'), (b'project/project_action_notification.html', b'project/project_action_notification.html'), (b'accounts/introducing_email_3d.html', b'accounts/introducing_email_3d.html'), (b'accounts/introducing_email_1d.html', b'accounts/introducing_email_1d.html'), (b'supports/support_request.html', b'supports/support_request.html'), (b'supports/support_confirm.html', b'supports/support_confirm.html')], max_length=255, verbose_name='template'),
+ model_name="emailtemplate",
+ name="title",
+ field=models.CharField(
+ choices=[
+ (b"accounts/activation.html", b"accounts/activation.html"),
+ (
+ b"project/introduction_project_mail_1d.html",
+ b"project/introduction_project_mail_1d.html",
+ ),
+ (
+ b"project/notice_original_deletion_3days.html",
+ b"project/notice_original_deletion_3days.html",
+ ),
+ (b"supports/feedback_email.html", b"supports/feedback_email.html"),
+ (
+ b"accounts/email_verification.html",
+ b"accounts/email_verification.html",
+ ),
+ (b"share/invitation.html", b"share/invitation.html"),
+ (
+ b"orders/cancelled_payment.html",
+ b"orders/cancelled_payment.html",
+ ),
+ (
+ b"project/new_template_available.html",
+ b"project/new_template_available.html",
+ ),
+ (
+ b"invitations/invite_friend.html",
+ b"invitations/invite_friend.html",
+ ),
+ (
+ b"project/introduction_project_mail_2d.html",
+ b"project/introduction_project_mail_2d.html",
+ ),
+ (
+ b"share/invitation_subject.html",
+ b"share/invitation_subject.html",
+ ),
+ (b"orders/delivered.html", b"orders/delivered.html"),
+ (
+ b"subscriptions/subscription_email.html",
+ b"subscriptions/subscription_email.html",
+ ),
+ (
+ b"project/notice_original_deletion_1week.html",
+ b"project/notice_original_deletion_1week.html",
+ ),
+ (b"accounts/welcome.html", b"accounts/welcome.html"),
+ (b"project/download_zip.html", b"project/download_zip.html"),
+ (b"orders/in_production.html", b"orders/in_production.html"),
+ (
+ b"project/notice_original_deletion_1month.html",
+ b"project/notice_original_deletion_1month.html",
+ ),
+ (
+ b"accounts/introducing_email_4d.html",
+ b"accounts/introducing_email_4d.html",
+ ),
+ (
+ b"orders/reorder_incentive_mail.html",
+ b"orders/reorder_incentive_mail.html",
+ ),
+ (
+ b"project/project_action_like_comment_notification.html",
+ b"project/project_action_like_comment_notification.html",
+ ),
+ (
+ b"accounts/introducing_email_2d.html",
+ b"accounts/introducing_email_2d.html",
+ ),
+ (
+ b"accounts/password_reset_email.html",
+ b"accounts/password_reset_email.html",
+ ),
+ (b"project/package_expired.html", b"project/package_expired.html"),
+ (b"project/package_upgrade.html", b"project/package_upgrade.html"),
+ (
+ b"project/introduction_project_mail_7d.html",
+ b"project/introduction_project_mail_7d.html",
+ ),
+ (
+ b"project/project_action_notification.html",
+ b"project/project_action_notification.html",
+ ),
+ (
+ b"accounts/introducing_email_3d.html",
+ b"accounts/introducing_email_3d.html",
+ ),
+ (
+ b"accounts/introducing_email_1d.html",
+ b"accounts/introducing_email_1d.html",
+ ),
+ (
+ b"supports/support_request.html",
+ b"supports/support_request.html",
+ ),
+ (
+ b"supports/support_confirm.html",
+ b"supports/support_confirm.html",
+ ),
+ ],
+ max_length=255,
+ verbose_name="template",
+ ),
),
]
diff --git a/emailtemplates/migrations/0003_auto_20180523_1027.py b/emailtemplates/migrations/0003_auto_20180523_1027.py
index e4ec1d9..4d40744 100644
--- a/emailtemplates/migrations/0003_auto_20180523_1027.py
+++ b/emailtemplates/migrations/0003_auto_20180523_1027.py
@@ -8,17 +8,28 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0002_auto_20170428_1442'),
+ ("emailtemplates", "0002_auto_20170428_1442"),
]
operations = [
migrations.CreateModel(
- name='MassEmailMessage',
+ name="MassEmailMessage",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('subject', models.CharField(max_length=255, verbose_name='subject')),
- ('content', models.TextField(verbose_name='content')),
- ('date_sent', models.DateTimeField(blank=True, null=True, verbose_name='sent')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("subject", models.CharField(max_length=255, verbose_name="subject")),
+ ("content", models.TextField(verbose_name="content")),
+ (
+ "date_sent",
+ models.DateTimeField(blank=True, null=True, verbose_name="sent"),
+ ),
],
),
]
diff --git a/emailtemplates/migrations/0004_auto_20180523_1608.py b/emailtemplates/migrations/0004_auto_20180523_1608.py
index 0941d67..7784b80 100644
--- a/emailtemplates/migrations/0004_auto_20180523_1608.py
+++ b/emailtemplates/migrations/0004_auto_20180523_1608.py
@@ -9,28 +9,48 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0003_auto_20180523_1027'),
+ ("emailtemplates", "0003_auto_20180523_1027"),
]
operations = [
migrations.CreateModel(
- name='MassEmailAttachment',
+ name="MassEmailAttachment",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('attachment_file', models.FileField(upload_to=b'', verbose_name='Attachment file')),
- ('mass_email_message',
- models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='emailtemplates.MassEmailMessage')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "attachment_file",
+ models.FileField(upload_to=b"", verbose_name="Attachment file"),
+ ),
+ (
+ "mass_email_message",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to="emailtemplates.MassEmailMessage",
+ ),
+ ),
],
),
migrations.AlterField(
- model_name='emailtemplate',
- name='language',
- field=models.CharField(choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE, max_length=10,
- verbose_name='language'),
+ model_name="emailtemplate",
+ name="language",
+ field=models.CharField(
+ choices=settings.LANGUAGES,
+ default=settings.LANGUAGE_CODE,
+ max_length=10,
+ verbose_name="language",
+ ),
),
migrations.AlterField(
- model_name='emailtemplate',
- name='title',
- field=models.CharField(max_length=255, verbose_name='template'),
+ model_name="emailtemplate",
+ name="title",
+ field=models.CharField(max_length=255, verbose_name="template"),
),
]
diff --git a/emailtemplates/migrations/0005_auto_20201110_1115.py b/emailtemplates/migrations/0005_auto_20201110_1115.py
index bc41e16..c7e48b6 100644
--- a/emailtemplates/migrations/0005_auto_20201110_1115.py
+++ b/emailtemplates/migrations/0005_auto_20201110_1115.py
@@ -6,27 +6,36 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0004_auto_20180523_1608'),
+ ("emailtemplates", "0004_auto_20180523_1608"),
]
operations = [
migrations.AlterModelOptions(
- name='emailtemplate',
- options={'verbose_name': 'Email template', 'verbose_name_plural': 'Email templates'},
+ name="emailtemplate",
+ options={
+ "verbose_name": "Email template",
+ "verbose_name_plural": "Email templates",
+ },
),
migrations.AlterModelOptions(
- name='massemailmessage',
- options={'verbose_name': 'Mass email message', 'verbose_name_plural': 'Mass email messages'},
+ name="massemailmessage",
+ options={
+ "verbose_name": "Mass email message",
+ "verbose_name_plural": "Mass email messages",
+ },
),
migrations.AlterField(
- model_name='massemailattachment',
- name='attachment_file',
- field=models.FileField(upload_to='', verbose_name='Attachment file'),
+ model_name="massemailattachment",
+ name="attachment_file",
+ field=models.FileField(upload_to="", verbose_name="Attachment file"),
),
migrations.AlterField(
- model_name='massemailattachment',
- name='mass_email_message',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments',
- to='emailtemplates.massemailmessage'),
+ model_name="massemailattachment",
+ name="mass_email_message",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="attachments",
+ to="emailtemplates.massemailmessage",
+ ),
),
]
diff --git a/emailtemplates/migrations/0006_auto_20201110_1151.py b/emailtemplates/migrations/0006_auto_20201110_1151.py
index 3f43306..b82a6a8 100644
--- a/emailtemplates/migrations/0006_auto_20201110_1151.py
+++ b/emailtemplates/migrations/0006_auto_20201110_1151.py
@@ -7,18 +7,22 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0005_auto_20201110_1115'),
+ ("emailtemplates", "0005_auto_20201110_1115"),
]
operations = [
migrations.AlterField(
- model_name='emailtemplate',
- name='created',
- field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='created'),
+ model_name="emailtemplate",
+ name="created",
+ field=models.DateTimeField(
+ default=django.utils.timezone.now, verbose_name="created"
+ ),
),
migrations.AlterField(
- model_name='emailtemplate',
- name='modified',
- field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='modified'),
+ model_name="emailtemplate",
+ name="modified",
+ field=models.DateTimeField(
+ default=django.utils.timezone.now, verbose_name="modified"
+ ),
),
]
diff --git a/emailtemplates/migrations/0007_auto_20201113_1354.py b/emailtemplates/migrations/0007_auto_20201113_1354.py
index a92948f..6e9ac3a 100644
--- a/emailtemplates/migrations/0007_auto_20201113_1354.py
+++ b/emailtemplates/migrations/0007_auto_20201113_1354.py
@@ -6,40 +6,65 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0006_auto_20201110_1151'),
+ ("emailtemplates", "0006_auto_20201110_1151"),
]
operations = [
migrations.CreateModel(
- name='EmailAttachment',
+ name="EmailAttachment",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('name', models.CharField(blank=True, max_length=50, verbose_name='name')),
- ('attachment_file', models.FileField(upload_to='emails/attachments/', verbose_name='Attachment file')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "name",
+ models.CharField(blank=True, max_length=50, verbose_name="name"),
+ ),
+ (
+ "attachment_file",
+ models.FileField(
+ upload_to="emails/attachments/", verbose_name="Attachment file"
+ ),
+ ),
],
options={
- 'verbose_name': 'Attachment',
- 'verbose_name_plural': 'Attachments',
- 'abstract': False,
+ "verbose_name": "Attachment",
+ "verbose_name_plural": "Attachments",
+ "abstract": False,
},
),
migrations.AlterModelOptions(
- name='massemailattachment',
- options={'verbose_name': 'Attachment', 'verbose_name_plural': 'Attachments'},
+ name="massemailattachment",
+ options={
+ "verbose_name": "Attachment",
+ "verbose_name_plural": "Attachments",
+ },
),
migrations.AddField(
- model_name='massemailattachment',
- name='name',
- field=models.CharField(blank=True, max_length=50, verbose_name='name'),
+ model_name="massemailattachment",
+ name="name",
+ field=models.CharField(blank=True, max_length=50, verbose_name="name"),
),
migrations.AlterField(
- model_name='massemailattachment',
- name='attachment_file',
- field=models.FileField(upload_to='emails/attachments/', verbose_name='Attachment file'),
+ model_name="massemailattachment",
+ name="attachment_file",
+ field=models.FileField(
+ upload_to="emails/attachments/", verbose_name="Attachment file"
+ ),
),
migrations.AddField(
- model_name='emailtemplate',
- name='attachments',
- field=models.ManyToManyField(blank=True, to='emailtemplates.EmailAttachment', verbose_name='attachments'),
+ model_name="emailtemplate",
+ name="attachments",
+ field=models.ManyToManyField(
+ blank=True,
+ to="emailtemplates.EmailAttachment",
+ verbose_name="attachments",
+ ),
),
]
diff --git a/emailtemplates/migrations/0008_auto_20201120_1056.py b/emailtemplates/migrations/0008_auto_20201120_1056.py
index bc6932c..5f4e712 100644
--- a/emailtemplates/migrations/0008_auto_20201120_1056.py
+++ b/emailtemplates/migrations/0008_auto_20201120_1056.py
@@ -6,18 +6,18 @@
class Migration(migrations.Migration):
dependencies = [
- ('emailtemplates', '0007_auto_20201113_1354'),
+ ("emailtemplates", "0007_auto_20201113_1354"),
]
operations = [
migrations.AddField(
- model_name='emailattachment',
- name='send_as_link',
- field=models.BooleanField(default=True, verbose_name='Send as link'),
+ model_name="emailattachment",
+ name="send_as_link",
+ field=models.BooleanField(default=True, verbose_name="Send as link"),
),
migrations.AddField(
- model_name='massemailattachment',
- name='send_as_link',
- field=models.BooleanField(default=True, verbose_name='Send as link'),
+ model_name="massemailattachment",
+ name="send_as_link",
+ field=models.BooleanField(default=True, verbose_name="Send as link"),
),
]
diff --git a/emailtemplates/migrations/0010_auto_20220803_1419.py b/emailtemplates/migrations/0010_auto_20220803_1419.py
new file mode 100644
index 0000000..e879af4
--- /dev/null
+++ b/emailtemplates/migrations/0010_auto_20220803_1419.py
@@ -0,0 +1,53 @@
+# Generated by Django 3.1.13 on 2022-08-03 12:19
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("emailtemplates", "0009_auto_20220111_1011"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="emailattachment",
+ options={
+ "ordering": ["ordering"],
+ "verbose_name": "Attachment",
+ "verbose_name_plural": "Attachments",
+ },
+ ),
+ migrations.AlterModelOptions(
+ name="massemailattachment",
+ options={
+ "ordering": ["ordering"],
+ "verbose_name": "Attachment",
+ "verbose_name_plural": "Attachments",
+ },
+ ),
+ migrations.AddField(
+ model_name="emailattachment",
+ name="comment",
+ field=models.TextField(
+ blank=True, verbose_name="Comment", help_text="visible only in admin"
+ ),
+ ),
+ migrations.AddField(
+ model_name="emailattachment",
+ name="ordering",
+ field=models.PositiveIntegerField(default=0, verbose_name="Ordering"),
+ ),
+ migrations.AddField(
+ model_name="massemailattachment",
+ name="comment",
+ field=models.TextField(
+ blank=True, verbose_name="Comment", help_text="visible only in admin"
+ ),
+ ),
+ migrations.AddField(
+ model_name="massemailattachment",
+ name="ordering",
+ field=models.PositiveIntegerField(default=0, verbose_name="Ordering"),
+ ),
+ ]
diff --git a/emailtemplates/models.py b/emailtemplates/models.py
index d675346..ec4dcf4 100644
--- a/emailtemplates/models.py
+++ b/emailtemplates/models.py
@@ -22,30 +22,40 @@ class EmailTemplate(models.Model):
"""
Model to store email template.
"""
- title = models.CharField(_(u'template'), max_length=255)
- subject = models.CharField(_(u'subject'), max_length=255, blank=True)
- content = models.TextField(_(u'content'))
- language = models.CharField(_(u'language'), max_length=10, choices=settings.LANGUAGES,
- default=settings.LANGUAGE_CODE)
- attachments = models.ManyToManyField("EmailAttachment", blank=True, verbose_name=_("attachments"))
+
+ id = models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name=_("ID")
+ )
+ title = models.CharField(_("template"), max_length=255)
+ subject = models.CharField(_("subject"), max_length=255, blank=True)
+ content = models.TextField(_("content"))
+ language = models.CharField(
+ _("language"),
+ max_length=10,
+ choices=settings.LANGUAGES,
+ default=settings.LANGUAGE_CODE,
+ )
+ attachments = models.ManyToManyField(
+ "EmailAttachment", blank=True, verbose_name=_("attachments")
+ )
created = models.DateTimeField(default=now, verbose_name=_("created"))
modified = models.DateTimeField(default=now, verbose_name=_("modified"))
class Meta:
- unique_together = (('title', 'language'),)
- verbose_name = _('Email template')
- verbose_name_plural = _('Email templates')
+ unique_together = (("title", "language"),)
+ verbose_name = _("Email template")
+ verbose_name_plural = _("Email templates")
def __str__(self):
- return '%s -> %s' % (self.title, self.language)
+ return "%s -> %s" % (self.title, self.language)
def get_default_content(self):
loader = TemplateSourceLoader()
try:
return loader.get_source(self.title)
except Exception as e:
- logger.error('Error loading template %s. Details: %s ', self.title, e)
- return ''
+ logger.error("Error loading template %s. Details: %s ", self.title, e)
+ return ""
def save(self, *args, **kwargs):
if not self.content:
@@ -54,12 +64,22 @@ def save(self, *args, **kwargs):
class BaseEmailAttachment(models.Model):
+ id = models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name=_("ID")
+ )
name = models.CharField(_("name"), blank=True, max_length=50)
- attachment_file = models.FileField(_(u"Attachment file"), upload_to="emails/attachments/")
+ attachment_file = models.FileField(
+ _("Attachment file"), upload_to="emails/attachments/"
+ )
+ comment = models.TextField(
+ verbose_name=_("Comment"), blank=True, help_text=_("visible only in admin")
+ )
+ ordering = models.PositiveIntegerField(verbose_name=_("Ordering"), default=0)
send_as_link = models.BooleanField(verbose_name=_("Send as link"), default=True)
class Meta:
abstract = True
+ ordering = ["ordering"]
verbose_name = _("Attachment")
verbose_name_plural = _("Attachments")
@@ -77,13 +97,16 @@ class EmailAttachment(BaseEmailAttachment):
class MassEmailMessage(models.Model):
- subject = models.CharField(_(u'subject'), max_length=255)
- content = models.TextField(_(u'content'))
- date_sent = models.DateTimeField(_(u'sent'), null=True, blank=True)
+ id = models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name=_("ID")
+ )
+ subject = models.CharField(_("subject"), max_length=255)
+ content = models.TextField(_("content"))
+ date_sent = models.DateTimeField(_("sent"), null=True, blank=True)
class Meta:
- verbose_name = _('Mass email message')
- verbose_name_plural = _('Mass email messages')
+ verbose_name = _("Mass email message")
+ verbose_name_plural = _("Mass email messages")
def __str__(self):
return self.subject
@@ -94,26 +117,35 @@ def sent(self):
def send(self, recipients=None, force=False):
from emailtemplates.email import EmailFromTemplate
+
recipients = recipients or mass_mailing_recipients()
if self.sent and not force:
return False
eft = EmailFromTemplate(
- name="emailtemplates/mass_email.html", subject=self.subject,
- template_object=self, registry_validation=False,
+ name="emailtemplates/mass_email.html",
+ subject=self.subject,
+ template_object=self,
+ registry_validation=False,
)
- attachment_paths = [attachment.attachment_file.path for attachment in self.attachments.all()]
+ attachment_paths = [
+ attachment.attachment_file.path for attachment in self.attachments.all()
+ ]
sent_count = 0
for recipient in recipients:
sent = eft.send(to=[recipient], attachment_paths=attachment_paths)
if sent:
sent_count += 1
- logger.info(u"Successfully sent mass email message to user %s", recipient)
+ logger.info(
+ "Successfully sent mass email message to user %s", recipient
+ )
else:
- logger.warning(u"Error sending mass email message to user %s", recipient)
+ logger.warning("Error sending mass email message to user %s", recipient)
self.date_sent = now()
self.save()
return sent_count == len(recipients)
class MassEmailAttachment(BaseEmailAttachment):
- mass_email_message = models.ForeignKey(MassEmailMessage, related_name="attachments", on_delete=models.CASCADE)
+ mass_email_message = models.ForeignKey(
+ MassEmailMessage, related_name="attachments", on_delete=models.CASCADE
+ )
diff --git a/emailtemplates/registry.py b/emailtemplates/registry.py
index 2d06503..9bb58cc 100644
--- a/emailtemplates/registry.py
+++ b/emailtemplates/registry.py
@@ -4,7 +4,6 @@
from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
-
logger = logging.getLogger(__name__)
@@ -20,6 +19,7 @@ class HelpContext(object):
"""
Provides helpers methods for displaying help context keys (descriptions) and values (examples).
"""
+
def __init__(self, help_context):
self.help_context = help_context or {}
@@ -44,13 +44,12 @@ def get_help_values(self):
if isinstance(v, tuple) and len(v) == 2:
help_values[k] = v[1]
else:
- help_values[k] = u"<%s>" % k
+ help_values[k] = "<%s>" % k
return help_values
class RegistrationItem(object):
-
- def __init__(self, path, help_text=u"", help_context=None, name=""):
+ def __init__(self, path, help_text="", help_context=None, name=""):
self.name = name or path
self.path = path
self.help_text = help_text
@@ -61,16 +60,31 @@ def help_context(self):
return self.help_context_obj.get_help_keys()
def _context_key(self, key):
- return u"{{ %s }}" % key
+ return "{{ %s }}" % key
def context_description(self):
- help_text_item = lambda k, v: u"%s - %s" % (self._context_key(k), v) if v else u"%s" % self._context_key(k)
- return u"
".join([help_text_item(k, v) for (k, v) in sorted(self.help_context_obj.get_help_keys().items())])
+ help_text_item = (
+ lambda k, v: "%s - %s" % (self._context_key(k), v)
+ if v
+ else "%s" % self._context_key(k)
+ )
+ return "
".join(
+ [
+ help_text_item(k, v)
+ for (k, v) in sorted(self.help_context_obj.get_help_keys().items())
+ ]
+ )
def as_form_help_text(self):
- item_help_text = _(u"USAGE: %s") % self.help_text if self.help_text else u""
- item_help_context = _(u"CONTEXT:
%s") % self.context_description() if self.help_context_obj.get_help_keys() else u""
- return u"
".join((item_help_text, item_help_context))
+ item_help_text = (
+ _("USAGE: %s") % self.help_text if self.help_text else ""
+ )
+ item_help_context = (
+ _("CONTEXT:
%s") % self.context_description()
+ if self.help_context_obj.get_help_keys()
+ else ""
+ )
+ return "
".join((item_help_text, item_help_context))
def as_form_choice(self):
return self.path, self.name
@@ -80,7 +94,6 @@ def get_help_content(self):
class EmailTemplateRegistry(object):
-
def __init__(self):
self._registry = {}
@@ -89,8 +102,8 @@ def register(self, path, name="", help_text=None, help_context=None):
Registers email template.
Example usage:
- email_templates.register('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
+ email_templates.register('hello_template.html', help_text='Hello template',
+ help_context={'username': 'Name of user in hello expression'})
:param name: Template name [optional]
:param path: Template file path. It will become immutable registry lookup key.
@@ -103,8 +116,10 @@ def register(self, path, name="", help_text=None, help_context=None):
If an email template is already registered, this will raise AlreadyRegistered.
"""
if path in self._registry:
- raise AlreadyRegistered('The template %s is already registered' % path)
- self._registry[path] = RegistrationItem(path, help_text, help_context, name=name)
+ raise AlreadyRegistered("The template %s is already registered" % path)
+ self._registry[path] = RegistrationItem(
+ path, help_text, help_context, name=name
+ )
logger.debug("Registered email template %s", path)
def is_registered(self, path):
@@ -146,11 +161,12 @@ def get_form_help_text(self, path):
Returns text that can be used as form help text for creating email templates.
"""
try:
- form_help_text = render_to_string("admin/emailtemplates/_helptext.html", context={
- 'registration_item': self.get_registration(path)
- })
+ form_help_text = render_to_string(
+ "admin/emailtemplates/_helptext.html",
+ context={"registration_item": self.get_registration(path)},
+ )
except NotRegistered:
- form_help_text = u""
+ form_help_text = ""
return form_help_text
diff --git a/emailtemplates/shortcuts.py b/emailtemplates/shortcuts.py
index 25d4068..3a36af8 100644
--- a/emailtemplates/shortcuts.py
+++ b/emailtemplates/shortcuts.py
@@ -2,7 +2,7 @@
from .email import EmailFromTemplate
-def send_email(name, ctx_dict, send_to=None, subject=u'Subject', **kwargs):
+def send_email(name, ctx_dict, send_to=None, subject="Subject", **kwargs):
"""
Shortcut function for EmailFromTemplate class
diff --git a/emailtemplates/tests/test_email.py b/emailtemplates/tests/test_email.py
index 27eb923..58041f0 100644
--- a/emailtemplates/tests/test_email.py
+++ b/emailtemplates/tests/test_email.py
@@ -1,7 +1,7 @@
# coding=utf-8
-import mock
import os
+import mock
from django.conf import settings
from django.core import mail
from django.test import TestCase, override_settings
@@ -10,8 +10,7 @@
from ..email import EmailFromTemplate
from ..email import logger as email_logger
-from ..helpers import substr
-from ..models import EmailTemplate
+from ..models import EmailTemplate, EmailAttachment
from ..registry import email_templates, NotRegistered, EmailTemplateRegistry
@@ -23,10 +22,10 @@ def check_email_was_sent(self, eft, to, reply_to=None):
self.assertTrue(len(mail.outbox) > 0)
msg = mail.outbox[0]
self.assertTrue(settings.DEFAULT_FROM_EMAIL in msg.from_email)
- self.assertEqual(msg.content_subtype, 'html')
+ self.assertEqual(msg.content_subtype, "html")
self.assertEqual(msg.subject, eft.subject)
self.assertEqual(msg.body, eft.message)
- self.assertTrue('Message-Id' in msg.message())
+ self.assertTrue("Message-Id" in msg.message())
self.assertEqual(msg.to, to)
self.assertEqual(msg.reply_to, reply_to)
@@ -35,37 +34,61 @@ class EmailFromTemplateTest(CheckEmail):
def setUp(self):
mail.outbox = []
email_templates = EmailTemplateRegistry()
- email_logger.warning = Mock()
- self.attachment_filepath = os.path.join(os.path.dirname(__file__), 'data', 'example_file.txt')
+ self.attachment_filepath = os.path.join(
+ os.path.dirname(__file__), "data", "example_file.txt"
+ )
- @override_settings(DEFAULT_REPLY_TO_EMAIL='hello@hello.pl')
+ @override_settings(DEFAULT_REPLY_TO_EMAIL="hello@hello.pl")
def test_empty_object(self):
eft = EmailFromTemplate(registry_validation=False)
self.assertTrue(isinstance(eft, object))
eft.render_message()
- to = ['to@example.com']
+ to = ["to@example.com"]
eft.send_email(to)
- self.check_email_was_sent(eft, to, reply_to=['hello@hello.pl'])
+ self.check_email_was_sent(eft, to, reply_to=["hello@hello.pl"])
@override_settings(DEFAULT_REPLY_TO_EMAIL=None)
def test_empty_object_with_empty_reply_to(self):
eft = EmailFromTemplate(registry_validation=False)
self.assertTrue(isinstance(eft, object))
eft.render_message()
- to = ['to@example.com']
+ to = ["to@example.com"]
eft.send_email(to)
self.check_email_was_sent(eft, to)
- def test_with_empty_db_object(self):
- eft = EmailFromTemplate(registry_validation=False)
+ @mock.patch("emailtemplates.email.logger")
+ def test_with_empty_db_object(self, mock_logger):
+ eft = EmailFromTemplate(registry_validation=False, name="template.html")
eft.get_object()
- email_logger.warning.assert_has_calls(substr("Can't find EmailTemplate object in database"))
- email_logger.warning.assert_has_calls(substr("template in the filesystem, will use very default one"))
+ mock_logger.warning.assert_called_with(
+ "Can't find %s template in the filesystem, will use very default one.",
+ "template.html",
+ )
eft.render_message()
- to = ['to@example.com']
+ to = ["to@example.com"]
eft.send_email(to)
self.check_email_was_sent(eft, to)
+ def test_get_default_attachments_ordering(self):
+ email_template = EmailTemplate.objects.create(title="template.html")
+ attachment1 = EmailAttachment.objects.create(
+ name="file1",
+ attachment_file="test/file1.pdf",
+ ordering=10,
+ send_as_link=True,
+ )
+ attachment2 = EmailAttachment.objects.create(
+ name="file2",
+ attachment_file="test/file2.pdf",
+ ordering=1,
+ send_as_link=True,
+ )
+ email_template.attachments.add(attachment1, attachment2)
+ eft = EmailFromTemplate(registry_validation=False, name="template.html")
+ result = eft.get_default_attachments(as_links=True)
+ self.assertEqual(result[0][0], attachment2.name)
+ self.assertEqual(result[1][0], attachment1.name)
+
def test_init_check_email_templates_registry(self):
with self.assertRaises(NotRegistered):
email_template = EmailFromTemplate("some_template.html")
@@ -75,63 +98,73 @@ def test_init_check_email_templates_registry(self):
def test_send_attachment_paths(self):
eft = EmailFromTemplate(registry_validation=False)
- to = ['to@example.com']
+ to = ["to@example.com"]
eft.send(to, attachment_paths=[self.attachment_filepath])
self.check_email_was_sent(eft, to)
self.assertEqual(
- mail.outbox[0].attachments,
- [('example_file.txt', u'Some content of example file.', 'text/plain')],
+ mail.outbox[0].attachments,
+ [("example_file.txt", "Some content of example file.", "text/plain")],
)
class EmailFromTemplateWithFixturesTest(CheckEmail):
def setUp(self):
- self.language = 'pl'
+ self.language = "pl"
email_templates = EmailTemplateRegistry()
self.support_template = EmailTemplate.objects.create(
language=self.language,
- title='support_respond.html',
+ title="support_respond.html",
subject="Hi {{ user_name }}",
- content="Support: {{ user_name }}"
+ content="Support: {{ user_name }}",
)
mail.outbox = []
email_logger.debug = Mock()
def test_support_database_template(self):
- template_name = 'support_respond.html'
- eft = EmailFromTemplate(name=template_name, language=self.language, registry_validation=False)
+ template_name = "support_respond.html"
+ eft = EmailFromTemplate(
+ name=template_name, language=self.language, registry_validation=False
+ )
eft.context = {"user_name": "Lucas"}
eft.get_object()
- email_logger.debug.assert_called_with('Got template %s from database', template_name)
- self.assertEqual(eft.template_source, 'database')
+ email_logger.debug.assert_called_with(
+ "Got template %s from database", template_name
+ )
+ self.assertEqual(eft.template_source, "database")
eft.render_message()
- to = ['tester1@example.com', 'tester2@example.com']
+ to = ["tester1@example.com", "tester2@example.com"]
eft.send_email(to)
self.check_email_was_sent(eft, to)
def test_support_database_template_without_title(self):
- self.support_template.subject = ''
- self.support_template.save(update_fields=['subject'])
+ self.support_template.subject = ""
+ self.support_template.save(update_fields=["subject"])
eft = EmailFromTemplate(
- name='support_respond.html',
- subject='default email title - hi {{ user_name }}',
+ name="support_respond.html",
+ subject="default email title - hi {{ user_name }}",
language=self.language,
- registry_validation=False
+ registry_validation=False,
)
eft.context = {"user_name": "Lucas"}
eft.get_object()
- self.assertEqual(eft.subject, 'default email title - hi Lucas')
+ self.assertEqual(eft.subject, "default email title - hi Lucas")
def test_friends_invitation_no_database_or_filesystem_template(self):
eft = EmailFromTemplate(registry_validation=False)
- eft.context = {'user_name': 'Alibaba',
- 'personal_message': "I'd like you te be site member!",
- 'landing_url': 'http://example.com/followers/612/'}
+ eft.context = {
+ "user_name": "Alibaba",
+ "personal_message": "I'd like you te be site member!",
+ "landing_url": "http://example.com/followers/612/",
+ }
eft.template = "{{ user_name }}, {{ personal_message }} {{ landing_url }}"
eft.render_message()
- self.assertEqual(eft.message,
- escape(u"Alibaba, I'd like you te be site member! http://example.com/followers/612/"))
- to = ['tester@example.com']
- self.assertEqual(eft.template_source, 'default')
+ self.assertEqual(
+ eft.message,
+ escape(
+ "Alibaba, I'd like you te be site member! http://example.com/followers/612/"
+ ),
+ )
+ to = ["tester@example.com"]
+ self.assertEqual(eft.template_source, "default")
eft.send_email(to)
self.check_email_was_sent(eft, to)
diff --git a/emailtemplates/tests/test_helpers.py b/emailtemplates/tests/test_helpers.py
index 4993b87..d81600f 100644
--- a/emailtemplates/tests/test_helpers.py
+++ b/emailtemplates/tests/test_helpers.py
@@ -5,17 +5,21 @@
def recipients_test_function():
- return ['user@example.com', 'another@example.com']
+ return ["user@example.com", "another@example.com"]
-class HelpersTest(TestCase):
+class HelpersTest(TestCase):
def test_mass_mailing_recipients(self):
User = get_user_model()
User.objects.create(username="mike", email="mike@example.com", is_active=True)
User.objects.create(username="john", email="john@example.com", is_active=False)
User.objects.create(username="paul", is_active=True)
self.assertEqual(list(mass_mailing_recipients()), ["mike@example.com"])
-
- @override_settings(MASS_EMAIL_RECIPIENTS='emailtemplates.tests.test_helpers.recipients_test_function')
+
+ @override_settings(
+ MASS_EMAIL_RECIPIENTS="emailtemplates.tests.test_helpers.recipients_test_function"
+ )
def test_mass_mailing_recipients_from_settings(self):
- self.assertEqual(mass_mailing_recipients(), ['user@example.com', 'another@example.com'])
+ self.assertEqual(
+ mass_mailing_recipients(), ["user@example.com", "another@example.com"]
+ )
diff --git a/emailtemplates/tests/test_models.py b/emailtemplates/tests/test_models.py
index 352c801..beee1f0 100644
--- a/emailtemplates/tests/test_models.py
+++ b/emailtemplates/tests/test_models.py
@@ -1,8 +1,9 @@
# encoding: utf-8
from __future__ import unicode_literals
-import mock
+
import os
+import mock
from django.core import mail
from django.core.files import File
from django.test import TestCase
@@ -13,38 +14,46 @@
class EmailTemplateTest(TestCase):
def setUp(self):
- self.default_content = 'TEST DEFAULT CONTENT
'
- self.email_template = EmailTemplate.objects.create(title='template-1.html')
+ self.default_content = "TEST DEFAULT CONTENT
"
+ self.email_template = EmailTemplate.objects.create(title="template-1.html")
- @mock.patch.object(TemplateSourceLoader, 'get_source')
+ @mock.patch.object(TemplateSourceLoader, "get_source")
def test_get_default_content(self, mock_source):
mock_source.return_value = self.default_content
- self.assertEqual(self.email_template.get_default_content(), self.default_content)
+ self.assertEqual(
+ self.email_template.get_default_content(), self.default_content
+ )
- @mock.patch.object(TemplateSourceLoader, 'get_source', mock.Mock(side_effect=Exception('error...')))
+ @mock.patch.object(
+ TemplateSourceLoader, "get_source", mock.Mock(side_effect=Exception("error..."))
+ )
def test_get_empty_default_content_if_error(self):
- self.assertEqual(self.email_template.get_default_content(), '')
+ self.assertEqual(self.email_template.get_default_content(), "")
- @mock.patch.object(TemplateSourceLoader, 'get_source')
+ @mock.patch.object(TemplateSourceLoader, "get_source")
def test_save_default_content(self, mock_source):
mock_source.return_value = self.default_content
- email_template = EmailTemplate.objects.create(title='template-2.html')
+ email_template = EmailTemplate.objects.create(title="template-2.html")
self.assertEqual(email_template.content, self.default_content)
- @mock.patch.object(TemplateSourceLoader, 'get_source')
+ @mock.patch.object(TemplateSourceLoader, "get_source")
def test_do_not_override_existing_content(self, mock_source):
mock_source.return_value = self.default_content
- email_template = EmailTemplate.objects.create(title='template-2.html', content='New content
')
- self.assertEqual(email_template.content, 'New content
')
+ email_template = EmailTemplate.objects.create(
+ title="template-2.html", content="New content
"
+ )
+ self.assertEqual(email_template.content, "New content
")
class MassEmailMessageTest(TestCase):
def setUp(self):
self.mass_email_message = MassEmailMessage.objects.create(
- subject="Temat maila",
- content="Treść emaila
"
+ subject="Temat maila", content="Treść emaila
"
)
- self.attachment_filepath = os.path.join(os.path.dirname(__file__), 'data', 'example_file.txt')
+ self.attachment_filepath = os.path.join(
+ os.path.dirname(__file__), "data", "example_file.txt"
+ )
+ mail.outbox = []
def test_send(self):
recipients = ["person@example.com"]
@@ -57,13 +66,15 @@ def test_send(self):
def test_send_with_attachments(self):
attachment = MassEmailAttachment.objects.create(
- attachment_file=File(open(self.attachment_filepath, 'r'), 'example_file.txt'),
+ attachment_file=File(
+ open(self.attachment_filepath, "r"), "example_file.txt"
+ ),
mass_email_message=self.mass_email_message,
)
recipients = ["person@example.com"]
sent = self.mass_email_message.send(recipients)
self.assertTrue(sent)
self.assertEqual(
- mail.outbox[0].attachments,
- [('example_file.txt', u'Some content of example file.', 'text/plain')],
- )
\ No newline at end of file
+ mail.outbox[0].attachments,
+ [("example_file.txt", "Some content of example file.", "text/plain")],
+ )
diff --git a/emailtemplates/tests/test_template_registry.py b/emailtemplates/tests/test_template_registry.py
index 942458f..6e0da11 100644
--- a/emailtemplates/tests/test_template_registry.py
+++ b/emailtemplates/tests/test_template_registry.py
@@ -1,121 +1,155 @@
# coding=utf-8
from django.test import TestCase
+from django.utils.translation import gettext as _
from ..registry import EmailTemplateRegistry, RegistrationItem, HelpContext
class HelpContextTest(TestCase):
-
def test_get_help_keys(self):
- help_context = HelpContext({
- 'username': (u'Name of user in hello expression', u'superman_90'),
- 'full_name': (u'Full user name', u'John Smith'),
- 'property': u'Some other property',
- })
- self.assertDictEqual(help_context.get_help_keys(), {
- 'username': u'Name of user in hello expression',
- 'full_name': u'Full user name',
- 'property': u'Some other property',
- })
+ help_context = HelpContext(
+ {
+ "username": ("Name of user in hello expression", "superman_90"),
+ "full_name": ("Full user name", "John Smith"),
+ "property": "Some other property",
+ }
+ )
+ self.assertDictEqual(
+ help_context.get_help_keys(),
+ {
+ "username": "Name of user in hello expression",
+ "full_name": "Full user name",
+ "property": "Some other property",
+ },
+ )
def test_get_help_values(self):
- help_context = HelpContext({
- 'username': (u'Name of user in hello expression', u'superman_90'),
- 'full_name': (u'Full user name', u'John Smith'),
- 'property': u'Some other property',
- })
- self.assertDictEqual(help_context.get_help_values(), {
- 'username': u'superman_90',
- 'full_name': u'John Smith',
- 'property': u'',
- })
+ help_context = HelpContext(
+ {
+ "username": ("Name of user in hello expression", "superman_90"),
+ "full_name": ("Full user name", "John Smith"),
+ "property": "Some other property",
+ }
+ )
+ self.assertDictEqual(
+ help_context.get_help_values(),
+ {
+ "username": "superman_90",
+ "full_name": "John Smith",
+ "property": "",
+ },
+ )
class RegistrationItemTest(TestCase):
-
def test_context_description(self):
- item = RegistrationItem('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
- self.assertIn(u"{{ username }}", item.context_description())
+ item = RegistrationItem(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
+ self.assertIn("{{ username }}", item.context_description())
def test_as_form_help_text(self):
- item = RegistrationItem('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
+ item = RegistrationItem(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
self.assertEqual(str, type(item.as_form_help_text()))
- self.assertIn("USAGE", item.as_form_help_text())
- self.assertIn("CONTEXT", item.as_form_help_text())
+ self.assertIn(_("USAGE"), item.as_form_help_text())
+ self.assertIn(_("CONTEXT"), item.as_form_help_text())
def test_as_form_choice(self):
- item = RegistrationItem('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
+ item = RegistrationItem(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
self.assertEqual(tuple, type(item.as_form_choice()))
def test_safe_defaults(self):
- item = RegistrationItem('hello_template.html')
+ item = RegistrationItem("hello_template.html")
self.assertEqual(str, type(item.help_text))
self.assertEqual(dict, type(item.help_context))
self.assertEqual(tuple, type(item.as_form_choice()))
class EmailTemplateRegistryTest(TestCase):
-
def test_is_registered(self):
registry = EmailTemplateRegistry()
- registry.register('hello_template.html')
- self.assertTrue(registry.is_registered('hello_template.html'))
+ registry.register("hello_template.html")
+ self.assertTrue(registry.is_registered("hello_template.html"))
def test_get_help_text(self):
template_registry = EmailTemplateRegistry()
- template_registry.register('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
- help_text = template_registry.get_help_text('hello_template.html')
- self.assertEqual(help_text, u'Hello template')
+ template_registry.register(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
+ help_text = template_registry.get_help_text("hello_template.html")
+ self.assertEqual(help_text, "Hello template")
def test_get_help_context(self):
template_registry = EmailTemplateRegistry()
- template_registry.register('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
- help_context = template_registry.get_help_context('hello_template.html')
- self.assertIn('username', help_context)
+ template_registry.register(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
+ help_context = template_registry.get_help_context("hello_template.html")
+ self.assertIn("username", help_context)
def test_get_help_content(self):
template_registry = EmailTemplateRegistry()
- template_registry.register('hello_template.html', help_text=u'Hello template',
- help_context={
- 'username': (u'Name of user in hello expression', u'superman_90'),
- 'full_name': (u'Full user name', u'John Smith'),
- 'property': u'Some other property',
- })
- help_content = template_registry.get_help_content('hello_template.html')
- self.assertDictEqual(help_content, {
- 'username': u'superman_90',
- 'full_name': u'John Smith',
- 'property': u'',
- })
+ template_registry.register(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={
+ "username": ("Name of user in hello expression", "superman_90"),
+ "full_name": ("Full user name", "John Smith"),
+ "property": "Some other property",
+ },
+ )
+ help_content = template_registry.get_help_content("hello_template.html")
+ self.assertDictEqual(
+ help_content,
+ {
+ "username": "superman_90",
+ "full_name": "John Smith",
+ "property": "",
+ },
+ )
def test_get_email_templates(self):
template_registry = EmailTemplateRegistry()
- template_registry.register('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
- template_registry.register('simple_template.html', help_text=u'Simple template')
+ template_registry.register(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
+ template_registry.register("simple_template.html", help_text="Simple template")
self.assertEqual(2, len(template_registry.email_template_choices()))
def test_email_template_choices(self):
template_registry = EmailTemplateRegistry()
- template_registry.register('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
+ template_registry.register(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
self.assertEqual(1, len(template_registry.email_template_choices()))
template, _ = template_registry.email_template_choices()[0]
- self.assertEqual('hello_template.html', template)
+ self.assertEqual("hello_template.html", template)
def test_registration_items(self):
template_registry = EmailTemplateRegistry()
- template_registry.register('hello_template.html', help_text=u'Hello template',
- help_context={'username': u'Name of user in hello expression'})
+ template_registry.register(
+ "hello_template.html",
+ help_text="Hello template",
+ help_context={"username": "Name of user in hello expression"},
+ )
items = list(template_registry.registration_items())
self.assertEqual(1, len(items))
- self.assertEqual('hello_template.html', items[0].path)
-
-
-
-
+ self.assertEqual("hello_template.html", items[0].path)
diff --git a/emailtemplates/urls.py b/emailtemplates/urls.py
index 680bd50..040cd7f 100644
--- a/emailtemplates/urls.py
+++ b/emailtemplates/urls.py
@@ -3,6 +3,8 @@
from emailtemplates.views import email_preview_view, send_mass_email_view
urlpatterns = [
- url(r'^email-preview/(?P\d+)/$', email_preview_view, name='email_preview'),
- url(r'^send-mass-email/(?P\d+)/$', send_mass_email_view, name='send_mass_email'),
+ url(r"^email-preview/(?P\d+)/$", email_preview_view, name="email_preview"),
+ url(
+ r"^send-mass-email/(?P\d+)/$", send_mass_email_view, name="send_mass_email"
+ ),
]
diff --git a/emailtemplates/views.py b/emailtemplates/views.py
index 6a9a124..f7292e8 100644
--- a/emailtemplates/views.py
+++ b/emailtemplates/views.py
@@ -15,9 +15,8 @@
class EmailPreviewView(View):
-
def get_email_template(self):
- return get_object_or_404(EmailTemplate, pk=self.kwargs['pk'])
+ return get_object_or_404(EmailTemplate, pk=self.kwargs["pk"])
def get_context_data(self):
email_template = self.get_email_template()
@@ -28,7 +27,7 @@ def get(self, request, *args, **kwargs):
email_content = Template(email_template.content)
return HttpResponse(
email_content.render(Context(self.get_context_data())),
- content_type='text/html; charset=utf-8'
+ content_type="text/html; charset=utf-8",
)
@@ -36,26 +35,35 @@ def get(self, request, *args, **kwargs):
class SendMassEmailView(View):
-
def get_mass_email_message(self):
- return get_object_or_404(MassEmailMessage, pk=self.kwargs['pk'])
+ return get_object_or_404(MassEmailMessage, pk=self.kwargs["pk"])
def redirect_back(self):
return HttpResponseRedirect(
- reverse('admin:emailtemplates_massemailmessage_change', args=(self.get_mass_email_message().pk,)),
+ reverse(
+ "admin:emailtemplates_massemailmessage_change",
+ args=(self.get_mass_email_message().pk,),
+ ),
)
def get(self, request, *args, **kwargs):
mass_email_message = self.get_mass_email_message()
if mass_email_message.sent:
- messages.success(request, _("Mass email was already sent. "
- "Create new mail message or force sending from shell."))
+ messages.success(
+ request,
+ _(
+ "Mass email was already sent. "
+ "Create new mail message or force sending from shell."
+ ),
+ )
return self.redirect_back()
sent = mass_email_message.send()
if sent:
messages.success(request, _("Mass email sent successfully"))
else:
- messages.warning(request, _("Error occurred when trying to send mass email message."))
+ messages.warning(
+ request, _("Error occurred when trying to send mass email message.")
+ )
return self.redirect_back()
diff --git a/setup.py b/setup.py
index 1562e3f..e1e846e 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@
setup(
name='django-emailtemplates',
- version='1.1.13',
+ version='1.1.14',
packages=find_packages(),
package_data={'emailtemplates': ['locale/*/LC_MESSAGES/*.po', 'locale/*/LC_MESSAGES/*.mo']},
include_package_data=True,