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