import http import tempfile import shutil import subprocess from pathlib import Path from django.http import HttpResponseForbidden, HttpResponse from django.shortcuts import render from django.views import generic from django.template.loader import render_to_string def csrf_error(request, reason=""): """ Jednoduchý „template view“ (třída to být nemůže) pro CSRF chyby """ return render( request, 'various/403_csrf.html', {"url": request.META.get("HTTP_REFERER", None), "reason": reason}, status=HttpResponseForbidden.status_code, ) 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 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 = "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, "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