2010-01-12 11 views
7

Wie wir alle wissen (oder sollte), können Sie Djangos Template-System verwenden, um E-Mail-Körper zu machen:Email Templat in django

def email(email, subject, template, context): 
    from django.core.mail import send_mail 
    from django.template import loader, Context 

    send_mail(subject, loader.get_template(template).render(Context(context)), '[email protected]', [email,]) 

Dies hat einen Fehler in meinem Kopf: das Thema und Inhalt eines bearbeiten E-Mail, müssen Sie sowohl die Ansicht als auch die Vorlage bearbeiten. Während ich rechtfertigen kann, Admin-Benutzern Zugriff auf die Templates zu geben, gebe ich ihnen keinen Zugriff auf den rohen Python!

Was wirklich cool wäre, wenn Sie Blöcke in der E-Mail angeben können, und ziehen Sie sie getrennt, wenn Sie die E-Mail senden:

{% block subject %}This is my subject{% endblock %} 
{% block plaintext %}My body{% endblock%} 
{% block html %}My HTML body{% endblock%} 

Aber wie würden Sie das tun? Wie würdest du nur einen Block nach dem anderen rendern?

Antwort

11

Dies ist meine dritte Arbeitsiteration. Es vorausgesetzt, Sie eine E-Mail-Vorlage haben etwa so:

{% block subject %}{% endblock %} 
{% block plain %}{% endblock %} 
{% block html %}{% endblock %} 

ich Refactoring habe die E-Mail iterieren eine Liste von Standard-Senden über und es gibt nützliche Methoden für die auf eine einzelne E-Mail zu senden und django.contrib.authUser s (Einzel- und Mehrfach). Ich bedecke vielleicht mehr, als ich vernünftig brauche, aber da gehst du.

Ich könnte auch mit Python-Liebe über die Spitze gegangen sein.

def email_list(to_list, template_path, context_dict): 
    from django.core.mail import send_mail 
    from django.template import loader, Context 

    nodes = dict((n.name, n) for n in loader.get_template(template_path).nodelist if n.__class__.__name__ == 'BlockNode') 
    con = Context(context_dict) 
    r = lambda n: nodes[n].render(con) 

    for address in to_list: 
     send_mail(r('subject'), r('plain'), '[email protected]', [address,]) 

def email(to, template_path, context_dict): 
    return email_list([to,], template_path, context_dict) 

def email_user(user, template_path, context_dict): 
    return email_list([user.email,], template_path, context_dict) 

def email_users(user_list, template_path, context_dict): 
    return email_list([user.email for user in user_list], template_path, context_dict) 

Wie immer, wenn Sie das verbessern können, bitte tun.

+0

Well & * $ # me E-Mail zu vermeiden. Es klappt. Berücksichtigen Sie, dass der Basis mehr Felder hinzugefügt werden, um die Einstellung von/from-name/reply-to zu ermöglichen. – Oli

+0

Hah, ich mache das mit drei verschiedenen Vorlagen, was ein PITA ist. Definitiv +1 von mir! –

+0

Ich mag es. Ich habe immer nur separate Templates verwendet, was gut funktioniert, aber das ist viel schöner zu handhaben (zumal du sowieso immer den gleichen Kontext für alle Templates willst). –

0

Verwenden Sie einfach zwei Vorlagen: eine für den Körper und eine für das Thema.

+0

Zwei Dateien bedeutet zwei Dateinamen für im Wesentlichen die gleiche Sache. Es ist nur ein Schmerz im Hinterteil, dass man auf den vielen Vorlagen bleiben muss. – Oli

0

ich nicht Vorlage Vererbung arbeiten mit den {% body %} Tags bekommen konnte, so wechselte ich zu einer Vorlage wie folgt aus:

{% extends "base.txt" %} 

{% if subject %}Subject{% endif %} 
{% if body %}Email body{% endif %} 
{% if html %}<p>HTML body</p>{% endif %} 

Jetzt müssen wir die Vorlage dreimal machen, aber die Vererbung funktioniert.

c = Context(context, autoescape = False) 
subject = render_to_string(template_name, {'subject': True}, c).strip() 
body = render_to_string(template_name, {'body': True}, c).strip() 
c = Context(context, autoescape = True) 
html = render_to_string(template_name, {'html': True}, c).strip() 

Ich fand es auch notwendig, autoescape auszuschalten, wenn die Nicht-HTML-Text-Rendering zu entkommen Text in der