--
Ticket URL: <https://code.djangoproject.com/ticket/17193>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 1
* needs_docs: => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:1>
* stage: Unreviewed => Accepted
Comment:
Yes, I think Django could provide this feature.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:2>
Comment (by julianapplebaum):
I'm new to to the django dev community, and was hoping to write some unit
tests for this shortcut. Should I claim the ticket before doing that?
Sorry if this isn't the right place to be asking that.
- Julian Applebaum
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:3>
Comment (by aaugustin):
Yes, you should assign the ticket to yourself if you intend to work on it.
You'll find more information about our development process in the
[https://docs.djangoproject.com/en/dev/internals/contributing/
contributing guide].
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:4>
* needs_docs: 1 => 0
Comment:
Updated the patch to include documentation.
Also tweaked the API slightly - the email connection and message sending
has been decoupled from the message generation, and I've made some tweaks
to the arguments that `send_templated_mail` takes.
I think this should pretty much hit the sweet spot of making sure the
shortcut interface isn't overly complicated, whilst still providing for
the common case.
Julian - That'd be great. Feel free to get in touch with me off-list if
there's anything I can do to help with that - t...@tomchristie.com.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:5>
Comment (by tomchristie):
Added some extra documentation in the existing email section, referring to
the shortcut.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:6>
* status: new => assigned
* owner: nobody => julianapplebaum
Comment:
Replying to [comment:4 aaugustin]:
> Yes, you should assign the ticket to yourself if you intend to work on
it.
>
> You'll find more information about our development process in the
[https://docs.djangoproject.com/en/dev/internals/contributing/
contributing guide].
Thanks, and will do. Should have the patch up by Sunday night.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:7>
Comment (by anonymous):
Quick status update:
It took me and the group I'm with longer than anticipated to get
everything up and running. We've written a few unit tests for
_render_mail, and aim to finish the rest this coming week. We apologize
for the delay.
Julian
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:8>
Comment (by tomchristie):
> We apologize for the delay.
Nothing to apologize for, it's a community effort - everything's
appreciated. :)
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:9>
Comment (by tevans.uk@…):
I have a few doubts about how this has been designed. With both html and
plain 'templates' actually just being blocks of a single template, it is
not possible to use template inheritance to design consistent emails,
which is a common use of the template system. Without this, styles would
need to be replicated across multiple templates.
In our send_mail wrapper at $JOB, we allow the user to pass in the stub
name of a template. The utility then attempts to render the templates
stub+'.html' and stub+'.txt', and uses the results of these to determine
whether we send a text/plain, text/html or multipart/alternative.
Instead of extracting the subject from a template, we allow it to be
passed in directly. We also add a language argument, which is used to
activate the appropriate translation prior to rendering the emails, or
coercing the subject to unicode. This allows us to send fully translated
emails appropriate for the user receiving the email - which may not be the
same as the language currently activated, if there is any, or the language
that has been activated for the current view.
Cheers
Tom (one of these days I'll remember my trac login)
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:10>
Comment (by tomchristie):
It's not quite true that you can't use template inheritance with this
style, although I've come around to thinking that it probably is a an
abuse of the 'block' tags to change their semantics for email templates.
I don't like the stub+'.txt', stub+'.html' for 2 reasons:
Firstly it's very easy for the two separate files to get out of sync, with
no easy way of noticing that's happened.
Secondly the stub + extension style isn't used anywhere else.
I think a better solution would be a single template and a flag to switch
between plaintext only, or html + autogenerated plaintext.
It's not impossible that I might get a spare couple of hours between now
and the 1.4 checkin deadline, but it's not looking all that likely, so may
have to defer this to 1.5.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:11>
Comment (by julianapplebaum):
Hey Everyone
Just uploaded the diff file for my group's unit tests. Let me know if you
run into any issues with the tests/the diff file, etc.
Best,[[BR]]
Julian
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:12>
Comment (by anonymous):
Thanks Julian,
There may be some redesign needed of this feature, but either way those
tests look fairly comprehensive - should come in useful.
Tom
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:13>
* needs_tests: 1 => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:14>
* stage: Accepted => Design decision needed
Comment:
Thank you all for your great work on this patch. However, I'm struggling a
bit to see the value of adding this much new code for something that is
already quite easily achievable using `render_to_string()` and separate
templates.
I do agree that creating html+plain emails is still a little too hard in
Django, but in my opinion this could be simplified by introducing a new
helper class wrapping around `EmailMultiAlternatives` and providing a
simpler API and sensible defaults. For example, something like:
`HTMLEmailMessage(body_plain='...', body_html='...')`
In any case, I personally think that any template rendering should be left
to the user to do separately (for example by using `render_to_string()`).
For now I'm marking this ticket as DDN instead of wontfixing so that more
discussion can occur.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:15>
Comment (by anonymous):
Agreed that this isn't quite the right way to approach it.
I still think a `send_templated_email`, makes a lot of sense, but I've not
had time to revisit this yet and propose something simpler.
I'll take it to django-developers if and when that happens.
If anyone else takes this to the group first, please link to the
discussion from this ticket.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:16>
* cc: streeter (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:17>
* cc: artem.rizhov@… (added)
Comment:
Hi there!
Replying to [comment:15 julien]:
> I do agree that creating html+plain emails is still a little too hard in
Django, but in my opinion this could be simplified by introducing a new
helper class wrapping around `EmailMultiAlternatives` and providing a
simpler API and sensible defaults. For example, something like:
`HTMLEmailMessage(body_plain='...', body_html='...')`
My implementation is based on `EmailMultiAlternatives` :) It's available
at !GitHub https://github.com/artemrizhov/django-mail-templated
Actuall, for me it
I've emailed to django-developers mailing list and proposed to merge it
into Django. However my proposition was declined.
http://groups.google.com/group/django-
developers/browse_frm/thread/4728f20dd8023dd9
I'd be glad to continue work on it, but there is no any reason to polish
it more for a while. :( At least unless I need some additional
functionality, or some activity is registered on the github project. :)
Propositions and suggestions are welcome.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:18>
Comment (by artem.rizhov@…):
Ooops..[[BR]]
{{{s/Actuall, for me it //}}}[[BR]]
Sorry for trash in the message.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:19>
* cc: chuck-norris@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:20>
* needs_better_patch: 0 => 1
* needs_tests: 0 => 1
* stage: Design decision needed => Accepted
Comment:
Rendering a template is simple, but there are some minor gotchas in
templated email (like remembering to remove newlines from the rendered
subject template) that would be reasonable to put in a convenience
function in Django rather than requiring everyone to implement them
independently. And the `EmailMultiAlternatives` API is just enough
boilerplate to always require looking up in the docs.
IMO the blocks approach implemented above (both in the patch and the
linked external project) is too complex, too much code, and too unusual a
use of templates (blocks are for template inheritance, not a way to
combine multiple templates in one file.) I would rather favor a simple
extension naming convention (i.e. give `path/to/myemail` and it looks for
templates `path/to/myemail.txt`, `path/to/myemail.html`, and
`path/to/myemail.subject.txt`). I've attached a sample implementation of
this approach (not yet integrated as a patch to Django); it really isn't
very much code. (This implements a two-layer API, with both a
`send_multipart` function that accepts strings, and a
`send_templated_multipart` that does the template-finding and rendering.)
I guess I'm personally +0 or +0.5 on including something like this in
Django. I think it's a very common pattern that's just irritating enough
to re-implement to be worth considering for inclusion, but I won't mind at
all if another core dev decides to close this wontfix.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:21>
* needs_docs: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:22>
Comment (by artem.rizhov@…):
> too unusual a use of templates (blocks are for template inheritance, not
a way to combine multiple templates in one file.)
Maybe you are right. However 3 files per message is too many. It may be
hard and annoying to maintain so many files. And somebody may forget to
change one of templates.
And why you say "multiple templates"? Imho this is single template of
multipart message :) Let's add this at the top of template:
{{{
{% extends 'email/multipart.html' %}
}}}
Does it look better now? ;) We also may add 'email/text.html',
'email/html.html' and so on. This will make the template code looking more
usual.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:23>
Comment (by carljm):
If the implementation requires Python code pulling out the blocks from the
rendered template for individual specialized handling, then IMO it's a
misuse of template blocks and it should be separate templates instead. If
the hypothetical `email/multipart.html` base actually contained a full
template for a multipart message, that would be a reasonable use of
templates (but still not necessarily a good idea, as the template would
then be re-implementing things already handled by
`EmailMultiAlternatives`).
I don't buy the idea that maintaining three files is too hard. But for
people who feel that way, alternative approaches would always be available
as third-party packages. (Or we can just wontfix this and let all
implementations stay outside core, I'm fine with that too.)
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:24>
Comment (by anonymous):
> Or we can just wontfix this
Ok, you won :)
I hope it is possible to make both html and text vesrions not required.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:25>
* status: assigned => closed
* resolution: => duplicate
Comment:
Marking this as a duplicate of #20817 which added an `html_message`
parameter to `send_mail()`.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:26>
Comment (by anonymous):
timo, does `html_message` parameter allow django templates to be used?
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:27>
Comment (by charettes):
@anon yes, you could use the
[https://docs.djangoproject.com/en/dev/ref/templates/api/#the-render-to-
string-shortcut render_to_string] function to build the `html_message`
kwarg passed to `send_mail`.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:28>
* status: closed => new
* resolution: duplicate =>
Comment:
No, this does not close the original OPs request, and concept as mentioned
by Carl.
This ticket is to introduce a helper function of some sort to handle
`send_mail(render_to_string(...))`. It's just a helper function, it's
achievable without, but it's an exceedingly common pattern and personally
I'm +1 on having this. A significant number of projects I've worked on
have included a utility function named something like
`render_to_send_mail()`.
The exact API is up for discussion still, which is probably the blocker
for this ticket. As mentioned in #20817, it may be better as extension
around the `EmailMessage` or `EmailMultiAlternatives` APIs rather than
just as a helper function. I can see something like the following API
being useful:
{{{
message = TemplatedEmail(
from_email=...,
to=[...],
subject_template='my_email_subject.txt',
body_template='my_email_template.txt',
html_body_template='my_enhanced_email_template.html',
context=context,
)
message.send()
}}}
A functional approach to this could be added as well as a shortcut
function, though this is already significantly easier than the existing
APIs to do this. If we take Carl's earlier suggestion about a naming
convention, it becomes simpler, alternatively we could add complexity by
also supporting kwargs for `subject`, `body` and `html_body` which can
take rendered strings as alternatives.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:29>
* cc: cmawebsite@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:30>
Old description:
> If your sending email it's likely that you want to render the body text
> from template, but there's currently no shortcut to send an email based
> on a template.
>
> The attached patch is based on a stripped down version of
> https://github.com/bradwhittington/django-templated-email
>
> It adds `django.shortcuts.send_templated_mail`, which mirrors the
> existing `send_mail`, but which renders the subject and body of the mail
> from a template, rather than taking their values explicitly. It also
> supports multipart html/plaintext emails.
>
> The docs will look something like this...
>
> **send_templated_mail(template_name, from_email, recipient_list,
> dictionary=None, context_instance=None, fail_silently=False,
> auth_user=None, auth_password=None, connection=None):**
> Sends a mail, rendering the subject and body of the email from a
> template.
>
> The template should contain a block named 'subject', and either/both
> of a 'plain' and/or 'html' block.
>
> If only the 'plain' block exists, a plaintext email will be sent.
>
> If only the 'html' block exists, the plaintext component will be
> automatically generated from the html, and a multipart email will be
> sent.
>
> If both the 'plain' and 'html' blocks exist, a multipart email will
> be sent.
>
> **Required arguments:**
>
> `template_name` - The template that should be used to render the
> email.
>
> `from_email` - The sender's email address.
>
> `recipient_list` - A list of reciepient's email addresses.
>
> **Optional arguments:**
>
> `dictionary` - The context dictionary used to render the template. By
> default, this is an empty dictionary.
>
> `context_instance` - The Context instance used to render the
> template. By default, the template will be rendered with a Context
> instance (filled with values from dictionary).
>
> `fail_silently` - As in `send_mail`.
>
> `auth_user` - As in `send_mail`.
>
> `auth_password` - As in `send_mail`.
>
> `connection` - As in `send_mail`.
New description:
If your sending email it's likely that you want to render the body text
from template, but there's currently no shortcut to send an email based on
a template.
The attached patch is based on a stripped down version of
https://github.com/bradwhittington/django-templated-email
It adds `django.shortcuts.send_templated_mail`, which mirrors the existing
`send_mail`, but which renders the subject and body of the mail from a
template, rather than taking their values explicitly. It also supports
multipart html/plaintext emails.
The docs will look something like this...
{{{
**send_templated_mail(template_name, from_email, recipient_list,
dictionary=None, context_instance=None, fail_silently=False,
auth_user=None, auth_password=None, connection=None):**
Sends a mail, rendering the subject and body of the email from a
template.
The template should contain a block named 'subject', and either/both
of a 'plain' and/or 'html' block.
If only the 'plain' block exists, a plaintext email will be sent.
If only the 'html' block exists, the plaintext component will be
automatically generated from the html, and a multipart email will be sent.
If both the 'plain' and 'html' blocks exist, a multipart email will be
sent.
**Required arguments:**
`template_name` - The template that should be used to render the
email.
`from_email` - The sender's email address.
`recipient_list` - A list of reciepient's email addresses.
**Optional arguments:**
`dictionary` - The context dictionary used to render the template. By
default, this is an empty dictionary.
`context_instance` - The Context instance used to render the template.
By default, the template will be rendered with a Context instance (filled
with values from dictionary).
`fail_silently` - As in `send_mail`.
`auth_user` - As in `send_mail`.
`auth_password` - As in `send_mail`.
`connection` - As in `send_mail`.
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:31>
Comment (by carljm):
With the addition of the `html_message` parameter to `send_mail`, the
reasons for adding this have been reduced to:
1. Saving the need to type `render_to_string` two or three times.
2. Saving the need to collapse newlines in the rendered subject (though
I'm not actually sure off-hand what the consequence of failing to do that
is, would need to check).
That starts to look a bit thin as rationale, but it is a common enough
need that I'd probably still be at least +0 on adding it.
I think the naming-convention suggestion is probably a bit too implicit
for Django's usual API style; that's something probably better left to a
third-party solution.
So I think if we do this, the API should probably look something like what
Marc proposed.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:32>
Comment (by carljm):
Also, one more argument against the "single template and pull out blocks"
suggestion -- a single file with some portions that are HTML and some
portions that are text does not work well with editor modes and syntax
highlighting.
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:33>
Comment (by Jacob Rief):
Just in case someone wants to implement a template rendering system for
the email backend, I have added a templated based email renderer to
https://github.com/ui/django-post_office
--
Ticket URL: <https://code.djangoproject.com/ticket/17193#comment:34>