Tag pro odkazy na poslání mailu #22
5 changed files with 121 additions and 4 deletions
|
@ -1,6 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load deadliny %}
|
||||
{% load mail %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
@ -14,7 +15,14 @@
|
|||
|
||||
{% if edit %}
|
||||
<p>Řešitelé:
|
||||
{% for r in object.resitele.all %}{{ r }} (<a href="mailto:{{ r.osoba.email }}?subject={{ "Oprava řešení M&M " | urlencode }}{{ object.problem.all.0.hlavni_problem | urlencode }}">{{ r.osoba.email }}</a>){% if forloop.revcounter0 != 0 %}, {% endif %}{% endfor %}
|
||||
{% for r in object.resitele.all %}
|
||||
{{ r }}
|
||||
{# DjangoTemplates neumí spojovat řetězce (https://stackoverflow.com/q/4386168), tak si necháváme vyrobit subject mailu ve view. #}
|
||||
({% maillink r.osoba.email to=r.osoba.email subject=predmetmailu %}){% if forloop.revcounter0 != 0 %}, {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
<p>
|
||||
{% maillink "Poslat mail všem řešitelům" bcc=maily_vsech_resitelu subject=predmetmailu %}
|
||||
</p>
|
||||
{% else %}
|
||||
<p>Řešitelé: {{ object.resitele.all | join:", " }}</p>
|
||||
|
|
|
@ -235,8 +235,12 @@ class DetailReseniView(DetailView):
|
|||
def get_context_data(self, **kw):
|
||||
self.check_access()
|
||||
ctx = super().get_context_data(**kw)
|
||||
hodnoceni = self.aktualni_hodnoceni()
|
||||
ctx["hodnoceni"] = hodnoceni
|
||||
detaily_hodnoceni = self.aktualni_hodnoceni()
|
||||
ctx["hodnoceni"] = detaily_hodnoceni
|
||||
|
||||
# Subject případného mailu (template neumí použitelně spojovat řetězce: https://stackoverflow.com/q/4386168)
|
||||
ctx["predmetmailu"] = "Oprava řešení M&M "+self.reseni.problem.first().hlavni_problem.nazev
|
||||
ctx["maily_vsech_resitelu"] = [y for x in self.reseni.resitele.all().values_list('osoba__email') for y in x]
|
||||
return ctx
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
|
0
various/templatetags/__init__.py
Normal file
0
various/templatetags/__init__.py
Normal file
48
various/templatetags/mail.py
Normal file
48
various/templatetags/mail.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
from urllib.request import quote as urlencode
|
||||
register = template.Library()
|
||||
|
||||
@register.simple_tag
|
||||
def mailurl(*, subject=None, body=None, to=[], cc=[], bcc=[]):
|
||||
"""Tag na vytváření správně zakódované mailto: adresy
|
||||
|
||||
Ref: RFC 6068, <https://en.wikipedia.org/wiki/Mailto>"""
|
||||
if isinstance(to, str):
|
||||
to = [to]
|
||||
if isinstance(cc, str):
|
||||
cc = [cc]
|
||||
if isinstance(bcc, str):
|
||||
bcc = [bcc]
|
||||
assert isinstance(to, list)
|
||||
assert isinstance(cc, list)
|
||||
assert isinstance(bcc, list)
|
||||
# FIXME: adresa není správně zakódovaná, rozbije se to na adresách s divnými znaky
|
||||
parts = [
|
||||
f'mailto:{str.join(",", to)}',
|
||||
]
|
||||
if len(to) + len(cc) + len(bcc) < 1:
|
||||
raise ValueError('Cannot mail to empty set of people')
|
||||
|
||||
if subject:
|
||||
parts.append(f'subject={urlencode(subject)}')
|
||||
if body:
|
||||
parts.append(f'body={urlencode(body)}')
|
||||
if len(cc) > 0:
|
||||
parts.append(f'cc={str.join(",", cc)}')
|
||||
if len(bcc) > 0:
|
||||
parts.append(f'bcc={str.join(",", bcc)}')
|
||||
|
||||
if len(parts) > 1:
|
||||
url = parts[0] + '?' + str.join('&', parts[1:])
|
||||
else:
|
||||
url = parts[0]
|
||||
return url
|
||||
|
||||
@register.simple_tag
|
||||
def maillink(text, subject=None, body=None, to=[], cc=[], bcc=[], attrs=None):
|
||||
url = mailurl(subject=subject, body=body, to=to, cc=cc, bcc=bcc)
|
||||
if not attrs: attrs = ''
|
||||
mezera = ' '*bool(attrs)
|
||||
full_link = f'<a href="{url}"{mezera}{attrs}>{text}</a>'
|
||||
return mark_safe(full_link)
|
|
@ -1,3 +1,60 @@
|
|||
from django.test import TestCase
|
||||
# TODO: Možná vyrobit separátní soubory v tests/… než mít všechny testy v jednom souboru?
|
||||
from various.templatetags.mail import maillink, mailurl
|
||||
|
||||
# Create your tests here.
|
||||
class MailTagsTest(TestCase):
|
||||
"""Testuje template tagy ohledně mailů."""
|
||||
def test_maillink(self):
|
||||
# Tohle nedává smysl dělit do víc funkcí, bylo by v nich víc boilerplatu než užitečného kódu.
|
||||
self.assertEquals(maillink('Hello', to='some@body.test'), r'<a href="mailto:some@body.test">Hello</a>')
|
||||
self.assertEquals(maillink('Hello', to=['some@body.test']), r'<a href="mailto:some@body.test">Hello</a>')
|
||||
self.assertEquals(
|
||||
maillink('Hello', to=['alice@test.test', 'bob@jinde.test']),
|
||||
r'<a href="mailto:alice@test.test,bob@jinde.test">Hello</a>',
|
||||
)
|
||||
self.assertEquals(
|
||||
maillink('Hello', to='some@body.test', attrs='class="trida" id="id"'),
|
||||
r'<a href="mailto:some@body.test" class="trida" id="id">Hello</a>',
|
||||
)
|
||||
# Následující test toho testuje moc zároveň, měly by předcházet dedikované testy… (kašlu na ně :-P)
|
||||
self.assertEquals(
|
||||
maillink('Text odkazu', to='prijemce@wtf.test', subject="Předmět", body="Čau"),
|
||||
r'<a href="mailto:prijemce@wtf.test?subject=P%C5%99edm%C4%9Bt&body=%C4%8Cau">Text odkazu</a>',
|
||||
)
|
||||
self.assertRaises(ValueError, lambda: maillink('Nemám příjemce'))
|
||||
self.assertRaises(TypeError, lambda: maillink()) # Nemá text, takže to shodí python
|
||||
|
||||
def test_mailurl(self):
|
||||
self.assertEquals(mailurl(to='some@body.test'), r'mailto:some@body.test')
|
||||
self.assertEquals(mailurl(to=['some@body.test']), r'mailto:some@body.test')
|
||||
self.assertEquals(mailurl(to=['alice@test.test', 'bob@jinde.test']), r'mailto:alice@test.test,bob@jinde.test')
|
||||
self.assertEquals(
|
||||
mailurl(to='some@body.test', body='Tělo', subject='Předmět'),
|
||||
r'mailto:some@body.test?subject=P%C5%99edm%C4%9Bt&body=T%C4%9Blo',
|
||||
)
|
||||
self.assertRaises(ValueError, lambda: mailurl())
|
||||
|
||||
def test_render_in_template(self):
|
||||
# Pomocná funkce: vykreslí template do stringu
|
||||
# Ref: https://stackoverflow.com/a/1690879
|
||||
def render_template(template, context=None):
|
||||
from django.template import Template, Context
|
||||
context = context or {}
|
||||
context = Context(context)
|
||||
return Template(template).render(context)
|
||||
|
||||
template = (
|
||||
r'{% load mail %}'
|
||||
# TODO: Vyzkoušet i víc adresátů. (Nepamatuji si z hlavy syntaxi…)
|
||||
r'{% maillink "Text" to="alice@test.test" subject="Oprava řešení" %}'
|
||||
)
|
||||
self.assertEquals(
|
||||
render_template(template),
|
||||
r'<a href="mailto:alice@test.test?subject=Oprava%20%C5%99e%C5%A1en%C3%AD">Text</a>',
|
||||
)
|
||||
|
||||
mailurltemplate = (
|
||||
r'{% load mail %}'
|
||||
r'{% mailurl to="alice@test.test" subject="Čau Alice" %}'
|
||||
)
|
||||
self.assertEquals(render_template(mailurltemplate), r'mailto:alice@test.test?subject=%C4%8Cau%20Alice')
|
||||
|
|
Loading…
Reference in a new issue