diff --git a/orchestra/contrib/accounts/serializers.py b/orchestra/contrib/accounts/serializers.py
index e58bb268..37edfdf8 100644
--- a/orchestra/contrib/accounts/serializers.py
+++ b/orchestra/contrib/accounts/serializers.py
@@ -15,7 +15,7 @@ class AccountSerializer(serializers.HyperlinkedModelSerializer):
class AccountSerializerMixin(object):
def __init__(self, *args, **kwargs):
super(AccountSerializerMixin, self).__init__(*args, **kwargs)
- self.account = None
+ self.account = self.get_account()
def get_account(self):
request = self.context.get('request')
diff --git a/orchestra/contrib/bills/templates/bills/microspective-fee.html b/orchestra/contrib/bills/templates/bills/microspective-fee.html
index 5825feec..33cf7de4 100644
--- a/orchestra/contrib/bills/templates/bills/microspective-fee.html
+++ b/orchestra/contrib/bills/templates/bills/microspective-fee.html
@@ -93,7 +93,7 @@ hr {
{{ buyer.vat }}
{{ buyer.address }}
{{ buyer.zipcode }} - {{ buyer.city }}
- {{ buyer.get_country_display }}
+ {% trans buyer.get_country_display %}
diff --git a/orchestra/contrib/domains/serializers.py b/orchestra/contrib/domains/serializers.py
index cc4d22cf..5eb1471a 100644
--- a/orchestra/contrib/domains/serializers.py
+++ b/orchestra/contrib/domains/serializers.py
@@ -39,9 +39,13 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
def validate(self, data):
""" Checks if everything is consistent """
data = super(DomainSerializer, self).validate(data)
- if self.instance and data.get('name'):
+ name = data.get('name')
+ if name:
+ instance = self.instance
+ if instance is None:
+ instance = Domain(name=name, account=self.account)
records = data['records']
- domain = domain_for_validation(self.instance, records)
+ domain = domain_for_validation(instance, records)
validators.validate_zone(domain.render_zone())
return data
@@ -52,9 +56,9 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
domain.records.create(type=record['type'], value=record['value'])
return domain
- def update(self, validated_data):
+ def update(self, instance, validated_data):
precords = validated_data.pop('records')
- domain = super(DomainSerializer, self).update(validated_data)
+ domain = super(DomainSerializer, self).update(instance, validated_data)
to_delete = []
for erecord in domain.records.all():
match = False
@@ -63,7 +67,7 @@ class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
match = True
break
if match:
- precords.remove(ix)
+ precords.pop(ix)
else:
to_delete.append(erecord)
for precord in precords:
diff --git a/orchestra/contrib/domains/validators.py b/orchestra/contrib/domains/validators.py
index e3e8114e..d8aeee6a 100644
--- a/orchestra/contrib/domains/validators.py
+++ b/orchestra/contrib/domains/validators.py
@@ -120,7 +120,10 @@ def validate_zone(zone):
# Don't use /dev/stdin becuase the 'argument list is too long' error
check = run(' '.join([checkzone, zone_name, zone_path]), valid_codes=(0,1,127), display=False)
finally:
- os.unlink(zone_path)
+ try:
+ os.unlink(zone_path)
+ except FileNotFoundError:
+ pass
if check.exit_code == 127:
logger.error("Cannot validate domain zone: %s not installed." % checkzone)
elif check.exit_code == 1:
diff --git a/orchestra/contrib/mailer/backends.py b/orchestra/contrib/mailer/backends.py
index 65de5cdf..f078e7ef 100644
--- a/orchestra/contrib/mailer/backends.py
+++ b/orchestra/contrib/mailer/backends.py
@@ -1,6 +1,9 @@
from django.conf import settings as djsettings
from django.core.mail.backends.base import BaseEmailBackend
+from orchestra.core.caches import get_request_cache
+
+from . import settings
from .models import Message
from .tasks import send_message
@@ -9,17 +12,27 @@ class EmailBackend(BaseEmailBackend):
"""
A wrapper that manages a queued SMTP system.
"""
+ messages = 0
+
def send_messages(self, email_messages):
if not email_messages:
return
- num_sent = 0
+ cache = get_request_cache()
+ key = 'mailer.sent_messages'
+ sent_messages = cache.get(key) or 0
+ sent_messages += 1
+ cache.set(key, sent_messages)
+
is_bulk = len(email_messages) > 1
+ if sent_messages > settings.MAILER_NON_QUEUED_MAILS_PER_REQUEST_THRESHOLD:
+ is_bulk = True
default_priority = Message.NORMAL if is_bulk else Message.CRITICAL
+ num_sent = 0
for message in email_messages:
priority = message.extra_headers.get('X-Mail-Priority', default_priority)
content = message.message().as_string()
for to_email in message.recipients():
- message = Message.objects.create(
+ message = Message(
priority=priority,
to_address=to_email,
from_address=getattr(message, 'from_email', djsettings.DEFAULT_FROM_EMAIL),
@@ -29,5 +42,7 @@ class EmailBackend(BaseEmailBackend):
if priority == Message.CRITICAL:
# send immidiately
send_message.apply_async(message)
+ else:
+ message.save()
num_sent += 1
return num_sent
diff --git a/orchestra/contrib/mailer/models.py b/orchestra/contrib/mailer/models.py
index e0e3c3b8..be952cb8 100644
--- a/orchestra/contrib/mailer/models.py
+++ b/orchestra/contrib/mailer/models.py
@@ -50,7 +50,7 @@ class Message(models.Model):
def sent(self):
self.state = self.SENT
- self.save(update_fields=('state',))
+ self.save()
def log(self, error):
result = SMTPLog.SUCCESS
diff --git a/orchestra/contrib/mailer/settings.py b/orchestra/contrib/mailer/settings.py
index 1eb9cb1e..9e0d42e5 100644
--- a/orchestra/contrib/mailer/settings.py
+++ b/orchestra/contrib/mailer/settings.py
@@ -1,3 +1,5 @@
+from django.utils.translation import ugettext_lazy as _
+
from orchestra.contrib.settings import Setting
@@ -9,3 +11,9 @@ MAILER_DEFERE_SECONDS = Setting('MAILER_DEFERE_SECONDS',
MAILER_MESSAGES_CLEANUP_DAYS = Setting('MAILER_MESSAGES_CLEANUP_DAYS',
7
)
+
+
+MAILER_NON_QUEUED_MAILS_PER_REQUEST_THRESHOLD = Setting('MAILER_NON_QUEUED_MAILS_PER_REQUEST_THRESHOLD',
+ 2,
+ help_text=_("Number of emails that will be sent directly before starting to queue them."),
+)
diff --git a/orchestra/core/caches.py b/orchestra/core/caches.py
index 4550d827..9c5e86fb 100644
--- a/orchestra/core/caches.py
+++ b/orchestra/core/caches.py
@@ -27,11 +27,19 @@ def get_request_cache():
class RequestCacheMiddleware(object):
def process_request(self, request):
- cache = _request_cache.get(currentThread(), RequestCache())
- _request_cache[currentThread()] = cache
+ current_thread = currentThread()
+ cache = _request_cache.get(current_thread, RequestCache())
+ _request_cache[current_thread] = cache
cache.clear()
- def process_response(self, request, response):
+ def clear_cache(self):
+ current_thread = currentThread()
if currentThread() in _request_cache:
- _request_cache[currentThread()].clear()
+ _request_cache[current_thread].clear()
+
+ def process_exception(self, request, exception):
+ self.clear_cache()
+
+ def process_response(self, request, response):
+ self.clear_cache()
return response
diff --git a/orchestra/utils/html.py b/orchestra/utils/html.py
index 7e51df9e..6d84a52d 100644
--- a/orchestra/utils/html.py
+++ b/orchestra/utils/html.py
@@ -5,7 +5,6 @@ from orchestra.utils.sys import run
def html_to_pdf(html, pagination=False):
""" converts HTL to PDF using wkhtmltopdf """
- print(pagination)
context = {
'pagination': textwrap.dedent("""\
--footer-center "Page [page] of [topage]"\\
diff --git a/orchestra/utils/mail.py b/orchestra/utils/mail.py
index fd189075..21028fb9 100644
--- a/orchestra/utils/mail.py
+++ b/orchestra/utils/mail.py
@@ -5,7 +5,7 @@ from django.template.loader import render_to_string
from django.template import Context
-def send_email_template(template, context, to, email_from=None, html=None, attachments=[]):
+def render_email_template(template, context):
"""
Renders an email template with this format:
{% if subject %}Subject{% endif %}
@@ -13,7 +13,6 @@ def send_email_template(template, context, to, email_from=None, html=None, attac
context can be a dictionary or a template.Context instance
"""
-
if isinstance(context, dict):
context = Context(context)
if isinstance(to, str):
@@ -27,13 +26,16 @@ def send_email_template(template, context, to, email_from=None, html=None, attac
'scheme': url.scheme,
'domain': url.netloc,
}
-
- #subject cannot have new lines
subject = render_to_string(template, {'subject': True}, context).strip()
message = render_to_string(template, {'message': True}, context).strip()
+ return subject, message
+
+
+def send_email_template(template, context, to, email_from=None, html=None, attachments=[]):
+ subject, message = render_email_template(template, context)
msg = EmailMultiAlternatives(subject, message, email_from, to, attachments=attachments)
if html:
- html_message = render_to_string(html, {'message': True}, context)
+ subject, html_message = render_email_template(html, context)
msg.attach_alternative(html_message, "text/html")
msg.send()