Skip to content
Merged
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
7 changes: 2 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@ python:

env:
matrix:
- DJANGO=2.0
- DJANGO=2.1
- DJANGO=2.2
- DJANGO=3.0
- DJANGO=3.1
- DJANGO=master

addons:
postgresql: '9.6'

matrix:
exclude:
- { python: "3.7", env: DJANGO=2.0 }

include:
- { python: "3.6", env: TOXENV=flake8 }

Expand Down
30 changes: 30 additions & 0 deletions entity_emailer/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,33 @@ def convert_events_to_emails():

# Create the emails
Email.objects.create_email(event=event, from_address=from_address, recipients=targets)

@staticmethod
def bulk_convert_events_to_emails():
"""
Converts unseen events to emails and marks them as seen. Uses the create_emails method to bulk create
emails and recipient relationships
"""

# Get the email medium
email_medium = get_medium()

# Get the default from email
default_from_email = get_from_email_address()

email_params_list = []

# Find any unseen events and create unsent email objects
for event, targets in email_medium.events_targets(seen=False, mark_seen=True):

# Check the event's context for a from_address, otherwise fallback to default
from_address = event.context.get('from_address') or default_from_email

email_params_list.append(dict(
event=event,
from_address=from_address,
recipients=targets
))

# Bulk create the emails
Email.objects.create_emails(email_params_list)
37 changes: 36 additions & 1 deletion entity_emailer/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import datetime

from django.db import models
from django.db import models, transaction
from entity.models import Entity
from entity_event.models import Event
import uuid
Expand All @@ -26,6 +26,41 @@ def create_email(self, recipients=None, **kwargs):
email.save()
return email

@transaction.atomic
def create_emails(self, email_params_list):
"""
:param email_params_list: A list of dicts containing the keys for the create_email method
:return: list of Email objects that were created
"""
emails_to_create = []
recipient_entities_per_email = []

# Build the emails to create and keep track of recipients
for kwargs in email_params_list:
scheduled = kwargs.pop('scheduled', datetime.utcnow())
recipients = kwargs.pop('recipients', [])
emails_to_create.append(Email(scheduled=scheduled, **kwargs))
recipient_entities_per_email.append(recipients)

# Bulk create the emails
emails = Email.objects.bulk_create(emails_to_create)

# Build list of recipient through relationships to create
recipients_to_create = []
for i, recipient_entities in enumerate(recipient_entities_per_email):
for recipient_entity in recipient_entities:
recipients_to_create.append(
Email.recipients.through(
email_id=emails[i].id,
entity_id=recipient_entity.id,
)
)

# Bulk create the recipient relationships
Email.recipients.through.objects.bulk_create(recipients_to_create)

return emails


class Email(models.Model):
"""Save an Email object and it is sent automagically!
Expand Down
24 changes: 24 additions & 0 deletions entity_emailer/tests/interface_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,30 @@ def test_multiple_events_only_following_false(self):
self.assertEquals(email.subject, '')
self.assertEquals(email.scheduled, datetime(2013, 1, 2))

@freeze_time('2013-1-2')
def test_bulk_multiple_events_only_following_false(self):
source = G(Source)
e = G(Entity)
other_e = G(Entity)

G(Subscription, entity=e, source=source, medium=self.email_medium, only_following=False)
G(Subscription, entity=other_e, source=source, medium=self.email_medium, only_following=False)
email_context = {
'entity_emailer_template': 'template',
'entity_emailer_subject': 'hi',
}
G(Event, source=source, context=email_context)
G(Event, source=source, context=email_context)

EntityEmailerInterface.bulk_convert_events_to_emails()

self.assertEquals(Email.objects.count(), 2)
for email in Email.objects.all():
self.assertEquals(set(email.recipients.all()), set([e, other_e]))
self.assertEquals(email.event.context, email_context)
self.assertEquals(email.subject, '')
self.assertEquals(email.scheduled, datetime(2013, 1, 2))

@freeze_time('2013-1-2')
def test_multiple_events_only_following_true(self):
source = G(Source)
Expand Down
2 changes: 1 addition & 1 deletion entity_emailer/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.1.2'
__version__ = '2.0.0'
5 changes: 5 additions & 0 deletions release_notes.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Release Notes
=============

v2.0.0
------
* Added bulk interface for converting to emails
* Add support for django 3.0, 3.1

v1.1.2
------
* Handle email render exceptions
Expand Down
14 changes: 7 additions & 7 deletions requirements/requirements-testing.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
coverage
django-dynamic-fixture<=2.0.0
django-nose
flake8
freezegun
mock
psycopg2
coverage==4.5.1
django-dynamic-fixture
django-nose==1.4.5
flake8==3.5.0
freezegun==0.3.12
mock==2.0.0
psycopg2>=2.7.7
12 changes: 7 additions & 5 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
beautifulsoup4>=4.3.2
Django>=2.0,<3.0
django-db-mutex>=1.2.0
django-entity>=4.2.0
django-entity-event>=1.2.0
Django>=2.2

django-db-mutex>=2.0.0
django-entity>=5.0.0
django-entity-event>=2.0.0
ambition-django-uuidfield>=0.5.0

beautifulsoup4>=4.3.2
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ def get_requirements(requirements_file):
'Programming Language :: Python',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Framework :: Django',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
],
license='MIT',
install_requires=get_requirements('requirements.txt'),
Expand Down
14 changes: 7 additions & 7 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
[tox]
envlist =
flake8
py{36}-django20
py{36,37}-django21
py{36,37}-django22
py{36,37}-django30
py{36,37}-django31
py{36,37}-djangomaster

[testenv]
setenv =
DB = postgres
deps =
django20: Django>=2.0,<2.1
django21: Django>=2.1,<2.2
django22: Django>=2.2,<2.3
django22: Django>=2.2,<3.0
django30: Django>=3.0,<3.1
django31: Django>=3.1,<3.2
djangomaster: https://github.com/django/django/archive/master.tar.gz
-rrequirements/requirements-testing.txt
commands =
Expand All @@ -25,7 +25,7 @@ commands = flake8 entity_emailer

[travis:env]
DJANGO =
2.0: django20
2.1: django21
2.2: django22
3.0: django30
3.1: django31
master: djangomaster