def send_unsent_scheduled_emails(): """ Send out any scheduled emails that are unsent """ current_time = datetime.utcnow() email_medium = get_medium() to_send = Email.objects.filter( scheduled__lte=current_time, sent__isnull=True).select_related( 'event').prefetch_related('recipients') # Fetch the contexts of every event so that they may be rendered context_loader.load_contexts_and_renderers([e.event for e in to_send], [email_medium]) emails = [] for email in to_send: to_email_addresses = get_subscribed_email_addresses(email) if to_email_addresses: text_message, html_message = email.render(email_medium) message = create_email_message( to_emails=to_email_addresses, from_email=email.from_address or get_from_email_address(), subject=email.subject or extract_email_subject_from_html_content(html_message), text=text_message, html=html_message, ) emails.append(message) connection = mail.get_connection() connection.send_messages(emails) to_send.update(sent=current_time)
def run_worker(self, *args, **kwargs): current_time = datetime.utcnow() email_medium = get_medium() to_send = ( Email.objects.filter(scheduled__lte=current_time, sent__isnull=True) .select_related("event") .prefetch_related("recipients") ) # Fetch the contexts of every event so that they may be rendered context_loader.load_contexts_and_renderers([e.event for e in to_send], [email_medium]) default_from_email = get_from_email_address() emails = [] for email in to_send: to_email_addresses = get_subscribed_email_addresses(email) if to_email_addresses: text_message, html_message = email.render(email_medium) message = create_email_message( to_emails=to_email_addresses, from_email=email.from_address or default_from_email, subject=email.subject or extract_email_subject_from_html_content(html_message), text=text_message, html=html_message, ) emails.append(message) connection = mail.get_connection() connection.send_messages(emails) to_send.update(sent=current_time)
def test_multiple_render_targets_multiple_events(self): test_m1 = G(test_models.TestModel) test_m2 = G(test_models.TestModel) test_m3 = G(test_models.TestModel) test_fk_m1 = G(test_models.TestFKModel) test_fk_m2 = G(test_models.TestFKModel) s1 = G(models.Source) s2 = G(models.Source) rg1 = G(models.RenderingStyle) rg2 = G(models.RenderingStyle) medium1 = G(models.Medium, source=s1, rendering_style=rg1) medium2 = G(models.Medium, source=s2, rendering_style=rg2) cr1 = G(models.ContextRenderer, rendering_style=rg1, source=s1, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', } }) cr2 = G(models.ContextRenderer, rendering_style=rg2, source=s2, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', }, 'key2': { 'model_name': 'TestFKModel', 'app_name': 'tests', } }) e1 = G(models.Event, context={'key': test_m1.id, 'key2': 'haha'}, source=s1) e2 = G(models.Event, context={'key': [test_m2.id, test_m3.id]}, source=s1) e3 = G(models.Event, context={'key2': test_fk_m1.id, 'key': test_m1.id}, source=s2) e4 = G(models.Event, context={'key2': test_fk_m2.id}, source=s2) context_loader.load_contexts_and_renderers([e1, e2, e3, e4], [medium1, medium2]) self.assertEquals(e1.context, {'key': test_m1, 'key2': 'haha'}) self.assertEquals(e2.context, {'key': [test_m2, test_m3]}) self.assertEquals(e3.context, {'key2': test_fk_m1, 'key': test_m1}) self.assertEquals(e4.context, {'key2': test_fk_m2}) # Verify context renderers are put into the events properly self.assertEquals(e1._context_renderers, { medium1: cr1, }) self.assertEquals(e2._context_renderers, { medium1: cr1, }) self.assertEquals(e3._context_renderers, { medium2: cr2, }) self.assertEquals(e4._context_renderers, { medium2: cr2, })
def test_optimal_queries(self): fk1 = G(test_models.TestFKModel) fk11 = G(test_models.TestFKModel) fk2 = G(test_models.TestFKModel2) test_m1 = G(test_models.TestModel, fk=fk1, fk2=fk2) test_m1.fk_m2m.add(fk1, fk11) test_m2 = G(test_models.TestModel, fk=fk1, fk2=fk2) test_m2.fk_m2m.add(fk1, fk11) test_m3 = G(test_models.TestModel, fk=fk1, fk2=fk2) test_fk_m1 = G(test_models.TestFKModel) test_fk_m2 = G(test_models.TestFKModel) s1 = G(models.Source) s2 = G(models.Source) rg1 = G(models.RenderingStyle) rg2 = G(models.RenderingStyle) medium1 = G(models.Medium, source=s1, rendering_style=rg1) medium2 = G(models.Medium, source=s2, rendering_style=rg2) G(models.ContextRenderer, rendering_style=rg1, source=s1, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', 'select_related': ['fk'], } }) G(models.ContextRenderer, rendering_style=rg2, source=s2, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', 'select_related': ['fk2'], 'prefetch_related': ['fk_m2m'], }, 'key2': { 'model_name': 'TestFKModel', 'app_name': 'tests', } }) e1 = G(models.Event, context={'key': test_m1.id, 'key2': 'haha'}, source=s1) e2 = G(models.Event, context={'key': [test_m2.id, test_m3.id]}, source=s1) e3 = G(models.Event, context={'key2': test_fk_m1.id, 'key': test_m1.id}, source=s2) e4 = G(models.Event, context={'key2': test_fk_m2.id}, source=s2) with self.assertNumQueries(6): context_loader.load_contexts_and_renderers([e1, e2, e3, e4], [medium1, medium2]) self.assertEquals(e1.context['key'].fk, fk1) self.assertEquals(e2.context['key'][0].fk, fk1) self.assertEquals(e1.context['key'].fk2, fk2) self.assertEquals(e2.context['key'][0].fk2, fk2) self.assertEquals(set(e1.context['key'].fk_m2m.all()), set([fk1, fk11])) self.assertEquals(set(e2.context['key'][0].fk_m2m.all()), set([fk1, fk11])) self.assertEquals(e3.context['key'].fk, fk1)
def test_one_render_target_one_event_no_style_with_default(self): m1 = G(test_models.TestModel) s = G(models.Source) rs = G(models.RenderingStyle, name='short') e = G(models.Event, context={'key': m1.id}, source=s) medium = G(models.Medium, source=s, rendering_style=None) G(models.ContextRenderer, rendering_style=rs, source=s, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', } }) context_loader.load_contexts_and_renderers([e], [medium]) self.assertEquals(e.context, {'key': m1})
def render(self, events): """ Renders a list of events for this medium. The events first have their contexts loaded. Afterwards, the rendered events are returned as a dictionary keyed on the event itself. The key points to a tuple of (txt, html) renderings of the event. :type events: list :param events: A list or queryset of Event models. :rtype: dict :returns: A dictionary of rendered text and html tuples keyed on the provided events. """ from entity_event import context_loader context_loader.load_contexts_and_renderers(events, [self]) return {e: e.render(self) for e in events}
def load_contexts_and_renderers(self, medium): """ Loads context data into the event ``context`` variable. This method destroys the queryset and returns a list of events. """ from entity_event import context_loader return context_loader.load_contexts_and_renderers(self, [medium])
def send_unsent_scheduled_emails(): """ Send out any scheduled emails that are unsent """ current_time = datetime.utcnow() email_medium = get_medium() to_send = Email.objects.filter( scheduled__lte=current_time, sent__isnull=True ).select_related( 'event' ).prefetch_related( 'recipients' ) # Fetch the contexts of every event so that they may be rendered context_loader.load_contexts_and_renderers([e.event for e in to_send], [email_medium]) emails = [] for email in to_send: to_email_addresses = get_subscribed_email_addresses(email) if to_email_addresses: text_message, html_message = email.render(email_medium) message = create_email_message( to_emails=to_email_addresses, from_email=email.from_address or get_from_email_address(), subject=email.subject or extract_email_subject_from_html_content(html_message), text=text_message, html=html_message, ) emails.append(message) connection = mail.get_connection() connection.send_messages(emails) to_send.update(sent=current_time)
def test_none(self): context_loader.load_contexts_and_renderers([], [])
def get(self, request, *args, **kwargs): email = self.get_email() medium = get_medium() context_loader.load_contexts_and_renderers([email.event], [medium]) txt, html = email.render(medium) return HttpResponse(html if html else txt)
def test_multiple_render_targets_multiple_events_use_default(self): """ Tests the case when a context renderer is not available for a rendering style but the default style is used instead. """ test_m1 = G(test_models.TestModel) test_m2 = G(test_models.TestModel) test_m3 = G(test_models.TestModel) test_fk_m1 = G(test_models.TestFKModel) test_fk_m2 = G(test_models.TestFKModel) s1 = G(models.Source) s2 = G(models.Source) rs1 = G(models.RenderingStyle, name='short') rs2 = G(models.RenderingStyle) medium1 = G(models.Medium, rendering_style=rs1) medium2 = G(models.Medium, rendering_style=rs2) cr1 = G(models.ContextRenderer, rendering_style=rs1, source=s1, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', } }) cr2 = G(models.ContextRenderer, rendering_style=rs1, source=s2, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', }, 'key2': { 'model_name': 'TestFKModel', 'app_name': 'tests', } }) e1 = G(models.Event, context={ 'key': test_m1.id, 'key2': 'haha' }, source=s1) e2 = G(models.Event, context={'key': [test_m2.id, test_m3.id]}, source=s1) e3 = G(models.Event, context={ 'key2': test_fk_m1.id, 'key': test_m1.id }, source=s2) e4 = G(models.Event, context={'key2': test_fk_m2.id}, source=s2) context_loader.load_contexts_and_renderers([e1, e2, e3, e4], [medium1, medium2]) self.assertEquals(e1.context, {'key': test_m1, 'key2': 'haha'}) self.assertEquals(e2.context, {'key': [test_m2, test_m3]}) self.assertEquals(e3.context, {'key2': test_fk_m1, 'key': test_m1}) self.assertEquals(e4.context, {'key2': test_fk_m2}) # Verify context renderers are put into the events properly self.assertEquals(e1._context_renderers, { medium1: cr1, medium2: cr1, }) self.assertEquals(e2._context_renderers, { medium1: cr1, medium2: cr1, }) self.assertEquals(e3._context_renderers, { medium1: cr2, medium2: cr2, }) self.assertEquals(e4._context_renderers, { medium1: cr2, medium2: cr2, })
def test_optimal_queries(self): fk1 = G(test_models.TestFKModel) fk11 = G(test_models.TestFKModel) fk2 = G(test_models.TestFKModel2) test_m1 = G(test_models.TestModel, fk=fk1, fk2=fk2) test_m1.fk_m2m.add(fk1, fk11) test_m2 = G(test_models.TestModel, fk=fk1, fk2=fk2) test_m2.fk_m2m.add(fk1, fk11) test_m3 = G(test_models.TestModel, fk=fk1, fk2=fk2) test_fk_m1 = G(test_models.TestFKModel) test_fk_m2 = G(test_models.TestFKModel) s1 = G(models.Source) s2 = G(models.Source) rg1 = G(models.RenderingStyle) rg2 = G(models.RenderingStyle) medium1 = G(models.Medium, source=s1, rendering_style=rg1) medium2 = G(models.Medium, source=s2, rendering_style=rg2) G(models.ContextRenderer, rendering_style=rg1, source=s1, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', 'select_related': ['fk'], } }) G(models.ContextRenderer, rendering_style=rg2, source=s2, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', 'select_related': ['fk2'], 'prefetch_related': ['fk_m2m'], }, 'key2': { 'model_name': 'TestFKModel', 'app_name': 'tests', } }) e1 = G(models.Event, context={ 'key': test_m1.id, 'key2': 'haha' }, source=s1) e2 = G(models.Event, context={'key': [test_m2.id, test_m3.id]}, source=s1) e3 = G(models.Event, context={ 'key2': test_fk_m1.id, 'key': test_m1.id }, source=s2) e4 = G(models.Event, context={'key2': test_fk_m2.id}, source=s2) with self.assertNumQueries(6): context_loader.load_contexts_and_renderers([e1, e2, e3, e4], [medium1, medium2]) self.assertEquals(e1.context['key'].fk, fk1) self.assertEquals(e2.context['key'][0].fk, fk1) self.assertEquals(e1.context['key'].fk2, fk2) self.assertEquals(e2.context['key'][0].fk2, fk2) self.assertEquals(set(e1.context['key'].fk_m2m.all()), set([fk1, fk11])) self.assertEquals(set(e2.context['key'][0].fk_m2m.all()), set([fk1, fk11])) self.assertEquals(e3.context['key'].fk, fk1)
def test_multiple_render_targets_multiple_events(self): test_m1 = G(test_models.TestModel) test_m2 = G(test_models.TestModel) test_m3 = G(test_models.TestModel) test_fk_m1 = G(test_models.TestFKModel) test_fk_m2 = G(test_models.TestFKModel) s1 = G(models.Source) s2 = G(models.Source) rg1 = G(models.RenderingStyle) rg2 = G(models.RenderingStyle) medium1 = G(models.Medium, source=s1, rendering_style=rg1) medium2 = G(models.Medium, source=s2, rendering_style=rg2) cr1 = G(models.ContextRenderer, rendering_style=rg1, source=s1, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', } }) cr2 = G(models.ContextRenderer, rendering_style=rg2, source=s2, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', }, 'key2': { 'model_name': 'TestFKModel', 'app_name': 'tests', } }) e1 = G(models.Event, context={ 'key': test_m1.id, 'key2': 'haha' }, source=s1) e2 = G(models.Event, context={'key': [test_m2.id, test_m3.id]}, source=s1) e3 = G(models.Event, context={ 'key2': test_fk_m1.id, 'key': test_m1.id }, source=s2) e4 = G(models.Event, context={'key2': test_fk_m2.id}, source=s2) context_loader.load_contexts_and_renderers([e1, e2, e3, e4], [medium1, medium2]) self.assertEquals(e1.context, {'key': test_m1, 'key2': 'haha'}) self.assertEquals(e2.context, {'key': [test_m2, test_m3]}) self.assertEquals(e3.context, {'key2': test_fk_m1, 'key': test_m1}) self.assertEquals(e4.context, {'key2': test_fk_m2}) # Verify context renderers are put into the events properly self.assertEquals(e1._context_renderers, { medium1: cr1, }) self.assertEquals(e2._context_renderers, { medium1: cr1, }) self.assertEquals(e3._context_renderers, { medium2: cr2, }) self.assertEquals(e4._context_renderers, { medium2: cr2, })
def test_no_mediums(self): e = G(models.Event, context={}) context_loader.load_contexts_and_renderers([e], []) self.assertEquals(e.context, {})
def test_multiple_render_targets_multiple_events_use_default(self): """ Tests the case when a context renderer is not available for a rendering style but the default style is used instead. """ test_m1 = G(test_models.TestModel) test_m2 = G(test_models.TestModel) test_m3 = G(test_models.TestModel) test_fk_m1 = G(test_models.TestFKModel) test_fk_m2 = G(test_models.TestFKModel) s1 = G(models.Source) s2 = G(models.Source) rs1 = G(models.RenderingStyle, name='short') rs2 = G(models.RenderingStyle) medium1 = G(models.Medium, rendering_style=rs1) medium2 = G(models.Medium, rendering_style=rs2) cr1 = G(models.ContextRenderer, rendering_style=rs1, source=s1, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', } }) cr2 = G(models.ContextRenderer, rendering_style=rs1, source=s2, context_hints={ 'key': { 'model_name': 'TestModel', 'app_name': 'tests', }, 'key2': { 'model_name': 'TestFKModel', 'app_name': 'tests', } }) e1 = G(models.Event, context={'key': test_m1.id, 'key2': 'haha'}, source=s1) e2 = G(models.Event, context={'key': [test_m2.id, test_m3.id]}, source=s1) e3 = G(models.Event, context={'key2': test_fk_m1.id, 'key': test_m1.id}, source=s2) e4 = G(models.Event, context={'key2': test_fk_m2.id}, source=s2) context_loader.load_contexts_and_renderers([e1, e2, e3, e4], [medium1, medium2]) self.assertEquals(e1.context, {'key': test_m1, 'key2': 'haha'}) self.assertEquals(e2.context, {'key': [test_m2, test_m3]}) self.assertEquals(e3.context, {'key2': test_fk_m1, 'key': test_m1}) self.assertEquals(e4.context, {'key2': test_fk_m2}) # Verify context renderers are put into the events properly self.assertEquals(e1._context_renderers, { medium1: cr1, medium2: cr1, }) self.assertEquals(e2._context_renderers, { medium1: cr1, medium2: cr1, }) self.assertEquals(e3._context_renderers, { medium1: cr2, medium2: cr2, }) self.assertEquals(e4._context_renderers, { medium1: cr2, medium2: cr2, })