108 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| Stejně jako je `django.views.generic` jsou zde generické Views
 | |
| a pár mixinů, které upravují chování Views.
 | |
| """
 | |
| 
 | |
| import http
 | |
| import shutil
 | |
| import subprocess
 | |
| import tempfile
 | |
| 
 | |
| from pathlib import Path
 | |
| 
 | |
| import django.views
 | |
| 
 | |
| from django.http import HttpResponse
 | |
| from django.shortcuts import render
 | |
| from django.template.loader import render_to_string
 | |
| from django.views import generic
 | |
| 
 | |
| 
 | |
| def viewMethodSwitch(get, post):
 | |
| 	"""
 | |
| 	Vrátí view, který zavolá různé jiné views podle toho, kterou metodou je zavolán.
 | |
| 
 | |
| 	Inspirováno https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#an-alternative-better-solution, jen jsem to udělal genericky.
 | |
| 
 | |
| 	Parametry:
 | |
| 		post	view pro metodu POST
 | |
| 		get	view pro metodu GET
 | |
| 
 | |
| 	V obou případech se míní už view jakožto funkce, takže u class-based views se už má použít .as_view()
 | |
| 
 | |
| 	TODO: Podpora i pro metodu HEAD? A možná i pro FILES?
 | |
| 	"""
 | |
| 
 | |
| 	theGetView = get
 | |
| 	thePostView = post
 | |
| 
 | |
| 	class NewView(django.views.View):
 | |
| 		def get(self, request, *args, **kwargs):
 | |
| 			return theGetView(request, *args, **kwargs)
 | |
| 
 | |
| 		def post(self, request, *args, **kwargs):
 | |
| 			return thePostView(request, *args, **kwargs)
 | |
| 
 | |
| 	return NewView.as_view()
 | |
| 
 | |
| 
 | |
| class NeprazdnyListView(generic.ListView):
 | |
| 	"""
 | |
| 		Použití jako generic.ListView, jen při prázdném listu vyhodí M&M stránku
 | |
| 		s titlem `self.if_prazdny_title` a textem `self.if_prazdny_text`
 | |
| 		a způsob renderování (např. CSV) lze změnit přepsáním metody render.
 | |
| 	"""
 | |
| 	allow_empty = False # Interní djangová věc
 | |
| 	if_prazdny_title = "V seznamu nic není"
 | |
| 	if_prazdny_text = "V seznamu nic není. Zkus to napravit v adminu, nebo se zeptej webařů."
 | |
| 
 | |
| 	# Skoro copy-paste generic.list.ListView.get,
 | |
| 	# protože nemůžu chytat 404, neboť může nastat i v get_context_data
 | |
| 	def get(self, request, *args, **kwargs):
 | |
| 		self.object_list = self.get_queryset()
 | |
| 
 | |
| 		if self.get_paginate_by(self.object_list) is not None and hasattr(
 | |
| 				self.object_list, "exists"
 | |
| 		):
 | |
| 			is_empty = not self.object_list.exists()
 | |
| 		else:
 | |
| 			is_empty = not self.object_list
 | |
| 		if is_empty:
 | |
| 			return render(request, 'universal.html', {
 | |
| 				'title': self.if_prazdny_title,
 | |
| 				'text': self.if_prazdny_text,
 | |
| 			}, status=http.HTTPStatus.NOT_FOUND)
 | |
| 
 | |
| 		return self.render(request, *args, **kwargs)
 | |
| 
 | |
| 	# Tohle jsem vyčlenil, aby šlo generovat i něco jiného než template
 | |
| 	def render(self, request, *args, **kwargs):
 | |
| 		context = self.get_context_data()
 | |
| 		return self.render_to_response(context)
 | |
| 
 | |
| 
 | |
| class TeXResponseMixin:
 | |
| 	"""
 | |
| 		Mixin pro TemplateView, aby výsledek projel TeXem a vrátil rovnou PDF.
 | |
| 		Obrázky a jiné soubory lze přidat nastavením `dalsi_potrebne_soubory`
 | |
| 		(např. na `[django.contrib.staticfiles.finders.find('bla')]`,
 | |
| 		nebo jiný seznam absolutních cest).
 | |
| 	"""
 | |
| 	dalsi_potrebne_soubory = []
 | |
| 	tex_prikaz = "pdflatex"
 | |
| 
 | |
| 	def render_to_response(self, context, **response_kwargs):
 | |
| 		zdrojak = render_to_string(self.get_template_names(), context)
 | |
| 
 | |
| 		with tempfile.TemporaryDirectory() as tempdirfn:
 | |
| 			tempdir = Path(tempdirfn)
 | |
| 			with open(tempdir / "main.tex", "w") as texfile:
 | |
| 				texfile.write(zdrojak)
 | |
| 			for file in self.dalsi_potrebne_soubory:
 | |
| 				shutil.copy(file, tempdir)
 | |
| 			subprocess.call([self.tex_prikaz, "main.tex"], cwd=tempdir, stdout=subprocess.DEVNULL)
 | |
| 
 | |
| 			with open(tempdir / "main.pdf", "rb") as pdffile:
 | |
| 				response = HttpResponse(pdffile.read(), content_type='application/pdf', **response_kwargs)
 | |
| 		return response
 | |
| 
 |