move: rozházení seminar.views.views_all
This commit is contained in:
parent
0fa3a2a077
commit
16cf18661a
10 changed files with 707 additions and 629 deletions
|
|
@ -20,6 +20,9 @@ urlpatterns = [
|
|||
# Seminarova aplikace (ma vlastni podadresare)
|
||||
path('', include('seminar.urls')),
|
||||
|
||||
# Obsahová plikace (ma vlastni podadresare)
|
||||
path('', include('tvorba.urls')),
|
||||
|
||||
# Odevzdavatko (ma vlastni podadresare)
|
||||
path('', include('odevzdavatko.urls')),
|
||||
|
||||
|
|
|
|||
|
|
@ -1,83 +1,21 @@
|
|||
"""
|
||||
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují.
|
||||
"""
|
||||
from django.urls import path, include, re_path
|
||||
from django.urls import path
|
||||
from . import views
|
||||
from personalni.views import AktivniOrganizatoriView, NeaktivniOrganizatoriStariView
|
||||
from personalni.utils import org_required
|
||||
|
||||
urlpatterns = [
|
||||
# path('aktualni/temata/', views.TemataRozcestnikView),
|
||||
# path('<int:rocnik>/t<int:tematko>/', views.TematkoView),
|
||||
|
||||
# Organizatori
|
||||
path('o-nas/organizatori/', AktivniOrganizatoriView.as_view(), name='organizatori'),
|
||||
path('o-nas/organizatori/organizovali/', NeaktivniOrganizatoriStariView.as_view(), name='stari_organizatori'),
|
||||
|
||||
# Archiv
|
||||
path('archiv/rocniky/', views.ArchivView.as_view(), name="seminar_archiv_rocniky"),
|
||||
path('archiv/temata/', views.ArchivTemataView.as_view(), name="seminar_archiv_temata"),
|
||||
|
||||
path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='seminar_rocnik'),
|
||||
path('cislo/<int:rocnik>.<str:cislo>/', views.CisloView.as_view(), name='seminar_cislo'),
|
||||
path('problem/<int:pk>/', views.problemView, name='seminar_problem'),
|
||||
|
||||
# Zadani
|
||||
# path('aktualni/zadani/', views.AktualniZadaniView.as_view(), name='seminar_aktualni_zadani'), # Dočasně ad-hoc jednoduchá věc.
|
||||
path('aktualni/zadani/', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
|
||||
#path('aktualni/temata/', views.ZadaniTemataView, name='seminar_temata'),
|
||||
path('aktualni/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_aktualni_vysledky'),
|
||||
path('aktualni/rocnik/', views.AktualniRocnikRedirectView.as_view(), name='seminar_aktualni_rocnik'),
|
||||
|
||||
# Clanky
|
||||
path('archiv/clanky/', views.ClankyResitelView.as_view(), name='clanky_resitel'),
|
||||
#path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'),
|
||||
|
||||
# Stranky viditelne pouze pro orgy:
|
||||
path(
|
||||
'rocnik/<int:rocnik>/vysledkovka.tex',
|
||||
org_required(views.RocnikVysledkovkaView.as_view()),
|
||||
name='seminar_rocnik_vysledkovka'
|
||||
),
|
||||
path(
|
||||
'rocnik/<int:rocnik>/resitele.csv',
|
||||
org_required(views.resiteleRocnikuCsvExportView),
|
||||
name='seminar_rocnik_resitele_csv'
|
||||
),
|
||||
path(
|
||||
'rocnik/<int:rocnik>/tituly.tex',
|
||||
org_required(views.TitulyViewRocnik),
|
||||
name='seminar_rocnik_titul'
|
||||
),
|
||||
path(
|
||||
'rocnik/<int:rocnik>/posledni_vysledkovka.tex',
|
||||
org_required(views.PosledniCisloVysledkovkaView.as_view()),
|
||||
name='seminar_rocnik_posledni_vysledkovka'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:rocnik>.<str:cislo>/vysledkovka.tex',
|
||||
org_required(views.CisloVysledkovkaView.as_view()),
|
||||
name='seminar_cislo_vysledkovka'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:rocnik>.<str:cislo>/obalky.pdf',
|
||||
org_required(views.cisloObalkyView),
|
||||
name='seminar_cislo_obalky'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:rocnik>.<str:cislo>/tituly.tex',
|
||||
org_required(views.TitulyView),
|
||||
name='seminar_cislo_titul'
|
||||
),
|
||||
path(
|
||||
'stav',
|
||||
org_required(views.StavDatabazeView),
|
||||
name='stav_databaze'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:trocnik>.<str:tcislo>/odmeny/<int:frocnik>.<str:fcislo>/',
|
||||
org_required(views.OdmenyView.as_view()),
|
||||
name="seminar_archiv_odmeny"),
|
||||
|
||||
path('', views.TitulniStranaView.as_view(), name='titulni_strana'),
|
||||
path('jak-resit/', views.JakResitView.as_view(), name='jak_resit'),
|
||||
|
|
@ -89,4 +27,5 @@ urlpatterns = [
|
|||
org_required(views.HromadnePridaniView.as_view()),
|
||||
name="hromadne_pridani"
|
||||
),
|
||||
path('problem/<int:pk>/', views.problemView, name='seminar_problem'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,218 +1,27 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.http import HttpResponse
|
||||
from django.urls import reverse
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.views import generic
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import Http404
|
||||
from django.db.models import Q, Sum, Count
|
||||
from django.views.generic.base import RedirectView
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
from treenode.treelib import get_parent
|
||||
from treenode.models import CisloNode
|
||||
from tvorba.models.problem import Problem
|
||||
from tvorba.models.tema import Tema
|
||||
from tvorba.models.clanek import Clanek
|
||||
from tvorba.models.nastaveni import Nastaveni
|
||||
from tvorba.models.rocnik import Rocnik
|
||||
from tvorba.models.cislo import Cislo
|
||||
from tvorba.models.deadline import Deadline
|
||||
from personalni.models.organizator import Organizator
|
||||
from personalni.models.resitel import Resitel
|
||||
from seminar.models.novinky import Novinky
|
||||
|
||||
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
|
||||
from treenode import treelib
|
||||
import treenode.templatetags as tnltt
|
||||
import treenode.serializers as vr
|
||||
from vysledkovky.utils import body_resitelu, VysledkovkaCisla, \
|
||||
VysledkovkaRocniku, VysledkovkaDoTeXu
|
||||
|
||||
from datetime import date, datetime
|
||||
from datetime import date
|
||||
from django.utils import timezone
|
||||
from itertools import groupby
|
||||
from collections import OrderedDict
|
||||
import tempfile
|
||||
import subprocess
|
||||
import shutil
|
||||
import os
|
||||
import os.path as op
|
||||
from django.conf import settings
|
||||
import unicodedata
|
||||
import time
|
||||
|
||||
# ze starého modelu
|
||||
#def verejna_temata(rocnik):
|
||||
# """
|
||||
# Vrací queryset zveřejněných témat v daném ročníku.
|
||||
# """
|
||||
# return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod')
|
||||
|
||||
|
||||
# FIXME: Pozor, níž je ještě jeden ProblemView!
|
||||
#class ProblemView(generic.DetailView):
|
||||
# model = s.Problem
|
||||
# # Zkopírujeme template_name od TreeNodeView, protože jsme prakticky jen trošku upravený TreeNodeView
|
||||
# template_name = TreeNodeView.template_name
|
||||
#
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# user = self.request.user
|
||||
# # Teď potřebujeme doplnit tnldata do kontextu.
|
||||
# # Ošklivý type switch, hezčí by bylo udělat to polymorfni. FIXME.
|
||||
# if False:
|
||||
# # Hezčí formátování zbytku :-P
|
||||
# pass
|
||||
# elif isinstance(self.object, s.Clanek) or isinstance(self.object, s.Konfera):
|
||||
# # Tyhle Problémy mají ŘešeníNode
|
||||
# context['tnldata'] = TNLData.from_treenode(self.object.reseninode,user)
|
||||
# elif isinstance(self.object, s.Uloha):
|
||||
# # FIXME: Teď vždycky zobrazujeme i vzorák! Možná by bylo hezčí/lepší mít to stejně jako pro Téma: procházet jen dosažitelné z Ročníku / čísla / whatever
|
||||
# tnl_zadani = TNLData.from_treenode(self.object.ulohazadaninode,user)
|
||||
# tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode,user)
|
||||
# context['tnldata'] = TNLData.from_tnldata_list([tnl_zadani, tnl_vzorak])
|
||||
# elif isinstance(self.object, s.Tema):
|
||||
# rocniknode = self.object.rocnik.rocniknode
|
||||
# context['tnldata'] = TNLData.filter_treenode(rocniknode, lambda x: isinstance(x, s.TemaVCisleNode))
|
||||
# else:
|
||||
# raise ValueError("Obecný problém nejde zobrazit.")
|
||||
# return context
|
||||
|
||||
|
||||
#class AktualniZadaniView(generic.TemplateView):
|
||||
# template_name = 'seminar/treenode.html'
|
||||
|
||||
# TODO Co chceme vlastně zobrazovat na této stránce? Zatím je zde aktuální číslo, ale může tu být cokoli jiného...
|
||||
#class AktualniZadaniView(TreeNodeView):
|
||||
# def get_object(self):
|
||||
# nastaveni = get_object_or_404(Nastaveni)
|
||||
# return nastaveni.aktualni_cislo.cislonode
|
||||
#
|
||||
# def get_context_data(self,**kwargs):
|
||||
# nastaveni = get_object_or_404(Nastaveni)
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# verejne = nastaveni.aktualni_cislo.verejne()
|
||||
# context['verejne'] = verejne
|
||||
# return context
|
||||
|
||||
def AktualniZadaniView(request):
|
||||
nastaveni = get_object_or_404(Nastaveni)
|
||||
verejne = nastaveni.aktualni_cislo.verejne()
|
||||
return render(request, 'seminar/zadani/AktualniZadani.html',
|
||||
{'nastaveni': nastaveni,
|
||||
'verejne': verejne,
|
||||
},
|
||||
)
|
||||
|
||||
def ZadaniTemataView(request):
|
||||
nastaveni = get_object_or_404(Nastaveni)
|
||||
verejne = nastaveni.aktualni_cislo.verejne()
|
||||
akt_rocnik = nastaveni.aktualni_cislo.rocnik
|
||||
temata = Tema.objects.filter(rocnik=akt_rocnik, stav='zadany')
|
||||
return render(request, 'seminar/tematka/rozcestnik.html',
|
||||
{
|
||||
'tematka': temata,
|
||||
'verejne': verejne,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
# nastaveni = get_object_or_404(Nastaveni)
|
||||
# temata = verejna_temata(nastaveni.aktualni_rocnik)
|
||||
# for t in temata:
|
||||
# if request.user.is_staff:
|
||||
# t.prispevky = t.prispevek_set.filter(problem=t)
|
||||
# else:
|
||||
# t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True)
|
||||
# return render(request, 'seminar/zadani/Temata.html',
|
||||
# {
|
||||
# 'temata': temata,
|
||||
# }
|
||||
# )
|
||||
#
|
||||
#
|
||||
#
|
||||
#def TematkoView(request, rocnik, tematko):
|
||||
# nastaveni = s.Nastaveni.objects.first()
|
||||
# rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik)
|
||||
# tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko)
|
||||
# seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode)
|
||||
# for node, depth in seznam:
|
||||
# if node.isinstance(node, s.KonferaNode):
|
||||
# raise Exception("Not implemented yet")
|
||||
# if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou
|
||||
# pass
|
||||
#
|
||||
# return render(request, 'seminar/tematka/toaletak.html', {})
|
||||
#
|
||||
#
|
||||
#def TemataRozcestnikView(request):
|
||||
# print("=============================================")
|
||||
# nastaveni = s.Nastaveni.objects.first()
|
||||
# tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik())
|
||||
# tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
|
||||
# for tematko_object in tematka_objects:
|
||||
# print("AKTUALNI TEMATKO")
|
||||
# print(tematko_object.id)
|
||||
# odkazy = vytahniZLesaSeznam(tematko_object, nastaveni.aktualni_rocnik().rocniknode, pouze_zajimave = True) #Odkazy jsou tuply (node, depth) v listu
|
||||
# print(odkazy)
|
||||
# cisla = [] # List tuplů (nazev cisla, list odkazů)
|
||||
# vcisle = []
|
||||
# cislo = None
|
||||
# for odkaz in odkazy:
|
||||
# if odkaz[1] == 0:
|
||||
# if cislo != None:
|
||||
# cisla.append((cislo, vcisle))
|
||||
# cislo = (odkaz[0].getOdkazStr(), odkaz[0].getOdkaz())
|
||||
# vcisle = []
|
||||
# else:
|
||||
# print(odkaz[0].getOdkaz())
|
||||
# vcisle.append((odkaz[0].getOdkazStr(), odkaz[0].getOdkaz()))
|
||||
# if cislo != None:
|
||||
# cisla.append((cislo, vcisle))
|
||||
#
|
||||
# print(cisla)
|
||||
# tematka.append({
|
||||
# "kod" : tematko_object.kod,
|
||||
# "nazev" : tematko_object.nazev,
|
||||
# "abstrakt" : tematko_object.abstrakt,
|
||||
# "obrazek": tematko_object.obrazek,
|
||||
# "cisla" : cisla
|
||||
# })
|
||||
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
|
||||
#
|
||||
|
||||
def ZadaniAktualniVysledkovkaView(request):
|
||||
nastaveni = get_object_or_404(Nastaveni)
|
||||
# Aktualni verejna vysledkovka
|
||||
rocnik = nastaveni.aktualni_rocnik
|
||||
context = {'vysledkovka': VysledkovkaRocniku(rocnik, True)}
|
||||
|
||||
# kdyz neni verejna vysledkovka, tak zobraz starou
|
||||
if len(context['vysledkovka'].cisla_rocniku) == 0:
|
||||
try:
|
||||
minuly_rocnik = Rocnik.objects.get(
|
||||
rocnik=(rocnik.rocnik-1))
|
||||
rocnik = minuly_rocnik
|
||||
|
||||
# Přepíšeme prázdnou výsledkovku výsledkovkou z minulého ročníku
|
||||
context['vysledkovka'] = VysledkovkaRocniku(rocnik, True)
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
context['rocnik'] = rocnik
|
||||
return render(
|
||||
request,
|
||||
'seminar/zadani/AktualniVysledkovka.html',
|
||||
context
|
||||
)
|
||||
|
||||
|
||||
### Titulni strana
|
||||
|
||||
def spravne_novinky(request):
|
||||
|
||||
def _spravne_novinky(request):
|
||||
"""
|
||||
Vrátí správný QuerySet novinek, tedy ten, který daný uživatel smí vidět.
|
||||
Tj. Organizátorům všechny, ostatním jen veřejné
|
||||
|
|
@ -224,7 +33,8 @@ def spravne_novinky(request):
|
|||
qs = qs.filter(zverejneno=True)
|
||||
return qs.order_by('-datum')
|
||||
|
||||
def aktualni_temata(rocnik):
|
||||
|
||||
def _aktualni_temata(rocnik):
|
||||
"""
|
||||
Vrací PolymorphicQuerySet témat v daném ročníku, ke kterým se aktuálně dá něco odevzdat.
|
||||
"""
|
||||
|
|
@ -235,7 +45,7 @@ class TitulniStranaView(generic.ListView):
|
|||
template_name= 'seminar/titulnistrana/titulnistrana.html'
|
||||
|
||||
def get_queryset(self):
|
||||
return spravne_novinky(self.request)[:3]
|
||||
return _spravne_novinky(self.request)[:3]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TitulniStranaView, self).get_context_data(**kwargs)
|
||||
|
|
@ -246,7 +56,7 @@ class TitulniStranaView(generic.ListView):
|
|||
|
||||
# Aktuální témata
|
||||
nazvy_a_odkazy_na_aktualni_temata = []
|
||||
akt_temata = aktualni_temata(nastaveni.aktualni_rocnik)
|
||||
akt_temata = _aktualni_temata(nastaveni.aktualni_rocnik)
|
||||
|
||||
for tema in akt_temata:
|
||||
# FIXME: netuším, jestli funguje tema.verejne_url(), nemáme testdata na témátka - je to asi url vzhledem k ročníku
|
||||
|
|
@ -258,371 +68,12 @@ class TitulniStranaView(generic.ListView):
|
|||
|
||||
return context
|
||||
|
||||
|
||||
class StareNovinkyView(generic.ListView):
|
||||
template_name = 'seminar/stare_novinky.html'
|
||||
|
||||
def get_queryset(self):
|
||||
return spravne_novinky(self.request)
|
||||
|
||||
### Archiv
|
||||
|
||||
|
||||
class ArchivView(generic.ListView):
|
||||
model = Rocnik
|
||||
template_name='seminar/archiv/cisla.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ArchivView, self).get_context_data(**kwargs)
|
||||
|
||||
cisla = Cislo.objects.filter(poradi=1)
|
||||
if not self.request.user.je_org:
|
||||
cisla = cisla.filter(verejne_db=True)
|
||||
urls ={}
|
||||
|
||||
for i, c in enumerate(cisla):
|
||||
# Výchozí nastavení
|
||||
if c.rocnik not in urls:
|
||||
urls[c.rocnik] = op.join(settings.STATIC_URL, "images", "no-picture.png")
|
||||
# NOTE: tohle možná nastavuje poslední titulku
|
||||
if c.titulka_nahled:
|
||||
urls[c.rocnik] = c.titulka_nahled.url
|
||||
|
||||
context["object_list"] = urls
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class RocnikView(generic.DetailView):
|
||||
model = Rocnik
|
||||
template_name = 'seminar/archiv/rocnik.html'
|
||||
|
||||
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
||||
def get_object(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = self.get_queryset()
|
||||
|
||||
return get_object_or_404(queryset,rocnik=self.kwargs.get('rocnik'))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(RocnikView, self).get_context_data(**kwargs)
|
||||
context["vysledkovka"] = VysledkovkaRocniku(context["rocnik"], True)
|
||||
context["neprazdna_vysledkovka"] = len(context['vysledkovka'].cisla_rocniku) != 0
|
||||
context["vysledkovka_neverejna"] = VysledkovkaRocniku(context["rocnik"], False)
|
||||
return context
|
||||
|
||||
def resiteleRocnikuCsvExportView(request, rocnik):
|
||||
from personalni.views import dataResiteluCsvResponse
|
||||
assert request.method in ('GET', 'HEAD')
|
||||
return dataResiteluCsvResponse(
|
||||
Resitel.objects.resi_v_rocniku(
|
||||
get_object_or_404(Rocnik, rocnik=rocnik)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# FIXME: Pozor, výš je ještě jeden ProblemView!
|
||||
#class ProblemView(generic.DetailView):
|
||||
# model = Problem
|
||||
#
|
||||
# # Používáme funkci, protože přímo template_name neumí mít v přiřazení dost logiky. Ledaže by se to udělalo polymorfně...
|
||||
# def get_template_names(self, **kwargs):
|
||||
# # FIXME: Switch podle typu není hezký, ale nechtělo se mi to přepisovat celé. Správně by se tohle mělo řešit polymorfismem.
|
||||
# spravne_templaty = {
|
||||
# s.Uloha: "uloha",
|
||||
# s.Tema: "tema",
|
||||
# s.Konfera: "konfera",
|
||||
# s.Clanek: "clanek",
|
||||
# }
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# return ['seminar/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
|
||||
#
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# # Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče.
|
||||
# if not context['object'].verejne() and not self.request.user.je_org:
|
||||
# raise PermissionDenied()
|
||||
# if isinstance(context['object'], Clanek):
|
||||
# context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni')
|
||||
# return context
|
||||
|
||||
|
||||
|
||||
class CisloView(generic.DetailView):
|
||||
# FIXME zobrazování témátek a vůbec, teď je tam jen odkaz na číslo v pdf
|
||||
model = Cislo
|
||||
template_name = 'seminar/archiv/cislo.html'
|
||||
|
||||
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
||||
def get_object(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = self.get_queryset()
|
||||
rocnik_arg = self.kwargs.get('rocnik')
|
||||
poradi_arg = self.kwargs.get('cislo')
|
||||
queryset = queryset.filter(rocnik__rocnik=rocnik_arg, poradi=poradi_arg)
|
||||
|
||||
try:
|
||||
obj = queryset.get()
|
||||
except queryset.model.DoesNotExist:
|
||||
raise Http404(_("No %(verbose_name)s found matching the query") %
|
||||
{'verbose_name': queryset.model._meta.verbose_name})
|
||||
return obj
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CisloView, self).get_context_data(**kwargs)
|
||||
|
||||
cislo = context['cislo']
|
||||
context['prevcislo'] = Cislo.objects.filter((Q(rocnik__lt=self.object.rocnik) | Q(poradi__lt=self.object.poradi))&Q(rocnik__lte=self.object.rocnik)).first()
|
||||
|
||||
deadliny = Deadline.objects.filter(cislo=cislo).reverse()
|
||||
deadliny_s_vysledkovkami = []
|
||||
|
||||
nadpisy = {
|
||||
Deadline.TYP_CISLA: "Výsledkovka",
|
||||
Deadline.TYP_PRVNI: "Výsledkovka do prvního deadlinu",
|
||||
Deadline.TYP_PRVNI_A_SOUS: "Výsledkovka do prvního deadlinu a deadlinu pro účast na soustředění",
|
||||
Deadline.TYP_SOUS: "Výsledkovka do deadlinu pro účast na soustředění",
|
||||
}
|
||||
|
||||
for deadline in deadliny:
|
||||
if self.request.user.je_org | deadline.verejna_vysledkovka:
|
||||
deadliny_s_vysledkovkami.append((deadline, nadpisy[deadline.typ], VysledkovkaCisla(cislo, not self.request.user.je_org, deadline)))
|
||||
|
||||
context['deadliny_s_vysledkovkami'] = deadliny_s_vysledkovkami
|
||||
return context
|
||||
|
||||
|
||||
class ArchivTemataView(generic.ListView):
|
||||
model = Problem
|
||||
template_name = 'seminar/archiv/temata.html'
|
||||
queryset = Tema.objects.filter(stav=Problem.STAV_ZADANY).select_related('rocnik').order_by('rocnik', 'kod')
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
ctx = super().get_context_data(*args, **kwargs)
|
||||
ctx['rocniky'] = OrderedDict()
|
||||
for rocnik, temata in groupby(ctx['object_list'], lambda tema: tema.rocnik):
|
||||
ctx['rocniky'][rocnik] = list(temata)
|
||||
return ctx
|
||||
|
||||
class OdmenyView(generic.TemplateView):
|
||||
template_name = 'seminar/archiv/odmeny.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
fromcislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('frocnik'), poradi=self.kwargs.get('fcislo'))
|
||||
tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo'))
|
||||
resitele = Resitel.objects.aktivni_resitele(tocislo)
|
||||
|
||||
def get_diff(from_deadline: Deadline, to_deadline: Deadline):
|
||||
frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline)
|
||||
tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline)
|
||||
outlist = []
|
||||
for resitel in resitele:
|
||||
fbody = frombody.get(resitel.id, 0)
|
||||
tbody = tobody.get(resitel.id, 0)
|
||||
ftitul = resitel.get_titul(fbody)
|
||||
ttitul = resitel.get_titul(tbody)
|
||||
if ftitul != ttitul:
|
||||
outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul})
|
||||
return outlist
|
||||
|
||||
def posledni_deadline_oprava(cislo: Cislo) -> Deadline:
|
||||
posledni_deadline = cislo.posledni_deadline
|
||||
if posledni_deadline is None:
|
||||
return Deadline.objects.filter(Q(cislo__poradi__lt=cislo.poradi, cislo__rocnik=cislo.rocnik) | Q(cislo__rocnik__rocnik__lt=cislo.rocnik.rocnik)).order_by("deadline").last()
|
||||
return posledni_deadline
|
||||
|
||||
context["from_cislo"] = fromcislo
|
||||
context["to_cislo"] = tocislo
|
||||
from_deadline = posledni_deadline_oprava(fromcislo)
|
||||
to_deadline = posledni_deadline_oprava(tocislo)
|
||||
context["from_deadline"] = from_deadline
|
||||
context["to_deadline"] = to_deadline
|
||||
context["zmeny"] = get_diff(from_deadline, to_deadline)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
|
||||
### Generovani vysledkovky
|
||||
|
||||
class CisloVysledkovkaView(CisloView):
|
||||
"""View vytvořené pro stránku zobrazující výsledkovku čísla v TeXu."""
|
||||
|
||||
model = Cislo
|
||||
template_name = 'seminar/archiv/cislo_vysledkovka.tex'
|
||||
#content_type = 'application/x-tex; charset=UTF8'
|
||||
#umozni rovnou stahnout TeXovsky dokument
|
||||
content_type = 'text/plain; charset=UTF8'
|
||||
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CisloVysledkovkaView, self).get_context_data()
|
||||
cislo = context['cislo']
|
||||
|
||||
cislopred = cislo.predchozi()
|
||||
if cislopred is not None:
|
||||
context['vysledkovka'] = VysledkovkaDoTeXu(
|
||||
cislo,
|
||||
od_vyjma=cislopred.zlomovy_deadline_pro_papirove_cislo(),
|
||||
do_vcetne=cislo.zlomovy_deadline_pro_papirove_cislo(),
|
||||
)
|
||||
else:
|
||||
context['vysledkovka'] = VysledkovkaCisla(
|
||||
cislo,
|
||||
jen_verejne=False,
|
||||
do_deadlinu=cislo.zlomovy_deadline_pro_papirove_cislo(),
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
# Podle předchozího
|
||||
class PosledniCisloVysledkovkaView(generic.DetailView):
|
||||
"""View vytvořené pro zobrazení výsledkovky posledního čísla v TeXu."""
|
||||
|
||||
model = Rocnik
|
||||
template_name = 'seminar/archiv/cislo_vysledkovka.tex'
|
||||
content_type = 'text/plain; charset=UTF8'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = self.get_queryset()
|
||||
rocnik_arg = self.kwargs.get('rocnik')
|
||||
queryset = queryset.filter(rocnik=rocnik_arg)
|
||||
|
||||
try:
|
||||
obj = queryset.get()
|
||||
except queryset.model.DoesNotExist:
|
||||
raise Http404(_("No %(verbose_name)s found matching the query") %
|
||||
{'verbose_name': queryset.model._meta.verbose_name})
|
||||
return obj
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(PosledniCisloVysledkovkaView, self).get_context_data()
|
||||
rocnik = context['rocnik']
|
||||
cislo = rocnik.cisla.order_by("poradi").last()
|
||||
cislopred = cislo.predchozi()
|
||||
context['vysledkovka'] = VysledkovkaDoTeXu(
|
||||
cislo,
|
||||
od_vyjma=cislopred.zlomovy_deadline_pro_papirove_cislo(),
|
||||
do_vcetne=cislo.deadline_v_cisle.order_by("deadline").last(),
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class RocnikVysledkovkaView(RocnikView):
|
||||
""" View vytvořené pro stránku zobrazující výsledkovku ročníku v TeXu."""
|
||||
model = Rocnik
|
||||
template_name = 'seminar/archiv/rocnik_vysledkovka.tex'
|
||||
#content_type = 'application/x-tex; charset=UTF8'
|
||||
#umozni rovnou stahnout TeXovsky dokument
|
||||
content_type = 'text/plain; charset=UTF8'
|
||||
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
||||
|
||||
def cisloObalkyView(request, rocnik, cislo):
|
||||
realne_cislo = get_object_or_404(Cislo, poradi=cislo, rocnik__rocnik=rocnik)
|
||||
return obalkyView(request, Resitel.objects.aktivni_resitele(realne_cislo))
|
||||
|
||||
|
||||
def obalkyView(request, resitele):
|
||||
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content
|
||||
|
||||
tempdir = tempfile.mkdtemp()
|
||||
with open(tempdir+"/obalky.tex","w") as texfile:
|
||||
texfile.write(tex.decode())
|
||||
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir)
|
||||
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
|
||||
|
||||
with open(tempdir+"/obalky.pdf","rb") as pdffile:
|
||||
response = HttpResponse(pdffile.read(), content_type='application/pdf')
|
||||
shutil.rmtree(tempdir)
|
||||
return response
|
||||
|
||||
|
||||
### Tituly
|
||||
def TitulyViewRocnik(request, rocnik):
|
||||
return TitulyView(request, rocnik, None)
|
||||
|
||||
|
||||
def TitulyView(request, rocnik, cislo):
|
||||
""" View pro stažení makra titulů v TeXu."""
|
||||
rocnik_obj = get_object_or_404(Rocnik, rocnik = rocnik)
|
||||
resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok)
|
||||
|
||||
asciijmena = []
|
||||
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
|
||||
# pokud ano, vrátí se jako true
|
||||
if cislo is not None:
|
||||
cislo_obj = get_object_or_404(Cislo, rocnik=rocnik_obj, poradi=cislo)
|
||||
slovnik_s_body = body_resitelu(do=cislo_obj.zlomovy_deadline_pro_papirove_cislo(), jen_verejne=False)
|
||||
else:
|
||||
slovnik_s_body = body_resitelu(do=Deadline.objects.filter(cislo__rocnik=rocnik_obj).last(), jen_verejne=False)
|
||||
|
||||
for resitel in resitele:
|
||||
resitel.titul = resitel.get_titul(slovnik_s_body[resitel.id])
|
||||
jmeno = resitel.osoba.jmeno+resitel.osoba.prijmeni
|
||||
# převedeme jména a příjmení řešitelů do ASCII
|
||||
ascii_jmeno_bytes = unicodedata.normalize('NFKD', jmeno).encode("ascii","ignore")
|
||||
# vrátí se byte string, převedeme na standardní string
|
||||
ascii_jmeno_divnoznaky = str(ascii_jmeno_bytes, "utf-8", "ignore").replace(" ","")
|
||||
resitel.ascii = ''.join(a for a in ascii_jmeno_divnoznaky if a.isalnum())
|
||||
if resitel.ascii not in asciijmena:
|
||||
asciijmena.append(resitel.ascii)
|
||||
else:
|
||||
jmenovci = True
|
||||
|
||||
return render(request, 'seminar/archiv/tituly.tex',
|
||||
{'resitele': resitele,'jmenovci':jmenovci},content_type="text/plain")
|
||||
|
||||
|
||||
### Články
|
||||
def group_by_rocnik(clanky):
|
||||
''' Vezme zadaný seznam článků a seskupí je podle ročníku.
|
||||
Vrátí seznam seznamů článků ze stejného ročníku.'''
|
||||
if len(clanky) == 0:
|
||||
return clanky
|
||||
clanky.order_by('cislo__rocnik__rocnik')
|
||||
skupiny_clanku = []
|
||||
skupina = []
|
||||
|
||||
rocnik = clanky.first().cislo.rocnik.rocnik # první ročník
|
||||
for clanek in clanky:
|
||||
if clanek.cislo.rocnik.rocnik == rocnik:
|
||||
skupina.append(clanek)
|
||||
else:
|
||||
skupiny_clanku.append(skupina)
|
||||
skupina = []
|
||||
skupina.append(clanek)
|
||||
rocnik = clanek.cislo.rocnik.rocnik
|
||||
skupiny_clanku.append(skupina)
|
||||
return skupiny_clanku
|
||||
|
||||
|
||||
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
|
||||
# FIXME: Původně tu byl kód přímo v těle třídy, což rozbíjelo migrace. Opravil jsem, ale vůbec nevím, jestli to funguje.
|
||||
class ClankyResitelView(generic.ListView):
|
||||
model = Problem
|
||||
template_name = 'seminar/clanky/resitelske_clanky.html'
|
||||
|
||||
# FIXME: QuerySet není pole!
|
||||
def get_queryset(self):
|
||||
clanky = Clanek.objects.filter(stav=Problem.STAV_VYRESENY).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik')
|
||||
queryset = []
|
||||
skupiny_clanku = group_by_rocnik(clanky)
|
||||
for skupina in skupiny_clanku:
|
||||
skupina.sort(key=lambda clanek: clanek.kod_v_rocniku)
|
||||
for clanek in skupina:
|
||||
queryset.append(clanek)
|
||||
return queryset
|
||||
|
||||
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
|
||||
#class ClankyOrganizatorView(generic.ListView)<F12>:
|
||||
# model = Problem
|
||||
# template_name = 'seminar/clanky/organizatorske_clanky.html'
|
||||
# queryset = Problem.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
|
||||
return _spravne_novinky(self.request)
|
||||
|
||||
|
||||
### Status
|
||||
|
|
@ -759,11 +210,3 @@ class JakResitView(generic.ListView):
|
|||
|
||||
def get_queryset(self):
|
||||
return None
|
||||
|
||||
class AktualniRocnikRedirectView(RedirectView):
|
||||
permanent=False
|
||||
pattern_name = 'seminar_rocnik'
|
||||
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
aktualni_rocnik = Nastaveni.get_solo().aktualni_rocnik.rocnik
|
||||
return super().get_redirect_url(rocnik=aktualni_rocnik, *args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,151 @@ import treenode.templatetags as tnltt
|
|||
import treenode.serializers as vr
|
||||
|
||||
|
||||
# ze starého modelu
|
||||
#def verejna_temata(rocnik):
|
||||
# """
|
||||
# Vrací queryset zveřejněných témat v daném ročníku.
|
||||
# """
|
||||
# return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod')
|
||||
|
||||
|
||||
# FIXME: Pozor, níž je ještě jeden ProblemView!
|
||||
#class ProblemView(generic.DetailView):
|
||||
# model = s.Problem
|
||||
# # Zkopírujeme template_name od TreeNodeView, protože jsme prakticky jen trošku upravený TreeNodeView
|
||||
# template_name = TreeNodeView.template_name
|
||||
#
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# user = self.request.user
|
||||
# # Teď potřebujeme doplnit tnldata do kontextu.
|
||||
# # Ošklivý type switch, hezčí by bylo udělat to polymorfni. FIXME.
|
||||
# if False:
|
||||
# # Hezčí formátování zbytku :-P
|
||||
# pass
|
||||
# elif isinstance(self.object, s.Clanek) or isinstance(self.object, s.Konfera):
|
||||
# # Tyhle Problémy mají ŘešeníNode
|
||||
# context['tnldata'] = TNLData.from_treenode(self.object.reseninode,user)
|
||||
# elif isinstance(self.object, s.Uloha):
|
||||
# # FIXME: Teď vždycky zobrazujeme i vzorák! Možná by bylo hezčí/lepší mít to stejně jako pro Téma: procházet jen dosažitelné z Ročníku / čísla / whatever
|
||||
# tnl_zadani = TNLData.from_treenode(self.object.ulohazadaninode,user)
|
||||
# tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode,user)
|
||||
# context['tnldata'] = TNLData.from_tnldata_list([tnl_zadani, tnl_vzorak])
|
||||
# elif isinstance(self.object, s.Tema):
|
||||
# rocniknode = self.object.rocnik.rocniknode
|
||||
# context['tnldata'] = TNLData.filter_treenode(rocniknode, lambda x: isinstance(x, s.TemaVCisleNode))
|
||||
# else:
|
||||
# raise ValueError("Obecný problém nejde zobrazit.")
|
||||
# return context
|
||||
|
||||
#class AktualniZadaniView(generic.TemplateView):
|
||||
# template_name = 'seminar/treenode.html'
|
||||
|
||||
# TODO Co chceme vlastně zobrazovat na této stránce? Zatím je zde aktuální číslo, ale může tu být cokoli jiného...
|
||||
#class AktualniZadaniView(TreeNodeView):
|
||||
# def get_object(self):
|
||||
# nastaveni = get_object_or_404(Nastaveni)
|
||||
# return nastaveni.aktualni_cislo.cislonode
|
||||
#
|
||||
# def get_context_data(self,**kwargs):
|
||||
# nastaveni = get_object_or_404(Nastaveni)
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# verejne = nastaveni.aktualni_cislo.verejne()
|
||||
# context['verejne'] = verejne
|
||||
# return context
|
||||
|
||||
|
||||
# nastaveni = get_object_or_404(Nastaveni)
|
||||
# temata = verejna_temata(nastaveni.aktualni_rocnik)
|
||||
# for t in temata:
|
||||
# if request.user.is_staff:
|
||||
# t.prispevky = t.prispevek_set.filter(problem=t)
|
||||
# else:
|
||||
# t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True)
|
||||
# return render(request, 'seminar/zadani/Temata.html',
|
||||
# {
|
||||
# 'temata': temata,
|
||||
# }
|
||||
# )
|
||||
#
|
||||
#
|
||||
#
|
||||
#def TematkoView(request, rocnik, tematko):
|
||||
# nastaveni = s.Nastaveni.objects.first()
|
||||
# rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik)
|
||||
# tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko)
|
||||
# seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode)
|
||||
# for node, depth in seznam:
|
||||
# if node.isinstance(node, s.KonferaNode):
|
||||
# raise Exception("Not implemented yet")
|
||||
# if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou
|
||||
# pass
|
||||
#
|
||||
# return render(request, 'seminar/tematka/toaletak.html', {})
|
||||
#
|
||||
#
|
||||
#def TemataRozcestnikView(request):
|
||||
# print("=============================================")
|
||||
# nastaveni = s.Nastaveni.objects.first()
|
||||
# tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik())
|
||||
# tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
|
||||
# for tematko_object in tematka_objects:
|
||||
# print("AKTUALNI TEMATKO")
|
||||
# print(tematko_object.id)
|
||||
# odkazy = vytahniZLesaSeznam(tematko_object, nastaveni.aktualni_rocnik().rocniknode, pouze_zajimave = True) #Odkazy jsou tuply (node, depth) v listu
|
||||
# print(odkazy)
|
||||
# cisla = [] # List tuplů (nazev cisla, list odkazů)
|
||||
# vcisle = []
|
||||
# cislo = None
|
||||
# for odkaz in odkazy:
|
||||
# if odkaz[1] == 0:
|
||||
# if cislo != None:
|
||||
# cisla.append((cislo, vcisle))
|
||||
# cislo = (odkaz[0].getOdkazStr(), odkaz[0].getOdkaz())
|
||||
# vcisle = []
|
||||
# else:
|
||||
# print(odkaz[0].getOdkaz())
|
||||
# vcisle.append((odkaz[0].getOdkazStr(), odkaz[0].getOdkaz()))
|
||||
# if cislo != None:
|
||||
# cisla.append((cislo, vcisle))
|
||||
#
|
||||
# print(cisla)
|
||||
# tematka.append({
|
||||
# "kod" : tematko_object.kod,
|
||||
# "nazev" : tematko_object.nazev,
|
||||
# "abstrakt" : tematko_object.abstrakt,
|
||||
# "obrazek": tematko_object.obrazek,
|
||||
# "cisla" : cisla
|
||||
# })
|
||||
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
|
||||
#
|
||||
|
||||
|
||||
# FIXME: Pozor, výš je ještě jeden ProblemView!
|
||||
#class ProblemView(generic.DetailView):
|
||||
# model = Problem
|
||||
#
|
||||
# # Používáme funkci, protože přímo template_name neumí mít v přiřazení dost logiky. Ledaže by se to udělalo polymorfně...
|
||||
# def get_template_names(self, **kwargs):
|
||||
# # FIXME: Switch podle typu není hezký, ale nechtělo se mi to přepisovat celé. Správně by se tohle mělo řešit polymorfismem.
|
||||
# spravne_templaty = {
|
||||
# s.Uloha: "uloha",
|
||||
# s.Tema: "tema",
|
||||
# s.Konfera: "konfera",
|
||||
# s.Clanek: "clanek",
|
||||
# }
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# return ['seminar/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
|
||||
#
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# # Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče.
|
||||
# if not context['object'].verejne() and not self.request.user.je_org:
|
||||
# raise PermissionDenied()
|
||||
# if isinstance(context['object'], Clanek):
|
||||
# context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni')
|
||||
# return context
|
||||
|
||||
class TNLData(object):
|
||||
def __init__(self,anode,parent=None, index=None):
|
||||
self.node = anode
|
||||
|
|
|
|||
71
tvorba/urls.py
Normal file
71
tvorba/urls.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"""
|
||||
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují.
|
||||
"""
|
||||
from django.urls import path
|
||||
from tvorba import views
|
||||
from personalni.utils import org_required
|
||||
|
||||
urlpatterns = [
|
||||
# path('aktualni/temata/', views.TemataRozcestnikView),
|
||||
# path('<int:rocnik>/t<int:tematko>/', views.TematkoView),
|
||||
|
||||
# Archiv
|
||||
path('archiv/rocniky/', views.ArchivView.as_view(), name="seminar_archiv_rocniky"),
|
||||
path('archiv/temata/', views.ArchivTemataView.as_view(), name="seminar_archiv_temata"),
|
||||
|
||||
path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='seminar_rocnik'),
|
||||
path('cislo/<int:rocnik>.<str:cislo>/', views.CisloView.as_view(), name='seminar_cislo'),
|
||||
# path('problem/<int:pk>/', views.problemView, name='seminar_problem'),
|
||||
|
||||
# Zadani
|
||||
# path('aktualni/zadani/', views.AktualniZadaniView.as_view(), name='seminar_aktualni_zadani'), # Dočasně ad-hoc jednoduchá věc.
|
||||
path('aktualni/zadani/', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
|
||||
# path('aktualni/temata/', views.ZadaniTemataView, name='seminar_temata'),
|
||||
path('aktualni/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_aktualni_vysledky'),
|
||||
path('aktualni/rocnik/', views.AktualniRocnikRedirectView.as_view(), name='seminar_aktualni_rocnik'),
|
||||
|
||||
# Clanky
|
||||
path('archiv/clanky/', views.ClankyResitelView.as_view(), name='clanky_resitel'),
|
||||
# path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'),
|
||||
|
||||
# Stranky viditelne pouze pro orgy:
|
||||
path(
|
||||
'rocnik/<int:rocnik>/vysledkovka.tex',
|
||||
org_required(views.RocnikVysledkovkaView.as_view()),
|
||||
name='seminar_rocnik_vysledkovka'
|
||||
),
|
||||
path(
|
||||
'rocnik/<int:rocnik>/resitele.csv',
|
||||
org_required(views.resiteleRocnikuCsvExportView),
|
||||
name='seminar_rocnik_resitele_csv'
|
||||
),
|
||||
path(
|
||||
'rocnik/<int:rocnik>/tituly.tex',
|
||||
org_required(views.TitulyViewRocnik),
|
||||
name='seminar_rocnik_titul'
|
||||
),
|
||||
path(
|
||||
'rocnik/<int:rocnik>/posledni_vysledkovka.tex',
|
||||
org_required(views.PosledniCisloVysledkovkaView.as_view()),
|
||||
name='seminar_rocnik_posledni_vysledkovka'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:rocnik>.<str:cislo>/vysledkovka.tex',
|
||||
org_required(views.CisloVysledkovkaView.as_view()),
|
||||
name='seminar_cislo_vysledkovka'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:rocnik>.<str:cislo>/obalky.pdf',
|
||||
org_required(views.cisloObalkyView),
|
||||
name='seminar_cislo_obalky'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:rocnik>.<str:cislo>/tituly.tex',
|
||||
org_required(views.TitulyView),
|
||||
name='seminar_cislo_titul'
|
||||
),
|
||||
path(
|
||||
'cislo/<int:trocnik>.<str:tcislo>/odmeny/<int:frocnik>.<str:fcislo>/',
|
||||
org_required(views.OdmenyView.as_view()),
|
||||
name="seminar_archiv_odmeny"),
|
||||
]
|
||||
4
tvorba/views/__init__.py
Normal file
4
tvorba/views/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
from aktualni import *
|
||||
from archiv import *
|
||||
from obalky import *
|
||||
from tex import *
|
||||
68
tvorba/views/aktualni.py
Normal file
68
tvorba/views/aktualni.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
from django.shortcuts import get_object_or_404, render
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.views.generic.base import RedirectView
|
||||
|
||||
from tvorba.models import Tema, Nastaveni, Rocnik
|
||||
|
||||
from vysledkovky.utils import VysledkovkaRocniku
|
||||
|
||||
|
||||
def AktualniZadaniView(request):
|
||||
nastaveni = get_object_or_404(Nastaveni)
|
||||
verejne = nastaveni.aktualni_cislo.verejne()
|
||||
return render(
|
||||
request, 'tvorba/zadani/AktualniZadani.html',
|
||||
{
|
||||
'nastaveni': nastaveni,
|
||||
'verejne': verejne,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def ZadaniTemataView(request):
|
||||
nastaveni = get_object_or_404(Nastaveni)
|
||||
verejne = nastaveni.aktualni_cislo.verejne()
|
||||
akt_rocnik = nastaveni.aktualni_cislo.rocnik
|
||||
temata = Tema.objects.filter(rocnik=akt_rocnik, stav='zadany')
|
||||
return render(
|
||||
request, 'tvorba/tematka/rozcestnik.html',
|
||||
{
|
||||
'tematka': temata,
|
||||
'verejne': verejne,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def ZadaniAktualniVysledkovkaView(request):
|
||||
nastaveni = get_object_or_404(Nastaveni)
|
||||
# Aktualni verejna vysledkovka
|
||||
rocnik = nastaveni.aktualni_rocnik
|
||||
context = {'vysledkovka': VysledkovkaRocniku(rocnik, True)}
|
||||
|
||||
# kdyz neni verejna vysledkovka, tak zobraz starou
|
||||
if len(context['vysledkovka'].cisla_rocniku) == 0:
|
||||
try:
|
||||
minuly_rocnik = Rocnik.objects.get(
|
||||
rocnik=(rocnik.rocnik-1))
|
||||
rocnik = minuly_rocnik
|
||||
|
||||
# Přepíšeme prázdnou výsledkovku výsledkovkou z minulého ročníku
|
||||
context['vysledkovka'] = VysledkovkaRocniku(rocnik, True)
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
context['rocnik'] = rocnik
|
||||
return render(
|
||||
request,
|
||||
'tvorba/zadani/AktualniVysledkovka.html',
|
||||
context
|
||||
)
|
||||
|
||||
|
||||
class AktualniRocnikRedirectView(RedirectView):
|
||||
permanent = False
|
||||
pattern_name = 'seminar_rocnik'
|
||||
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
aktualni_rocnik = Nastaveni.get_solo().aktualni_rocnik.rocnik
|
||||
return super().get_redirect_url(rocnik=aktualni_rocnik, *args, **kwargs)
|
||||
182
tvorba/views/archiv.py
Normal file
182
tvorba/views/archiv.py
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
import os.path as op
|
||||
from itertools import groupby
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views import generic
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import Http404
|
||||
from django.db.models import Q
|
||||
from django.conf import settings
|
||||
|
||||
from vysledkovky.utils import VysledkovkaCisla, VysledkovkaRocniku
|
||||
|
||||
from tvorba.models import Rocnik, Cislo, Deadline, Problem, Tema, Clanek
|
||||
from personalni.models.resitel import Resitel
|
||||
|
||||
|
||||
class ArchivView(generic.ListView):
|
||||
model = Rocnik
|
||||
template_name = 'tvorba/archiv/cisla.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ArchivView, self).get_context_data(**kwargs)
|
||||
|
||||
cisla = Cislo.objects.filter(poradi=1)
|
||||
if not self.request.user.je_org:
|
||||
cisla = cisla.filter(verejne_db=True)
|
||||
urls = {}
|
||||
|
||||
for i, c in enumerate(cisla):
|
||||
# Výchozí nastavení
|
||||
if c.rocnik not in urls:
|
||||
urls[c.rocnik] = op.join(settings.STATIC_URL, "images", "no-picture.png")
|
||||
# NOTE: tohle možná nastavuje poslední titulku
|
||||
if c.titulka_nahled:
|
||||
urls[c.rocnik] = c.titulka_nahled.url
|
||||
|
||||
context["object_list"] = urls
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class RocnikView(generic.DetailView):
|
||||
model = Rocnik
|
||||
template_name = 'tvorba/archiv/rocnik.html'
|
||||
|
||||
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
||||
def get_object(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = self.get_queryset()
|
||||
|
||||
return get_object_or_404(queryset, rocnik=self.kwargs.get('rocnik'))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(RocnikView, self).get_context_data(**kwargs)
|
||||
context["vysledkovka"] = VysledkovkaRocniku(context["rocnik"], True)
|
||||
context["neprazdna_vysledkovka"] = len(context['vysledkovka'].cisla_rocniku) != 0
|
||||
context["vysledkovka_neverejna"] = VysledkovkaRocniku(context["rocnik"], False)
|
||||
return context
|
||||
|
||||
|
||||
def resiteleRocnikuCsvExportView(request, rocnik):
|
||||
from personalni.views import dataResiteluCsvResponse
|
||||
assert request.method in ('GET', 'HEAD')
|
||||
return dataResiteluCsvResponse(
|
||||
Resitel.objects.resi_v_rocniku(
|
||||
get_object_or_404(Rocnik, rocnik=rocnik)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class CisloView(generic.DetailView):
|
||||
# FIXME zobrazování témátek a vůbec, teď je tam jen odkaz na číslo v pdf
|
||||
model = Cislo
|
||||
template_name = 'tvorba/archiv/cislo.html'
|
||||
|
||||
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
||||
def get_object(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = self.get_queryset()
|
||||
rocnik_arg = self.kwargs.get('rocnik')
|
||||
poradi_arg = self.kwargs.get('cislo')
|
||||
queryset = queryset.filter(rocnik__rocnik=rocnik_arg, poradi=poradi_arg)
|
||||
|
||||
try:
|
||||
obj = queryset.get()
|
||||
except queryset.model.DoesNotExist:
|
||||
raise Http404(
|
||||
_("No %(verbose_name)s found matching the query") %
|
||||
{'verbose_name': queryset.model._meta.verbose_name}
|
||||
)
|
||||
return obj
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CisloView, self).get_context_data(**kwargs)
|
||||
|
||||
cislo = context['cislo']
|
||||
context['prevcislo'] = Cislo.objects.filter(
|
||||
(Q(rocnik__lt=self.object.rocnik) | Q(poradi__lt=self.object.poradi)) &
|
||||
Q(rocnik__lte=self.object.rocnik)
|
||||
).first()
|
||||
|
||||
deadliny = Deadline.objects.filter(cislo=cislo).reverse()
|
||||
deadliny_s_vysledkovkami = []
|
||||
|
||||
nadpisy = {
|
||||
Deadline.TYP_CISLA: "Výsledkovka",
|
||||
Deadline.TYP_PRVNI: "Výsledkovka do prvního deadlinu",
|
||||
Deadline.TYP_PRVNI_A_SOUS: "Výsledkovka do prvního deadlinu a deadlinu pro účast na soustředění",
|
||||
Deadline.TYP_SOUS: "Výsledkovka do deadlinu pro účast na soustředění",
|
||||
}
|
||||
|
||||
for deadline in deadliny:
|
||||
if self.request.user.je_org | deadline.verejna_vysledkovka:
|
||||
deadliny_s_vysledkovkami.append((
|
||||
deadline, nadpisy[deadline.typ],
|
||||
VysledkovkaCisla(
|
||||
cislo, not self.request.user.je_org, deadline
|
||||
),
|
||||
))
|
||||
|
||||
context['deadliny_s_vysledkovkami'] = deadliny_s_vysledkovkami
|
||||
return context
|
||||
|
||||
|
||||
class ArchivTemataView(generic.ListView):
|
||||
model = Problem
|
||||
template_name = 'tvorba/archiv/temata.html'
|
||||
queryset = Tema.objects.filter(stav=Problem.STAV_ZADANY).select_related('rocnik').order_by('rocnik', 'kod')
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
ctx = super().get_context_data(*args, **kwargs)
|
||||
ctx['rocniky'] = OrderedDict()
|
||||
for rocnik, temata in groupby(ctx['object_list'], lambda tema: tema.rocnik):
|
||||
ctx['rocniky'][rocnik] = list(temata)
|
||||
return ctx
|
||||
|
||||
|
||||
### Články
|
||||
def group_by_rocnik(clanky):
|
||||
""" Vezme zadaný seznam článků a seskupí je podle ročníku.
|
||||
Vrátí seznam seznamů článků ze stejného ročníku."""
|
||||
if len(clanky) == 0:
|
||||
return clanky
|
||||
clanky.order_by('cislo__rocnik__rocnik')
|
||||
skupiny_clanku = []
|
||||
skupina = []
|
||||
|
||||
rocnik = clanky.first().cislo.rocnik.rocnik # první ročník
|
||||
for clanek in clanky:
|
||||
if clanek.cislo.rocnik.rocnik == rocnik:
|
||||
skupina.append(clanek)
|
||||
else:
|
||||
skupiny_clanku.append(skupina)
|
||||
skupina = [clanek]
|
||||
rocnik = clanek.cislo.rocnik.rocnik
|
||||
skupiny_clanku.append(skupina)
|
||||
return skupiny_clanku
|
||||
|
||||
|
||||
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
|
||||
# FIXME: Původně tu byl kód přímo v těle třídy, což rozbíjelo migrace. Opravil jsem, ale vůbec nevím, jestli to funguje.
|
||||
class ClankyResitelView(generic.ListView):
|
||||
model = Problem
|
||||
template_name = 'tvorba/clanky/resitelske_clanky.html'
|
||||
|
||||
# FIXME: QuerySet není pole!
|
||||
def get_queryset(self):
|
||||
clanky = Clanek.objects.filter(stav=Problem.STAV_VYRESENY).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik')
|
||||
queryset = []
|
||||
skupiny_clanku = group_by_rocnik(clanky)
|
||||
for skupina in skupiny_clanku:
|
||||
skupina.sort(key=lambda clanek: clanek.kod_v_rocniku)
|
||||
for clanek in skupina:
|
||||
queryset.append(clanek)
|
||||
return queryset
|
||||
|
||||
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
|
||||
# class ClankyOrganizatorView(generic.ListView):
|
||||
# model = Problem
|
||||
# template_name = 'seminar/clanky/organizatorske_clanky.html'
|
||||
# queryset = Problem.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
|
||||
91
tvorba/views/obalky.py
Normal file
91
tvorba/views/obalky.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import tempfile
|
||||
import subprocess
|
||||
import shutil
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.http import HttpResponse
|
||||
from django.views import generic
|
||||
from django.db.models import Q
|
||||
|
||||
from tvorba.models import Cislo, Deadline
|
||||
from personalni.models.resitel import Resitel
|
||||
from vysledkovky.utils import body_resitelu
|
||||
|
||||
|
||||
def cisloObalkyView(request, rocnik, cislo):
|
||||
realne_cislo = get_object_or_404(Cislo, poradi=cislo, rocnik__rocnik=rocnik)
|
||||
return obalkyView(request, Resitel.objects.aktivni_resitele(realne_cislo))
|
||||
|
||||
|
||||
def obalkyView(request, resitele):
|
||||
tex = render(
|
||||
request, 'tvorba/archiv/obalky.tex',
|
||||
{'resitele': resitele}
|
||||
).content
|
||||
|
||||
tempdir = tempfile.mkdtemp()
|
||||
with open(tempdir+"/obalky.tex", "w") as texfile:
|
||||
texfile.write(tex.decode())
|
||||
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir)
|
||||
subprocess.call(["pdflatex", "obalky.tex"], cwd=tempdir)
|
||||
|
||||
with open(tempdir+"/obalky.pdf", "rb") as pdffile:
|
||||
response = HttpResponse(pdffile.read(), content_type='application/pdf')
|
||||
shutil.rmtree(tempdir)
|
||||
return response
|
||||
|
||||
|
||||
class OdmenyView(generic.TemplateView):
|
||||
template_name = 'tvorba/archiv/odmeny.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
fromcislo = get_object_or_404(
|
||||
Cislo,
|
||||
rocnik=self.kwargs.get('frocnik'),
|
||||
poradi=self.kwargs.get('fcislo'),
|
||||
)
|
||||
tocislo = get_object_or_404(
|
||||
Cislo,
|
||||
rocnik=self.kwargs.get('trocnik'),
|
||||
poradi=self.kwargs.get('tcislo'),
|
||||
)
|
||||
resitele = Resitel.objects.aktivni_resitele(tocislo)
|
||||
|
||||
def get_diff(from_deadline: Deadline, to_deadline: Deadline):
|
||||
frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline)
|
||||
tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline)
|
||||
outlist = []
|
||||
for resitel in resitele:
|
||||
fbody = frombody.get(resitel.id, 0)
|
||||
tbody = tobody.get(resitel.id, 0)
|
||||
ftitul = resitel.get_titul(fbody)
|
||||
ttitul = resitel.get_titul(tbody)
|
||||
if ftitul != ttitul:
|
||||
outlist.append({
|
||||
'jmeno': resitel.osoba.plne_jmeno(),
|
||||
'ftitul': ftitul,
|
||||
'ttitul': ttitul},
|
||||
)
|
||||
return outlist
|
||||
|
||||
def posledni_deadline_oprava(cislo: Cislo) -> Deadline:
|
||||
posledni_deadline = cislo.posledni_deadline
|
||||
if posledni_deadline is None:
|
||||
return Deadline.objects.filter(
|
||||
Q(cislo__poradi__lt=cislo.poradi, cislo__rocnik=cislo.rocnik) |
|
||||
Q(cislo__rocnik__rocnik__lt=cislo.rocnik.rocnik),
|
||||
).order_by("deadline").last()
|
||||
return posledni_deadline
|
||||
|
||||
context["from_cislo"] = fromcislo
|
||||
context["to_cislo"] = tocislo
|
||||
from_deadline = posledni_deadline_oprava(fromcislo)
|
||||
to_deadline = posledni_deadline_oprava(tocislo)
|
||||
context["from_deadline"] = from_deadline
|
||||
context["to_deadline"] = to_deadline
|
||||
context["zmeny"] = get_diff(from_deadline, to_deadline)
|
||||
|
||||
return context
|
||||
132
tvorba/views/tex.py
Normal file
132
tvorba/views/tex.py
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
import unicodedata
|
||||
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.views import generic
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import Http404
|
||||
|
||||
from personalni.models.resitel import Resitel
|
||||
from tvorba.models import Rocnik, Cislo, Deadline
|
||||
|
||||
from vysledkovky.utils import body_resitelu, VysledkovkaCisla, VysledkovkaDoTeXu
|
||||
from tvorba.views.archiv import CisloView, RocnikView
|
||||
|
||||
|
||||
class CisloVysledkovkaView(CisloView):
|
||||
"""View vytvořené pro stránku zobrazující výsledkovku čísla v TeXu."""
|
||||
|
||||
model = Cislo
|
||||
template_name = 'tvorba/archiv/cislo_vysledkovka.tex'
|
||||
# content_type = 'application/x-tex; charset=UTF8'
|
||||
# umozni rovnou stahnout TeXovsky dokument
|
||||
content_type = 'text/plain; charset=UTF8'
|
||||
# vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CisloVysledkovkaView, self).get_context_data()
|
||||
cislo = context['cislo']
|
||||
|
||||
cislopred = cislo.predchozi()
|
||||
if cislopred is not None:
|
||||
context['vysledkovka'] = VysledkovkaDoTeXu(
|
||||
cislo,
|
||||
od_vyjma=cislopred.zlomovy_deadline_pro_papirove_cislo(),
|
||||
do_vcetne=cislo.zlomovy_deadline_pro_papirove_cislo(),
|
||||
)
|
||||
else:
|
||||
context['vysledkovka'] = VysledkovkaCisla(
|
||||
cislo,
|
||||
jen_verejne=False,
|
||||
do_deadlinu=cislo.zlomovy_deadline_pro_papirove_cislo(),
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
# Podle předchozího
|
||||
class PosledniCisloVysledkovkaView(generic.DetailView):
|
||||
"""View vytvořené pro zobrazení výsledkovky posledního čísla v TeXu."""
|
||||
|
||||
model = Rocnik
|
||||
template_name = 'tvorba/archiv/cislo_vysledkovka.tex'
|
||||
content_type = 'text/plain; charset=UTF8'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = self.get_queryset()
|
||||
rocnik_arg = self.kwargs.get('rocnik')
|
||||
queryset = queryset.filter(rocnik=rocnik_arg)
|
||||
|
||||
try:
|
||||
obj = queryset.get()
|
||||
except queryset.model.DoesNotExist:
|
||||
raise Http404(
|
||||
_("No %(verbose_name)s found matching the query") %
|
||||
{'verbose_name': queryset.model._meta.verbose_name}
|
||||
)
|
||||
return obj
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(PosledniCisloVysledkovkaView, self).get_context_data()
|
||||
rocnik = context['rocnik']
|
||||
cislo = rocnik.cisla.order_by("poradi").last()
|
||||
cislopred = cislo.predchozi()
|
||||
context['vysledkovka'] = VysledkovkaDoTeXu(
|
||||
cislo,
|
||||
od_vyjma=cislopred.zlomovy_deadline_pro_papirove_cislo(),
|
||||
do_vcetne=cislo.deadline_v_cisle.order_by("deadline").last(),
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class RocnikVysledkovkaView(RocnikView):
|
||||
""" View vytvořené pro stránku zobrazující výsledkovku ročníku v TeXu."""
|
||||
model = Rocnik
|
||||
template_name = 'tvorba/archiv/rocnik_vysledkovka.tex'
|
||||
# content_type = 'application/x-tex; charset=UTF8'
|
||||
# umozni rovnou stahnout TeXovsky dokument
|
||||
content_type = 'text/plain; charset=UTF8'
|
||||
# vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
||||
|
||||
|
||||
# Tituly
|
||||
def TitulyViewRocnik(request, rocnik):
|
||||
return TitulyView(request, rocnik, None)
|
||||
|
||||
|
||||
def TitulyView(request, rocnik, cislo):
|
||||
""" View pro stažení makra titulů v TeXu."""
|
||||
rocnik_obj = get_object_or_404(Rocnik, rocnik=rocnik)
|
||||
resitele = Resitel.objects.filter(rok_maturity__gte=rocnik_obj.prvni_rok)
|
||||
|
||||
asciijmena = []
|
||||
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
|
||||
# pokud ano, vrátí se jako true
|
||||
if cislo is not None:
|
||||
cislo_obj = get_object_or_404(Cislo, rocnik=rocnik_obj, poradi=cislo)
|
||||
slovnik_s_body = body_resitelu(
|
||||
do=cislo_obj.zlomovy_deadline_pro_papirove_cislo(), jen_verejne=False
|
||||
)
|
||||
else:
|
||||
slovnik_s_body = body_resitelu(
|
||||
do=Deadline.objects.filter(cislo__rocnik=rocnik_obj).last(),
|
||||
jen_verejne=False
|
||||
)
|
||||
|
||||
for resitel in resitele:
|
||||
resitel.titul = resitel.get_titul(slovnik_s_body[resitel.id])
|
||||
jmeno = resitel.osoba.jmeno+resitel.osoba.prijmeni
|
||||
# převedeme jména a příjmení řešitelů do ASCII
|
||||
ascii_jmeno_bytes = unicodedata.normalize('NFKD', jmeno).encode("ascii", "ignore")
|
||||
# vrátí se byte string, převedeme na standardní string
|
||||
ascii_jmeno_divnoznaky = str(ascii_jmeno_bytes, "utf-8", "ignore").replace(" ", "")
|
||||
resitel.ascii = ''.join(a for a in ascii_jmeno_divnoznaky if a.isalnum())
|
||||
if resitel.ascii not in asciijmena:
|
||||
asciijmena.append(resitel.ascii)
|
||||
else:
|
||||
jmenovci = True
|
||||
|
||||
return render(
|
||||
request, 'tvorba/archiv/tituly.tex',
|
||||
{'resitele': resitele, 'jmenovci': jmenovci},
|
||||
content_type="text/plain"
|
||||
)
|
||||
Loading…
Reference in a new issue