You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.3 KiB

"""
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
4 months ago
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
4 months ago
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í view jakožto funkce, takže u class-based views se 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
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