[ x ]

Faig servir les cookies de Google Analytics per al control de visites i estadístiques..
És una pardalada, però la llei diu que us he d'avisar, ja veus. Així que si visitau aquest blog donau-vos per informats o sortiu ara mateix i netejau les cookies del vostre navegador. Si continuau llegint, suposaré que ja us està bé. Si vols saber com llevar les cookies del teu navegador: aquí ho pots trobar

Mails amb Django - II

Enviar un e-mail fent servir plantilles Django

Com ja tots sabeu Django té un sistema de plantilles molt eficaç. Normalment les fem servir per mostrar l'html de les nostres aplicacions web, però no estan limitades a això, i com veurem les podem fer servir per generar els nostre correu.

La manera de fer-ho és fent servir render_to_string que podem trobar a django.template.loader. Aquesta funció agafa com a paràmetres el nom de la plantilla que volem fer servir i un diccionari amb els paràmetres que farem servir a la plantilla. Agafa un tercer paràmetre, que ha de ser de tipus Context, però que per als nostres objectius no la farem servir gaire.

Quan volem enviar un correu ho podem fer dins la vista, però sovint ho farem des de classes d'utilitat, el model o un formulari, on el request no està disponible. Per això hem de tenir em compte que la majoria de vegades no tindrem accés a les variables que normalment estan accessibles a les plantilles mitjançant el context processors. Així doncs que si el correu te links pensau que tot el que siguin referències a arxius i links forçosament necessiten de Sites, MEDIA_URL i STATIC_URL (o fer servir el tag {% static %} introduït a les darreres versions de Django.

Suposem doncs que tenim el seguent, dins una plantilla que hem anomenta newsletter.html i que tenim accessible dins els TEMPLATE_DIRS

Benvolgut {{user.get_fullname}},

No deixis de visitar les nostres ofertes a http://{{current_site}}/ofertes/

Salutacions,

--
info@{{current_site}}
http://{{current_site}}

I a la funció que genera el correu tendríem per exemple:

from django.contrib.sites.models import Site
from django.conf import settings
from django.template.loader import render_to_string
from django.core.mail import EmailMessage

def send_wellcome():
    """Envia un missatge als nostres usuaris"""
    current_site = Site.objects.get_current().domain
    context = {'current_site': current_site}
    for u in User.objects.all():
        context['user'] = u
        body = render_to_string('dos/newsletter.html', context)
        msg = EmailMessage(subject="hello",
        body = body,
        from_email="jo@apsl.net",
        to=['someuser@example.com'])
        msg.content_subtype = "html"
        msg.send()

Fixem-nos com context és un diccionari on li hem de passar totes les variables que utilitza la nostra plantilla. En aquests tipus de corrreus el més habitual és anar en pilot automàtica i fer servir les variables {{STATIC_URL}} o {{MEDIA_URL}} habituats a tenir-les accessibles gràcies als context_processors i trobar-nos que als nostres e-mails no es veuen les imatges. Així que a més de passar-les al context ens hem d'assegurar que es passen aquestes variables i a més que les urls es generen com a url absolutes.

Per això a la plantilla de Django podem fer servir la llibreria static i utilitzar els tags get_static_prefix i get_media_prefixper a generar les urls. Seria una cosa semblant a

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}
{% get_media_prefix as MEDI_PREFIX %}

<img src="http://{{current_site}}/{{STATIC_PREFIX}}/img/log.jpg" alt="logo" />
<img scr="http://{{current_site}}/{{MEDIA_PREFIX}}/profile/{{foto}}" alt="foot pujada" />

No fa falta recordar que a static hi posarem totes aquelles images, css, js, etc que formen part de l'estructura de l'aplicació i a media hi haurà totes aquelles imatges i continguts que puja l'usuari de la nostra aplicació.

Donat que hem utilitzat en render_to_string per a generar el cos del missatge, segur que a més d'un se li haurà acudit que podem fer el mateix amb el subject, doncs sí, si és necessari es pot fer i de fet es fa. Però això ja serà al proper article...

Comentaris
  1. Biel Frontera Biel Frontera on 27/03/2013 3:00 #

    Jo ho vaig implementar fa poc. Però no tenc les plantilles dins fitxers html, sinó que les tenc a base de dades. Vaig crear un objecte MailTemplate que té, entre d'altres, els camps subject, body i attachment.

    Així, per generar el body faig:
    body = Template(mailtemplate.body).render(context)

    És a dir, genera la plantilla des d'un string que està a base de dades (no sé si és el que venia a la tercera entrega ;) )

    Per generar el fitxer adjunt, sí que me'n vaig a cercar la plantilla a un fitxer. Després de fer el render, ho pas a pdf.
    Ara veig que podria haver utilitzat la funció render_to_string, enlloc de fer get_template + render.

    Tenc el codi aquí: https://github.com/bielfrontera/django-registration-jaem/blob/master/contacts/functions/mailtemplate.py

  2. aaloy aaloy on 28/03/2013 10:01 #

    La idea de tenir els templates a una base de dades la veritat és que no m'agrada gaire. Potser en el teu cas es deu a la necessitat de poder fer modificacions ràpid o de crear-ne moltes, però si no tens control de versions qualsevol cosa es fa mala de mantenir.

    M'agrada més tenir el codi fora de la base de dades i poder fer actualitzacions automàtiques.

    Després també hi ha una qüestió de rendiment, si envies molts mails, s'ha de consultar la BD cada vegada, obtenir el resultat, etc. Amb Django pots fer que les plantilles quedin en memòria.

Els pingbacks estan tancats.