Browse Source
Vyrábí odkazy, které vedou na poslání mailu. Psal jsem to spíš po paměti, nejsem si jistý, že to takhle je přesně podle příslušného RFC, ale jako PoC dobrý a když to nebude fungovat, tak se implementace opraví. Všimněte si, že to je otestované, takže když někdo opraví testy (=předpis chování), tak je pak snadné z diffu a všeho odvodit úpravu. V Django dokumentaci se píše něco o tom, že by se měl použít spíš `format_html` a `conditional_escape`, ale zatím jsem to víc nezkoumal. Je žádoucí z tagu {% maillink %} odddělit i tag {% mailurl %}, který by vracel samotnou URL. Obojí dává smysl umět (speciálně bastlení odkazů z URL je stejně strašně nepřehledné, takže je lepší to zavřít do {% maillink %} a nikdy nevidět), ale zatím to oddělené není… (Ale jsou na to testy, takže by se mělo aspoň dát poznat, že rozdělení nerozbije chování.)maillink_dev_ledoian^2
Pavel 'LEdoian' Turinsky
2 years ago
3 changed files with 72 additions and 1 deletions
@ -0,0 +1,30 @@ |
|||
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 maillink(text: str, subject=None, body=None, to=[], attrs=None): |
|||
"""TODO: Dokumentace""" |
|||
if isinstance(to, str): |
|||
to = [to] |
|||
assert isinstance(to, list) |
|||
parts = [ |
|||
f'mailto:{str.join(",", to)}', |
|||
] |
|||
if len(to) < 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(parts) > 1: |
|||
url = parts[0] + '?' + str.join('&', parts[1:]) |
|||
else: |
|||
url = parts[0] |
|||
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,44 @@ |
|||
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 |
|||
|
|||
# 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_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>', |
|||
) |
|||
|
Loading…
Reference in new issue