Closed jhagege closed 9 years ago
You could do something like this:
from emailtools import HTMLEmail
class ThingCreatedAdminEmail(HTMLEmail):
template_name = 'things/mail/thing_created_admin.html'
subject = "New Thing Created"
def __init__(self, thing, request):
self.thing = thing
self.request = request
def get_to(self):
return [user.email for user in User.objects.filter(is_superuser=True)]
def get_context_data(self, **kwargs):
kwargs = super(ThingCreatedAdminEmail, self).get_context_data(**kwargs)
kwargs.update(
thing=self.thing,
request=self.request,
)
return kwargs
Then when you want to send your emails, you can do so like this:
def view(request):
# ...
email = ThingCreatedAdminEmail(thing, request=request)
email.send()
# ...
Another thing you can do is use the BuildAbsoluteURIMixin
mixin to build URLs, but it's not that user-friendly because you can't use it in the templates, here's an example usage:
from emailtools import HTMLEmail
from emailtools.cbe.mixins import BuildAbsoluteURIMixin
class ThingCreatedAdminEmail(BuildAbsoluteURIMixin, HTMLEmail):
template_name = 'things/mail/thing_created_admin.html'
subject = "New Thing Created"
def __init__(self, thing):
self.thing = thing
def get_to(self):
return [user.email for user in User.objects.filter(is_superuser=True)]
def get_context_data(self, **kwargs):
kwargs = super(ThingCreatedAdminEmail, self).get_context_data(**kwargs)
kwargs.update(
thing=self.thing,
detail_link=self.build_absolute_uri(self.thing.get_absolute_url()),
admin_link=self.reverse_absolute_uri('admin:things_thing_change', args=(self.thing.pk,)),
)
return kwargs
send_thing_created_admin_email = ThingCreatedAdminEmail.as_callable()
The template could just output using {{ detail_link }}
or {{ admin_link }}
. This has the benefit of not needing the request. This is useful if you are sending emails when you don't have a request (like from a cron job), however, it does require you to set your django.contrib.sites
up correctly.
If you wanted to send emails from a cron job, but still reverse the URLs in the template using something like absolute_uri
, here's an implementation that uses the django.contrib.sites
framework:
# myapp/templatetags/absolute_uri.py
from django import template
from django.core import urlresolvers
from django.contrib.sites.models import Site
register = template.Library()
def build_absolute_uri(path):
site = Site.objects.get_current()
return '{protocol}://{domain}{path}'.format(
protocol='http',
domain=site.domain,
path=path
)
@register.simple_tag
def absolute_uri(view_name, *args, **kwargs):
"""Reverse a URL and make it absolute."""
path = urlresolvers.reverse(view_name, args=args, kwargs=kwargs)
return build_absolute_uri(path)
@register.simple_tag
def absolutize(path):
"""Turn a relative URL into an absolute URL."""
return build_absolute_uri(path)
(I modified this code before posting it, so I haven't tested it, but it's based on something that I've used before.)
I hope this answers your question. I am going to go ahead and close the issue. Please feel free to keep discussing this if you need some more clarification.
Thank you so much for your thorough explanations, it proves very useful, and thanks again for this great package. It helps me understand better some OOP concepts in Python / Django.
Regards.
Thanks @cyberjoac, if you have any more questions, feel free to keep asking!
And just a small follow-up @cyberjoac.
I would really recommend using a pattern that doesn't involve needing the request
object to send your emails. By doing so, you've forced yourself into a corner where you always need a request object to trigger an email, meaning that you can't do things like sending them asynchronously with cron/celery, or even triggering them manually via the command line.
I wrapped that pattern I mentioned in the previous comment up in a django package, you can get it from PyPI:
LOVE IT!
Thanks a lot!!!
Hi guys,
I've been playing around with your package and making progress with it.
I am now stuck with a particular issue: I am using another third-party package that needs access to the context['request'] when trying to render the absolute url path of elements that I put inside the template (such as in {% absolute_url 'functionfoo' %} but for some reason I get an error thrown when trying to access the context['request'] inside this template tag.
It looks like the HtmlEmail class doesn't pass the request object inside the context. What would be the best way to go to include it? I guess I would have somehow to pass the context whenever creating an HTMLEmail().
Thanks a lot for your help.