Rozstřílení seminářové aplikace #60

Merged
zelvuska merged 19 commits from split into master 2024-10-22 21:27:21 +02:00
36 changed files with 215 additions and 190 deletions
Showing only changes of commit 31b7cbb8d7 - Show all commits

View file

@ -1,7 +1,6 @@
from django.test import TestCase, tag
from django.urls import reverse
import seminar.models as m
import seminar.views as v
from seminar.utils import sync_skoly
@tag('stejny-model-na-produkci')

View file

@ -131,6 +131,7 @@ INSTALLED_APPS = (
# MaMweb
'mamweb',
'seminar',
'tvorba',
'galerie',
'korektury',
'prednasky',

View file

@ -17,8 +17,8 @@ urlpatterns = [
path('admin/', admin.site.urls), # NOQA
path('ckeditor/', include('ckeditor_uploader.urls')),
# Seminarova aplikace (ma vlastni podadresare)
path('', include('seminar.urls')),
# Tvorba = ročníky, čísla, problémy atd. (ma vlastni podadresare)
path('', include('tvorba.urls')),
# Odevzdavatko (ma vlastni podadresare)
path('', include('odevzdavatko.urls')),

View file

@ -1,173 +1,11 @@
from django.contrib import admin
from django.db import models
from django.forms import widgets, ModelForm
from django.core.exceptions import ValidationError
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
from solo.admin import SingletonModelAdmin
from django.utils.safestring import mark_safe
from django.forms import widgets
# Todo: reversion
import seminar.models as m
admin.site.register(m.Rocnik)
admin.site.register(m.ZmrazenaVysledkovka)
@admin.register(m.Deadline)
class DeadlineAdmin(admin.ModelAdmin):
actions = ['pregeneruj_vysledkovku']
# Nikomu nezobrazovat, ale superuživatelům se může hodit :-)
@admin.action(permissions=['bazmek'], description= 'Přegeneruj výsledkovky vybraných deadlinů')
def pregeneruj_vysledkovku(self, req, qs):
for deadline in qs:
deadline.vygeneruj_vysledkovku()
def has_bazmek_permission(self, request):
# Boilerplate: potřebujeme nějakou permission, protože nějaká haluz v Djangu…
return request.user.is_superuser
class DeadlineAdminInline(admin.TabularInline):
model = m.Deadline
extra = 0
class CisloForm(ModelForm):
class Meta:
model = m.Cislo
fields = '__all__'
def clean(self):
if self.cleaned_data.get('verejne_db') == False:
return self.cleaned_data
# cn = m.CisloNode.objects.get(cislo=self.instance)
# errors = []
# for ch in tl.all_children(cn):
# if isinstance(ch, m.TemaVCisleNode):
# if ch.tema.stav not in \
# (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
# errors.append(ValidationError('Téma %(tema)s není zadané ani vyřešené', params={'tema':ch.tema}))
#
# if isinstance(ch, m.UlohaZadaniNode) or isinstance(ch, m.UlohaVzorakNode):
# if ch.uloha.stav not in \
# (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
# errors.append(ValidationError('Úloha %(uloha)s není zadaná ani vyřešená', params={'uloha':ch.uloha}))
# if isinstance(ch, m.ReseniNode):
# for problem in ch.reseni.problem_set:
# if problem not in \
# (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
# errors.append(ValidationError('Problém %s není zadaný ani vyřešený', code=problem))
# if errors:
# errors.append(ValidationError(mark_safe('<b>Pokud chceš učinit všechny problémy, co nejsou zadané ani vyřešené, zadanými a číslo zveřejnit, můžeš to udělat pomocí akce v <a href="/admin/seminar/cislo">seznamu čísel</a></b>')))
# raise ValidationError(errors)
errors = []
for ch in m.Uloha.objects.filter(cislo_zadani=self.instance):
if ch.stav not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
errors.append(
ValidationError('Úloha %(uloha)s není zadaná ani vyřešená', params={'uloha': ch}))
if errors:
errors.append(ValidationError(mark_safe(
'<b>Pokud chceš učinit všechny problémy, co nejsou zadané ani vyřešené, zadanými a číslo zveřejnit, můžeš to udělat pomocí akce v <a href="/admin/seminar/cislo">seznamu čísel</a></b>')))
if self.cleaned_data.get('datum_vydani') == None:
self.add_error('datum_vydani','Číslo určené ke zveřejnění nemá nastavené datum vydání')
if errors:
raise ValidationError(errors)
return self.cleaned_data
@admin.register(m.Cislo)
class CisloAdmin(admin.ModelAdmin):
form = CisloForm
actions = ['force_publish', 'pregeneruj_vysledkovky']
inlines = (DeadlineAdminInline,)
def force_publish(self,request,queryset):
for cislo in queryset:
# cn = m.CisloNode.objects.get(cislo=cislo)
# for ch in tl.all_children(cn):
# if isinstance(ch, m.TemaVCisleNode):
# if ch.tema.stav not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
# ch.tema.stav = m.Problem.STAV_ZADANY
# ch.tema.save()
#
# if isinstance(ch, m.UlohaZadaniNode) or isinstance(ch, m.UlohaVzorakNode):
# if ch.uloha.stav not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
# ch.uloha.stav = m.Problem.STAV_ZADANY
# ch.uloha.save()
# if isinstance(ch, m.ReseniNode):
# for problem in ch.reseni.problem_set:
# if problem not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
# problem.stav = m.Problem.STAV_ZADANY
# problem.save()
for ch in m.Uloha.objects.filter(cislo_zadani=cislo):
if ch.stav not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
ch.stav = m.Problem.STAV_ZADANY
ch.save()
hp = ch.hlavni_problem
if hp.stav not in (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY):
hp.stav = m.Problem.STAV_ZADANY
hp.save()
# TODO Řešení, vzoráky?
# TODO Konfera/Článek?
cislo.verejne_db = True
cislo.save()
force_publish.short_description = 'Zveřejnit vybraná čísla a všechny návrhy úloh v nich učinit zadanými'
# Jen pro superuživatele
@admin.action(permissions=['bazmek'], description='Přegenerovat výsledkovky všech deadlinů vybraných čísel')
def pregeneruj_vysledkovky(self, req, qs):
for cislo in qs:
for deadline in cislo.deadline_v_cisle.all():
deadline.vygeneruj_vysledkovku()
def has_bazmek_permission(self, request):
# Boilerplate: potřebujeme nějakou permission, protože nějaká haluz v Djangu…
return request.user.is_superuser
@admin.register(m.Problem)
class ProblemAdmin(PolymorphicParentModelAdmin):
base_model = m.Problem
child_models = [
m.Tema,
m.Clanek,
m.Uloha,
m.Konfera,
]
# Pokud chceme orezavat na aktualni rocnik, musime do modelu pridat odkaz na rocnik. Zatim bere vse.
search_fields = ['nazev']
# V ProblemAdmin to nejde, protoze se to nepropise do deti
class ProblemAdminMixin(object):
show_in_index = True
autocomplete_fields = ['nadproblem','autor','garant']
filter_horizontal = ['opravovatele']
@admin.register(m.Tema)
class TemaAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = m.Tema
@admin.register(m.Clanek)
class ClanekAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = m.Clanek
@admin.register(m.Uloha)
class UlohaAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = m.Uloha
@admin.register(m.Konfera)
class KonferaAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = m.Konfera
class TextAdminInline(admin.TabularInline):
model = m.Text
@ -180,4 +18,3 @@ admin.site.register(m.Text)
# admin.site.register(m.Pohadka)
admin.site.register(m.Obrazek)
admin.site.register(m.Nastaveni, SingletonModelAdmin)

View file

@ -1,4 +1,4 @@
{% extends "seminar/archiv/base.html" %}
{% extends "tvorba/archiv/base.html" %}
{% load static %}
{% block custom_css %}

0
tvorba/__init__.py Normal file
View file

177
tvorba/admin.py Normal file
View file

@ -0,0 +1,177 @@
from django.contrib import admin
from django.db import models
from django.forms import widgets, ModelForm
from django.core.exceptions import ValidationError
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
from django.utils.safestring import mark_safe
# Todo: reversion
import soustredeni.models
from seminar.models.tvorba import Rocnik, ZmrazenaVysledkovka, Deadline, Uloha, Problem, Tema, Clanek, Cislo
admin.site.register(Rocnik)
admin.site.register(ZmrazenaVysledkovka)
@admin.register(Deadline)
class DeadlineAdmin(admin.ModelAdmin):
actions = ['pregeneruj_vysledkovku']
# Nikomu nezobrazovat, ale superuživatelům se může hodit :-)
@admin.action(permissions=['bazmek'], description= 'Přegeneruj výsledkovky vybraných deadlinů')
def pregeneruj_vysledkovku(self, req, qs):
for deadline in qs:
deadline.vygeneruj_vysledkovku()
def has_bazmek_permission(self, request):
# Boilerplate: potřebujeme nějakou permission, protože nějaká haluz v Djangu…
return request.user.is_superuser
class DeadlineAdminInline(admin.TabularInline):
model = Deadline
extra = 0
class CisloForm(ModelForm):
class Meta:
model = Cislo
fields = '__all__'
def clean(self):
if self.cleaned_data.get('verejne_db') == False:
return self.cleaned_data
# cn = CisloNode.objects.get(cislo=self.instance)
# errors = []
# for ch in tl.all_children(cn):
# if isinstance(ch, TemaVCisleNode):
# if ch.tema.stav not in \
# (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
# errors.append(ValidationError('Téma %(tema)s není zadané ani vyřešené', params={'tema':ch.tema}))
#
# if isinstance(ch, UlohaZadaniNode) or isinstance(ch, UlohaVzorakNode):
# if ch.uloha.stav not in \
# (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
# errors.append(ValidationError('Úloha %(uloha)s není zadaná ani vyřešená', params={'uloha':ch.uloha}))
# if isinstance(ch, ReseniNode):
# for problem in ch.reseni.problem_set:
# if problem not in \
# (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
# errors.append(ValidationError('Problém %s není zadaný ani vyřešený', code=problem))
# if errors:
# errors.append(ValidationError(mark_safe('<b>Pokud chceš učinit všechny problémy, co nejsou zadané ani vyřešené, zadanými a číslo zveřejnit, můžeš to udělat pomocí akce v <a href="/admin/seminar/cislo">seznamu čísel</a></b>')))
# raise ValidationError(errors)
errors = []
for ch in Uloha.objects.filter(cislo_zadani=self.instance):
if ch.stav not in (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
errors.append(
ValidationError('Úloha %(uloha)s není zadaná ani vyřešená', params={'uloha': ch}))
if errors:
errors.append(ValidationError(mark_safe(
'<b>Pokud chceš učinit všechny problémy, co nejsou zadané ani vyřešené, zadanými a číslo zveřejnit, můžeš to udělat pomocí akce v <a href="/admin/seminar/cislo">seznamu čísel</a></b>')))
if self.cleaned_data.get('datum_vydani') == None:
self.add_error('datum_vydani','Číslo určené ke zveřejnění nemá nastavené datum vydání')
if errors:
raise ValidationError(errors)
return self.cleaned_data
@admin.register(Cislo)
class CisloAdmin(admin.ModelAdmin):
form = CisloForm
actions = ['force_publish', 'pregeneruj_vysledkovky']
inlines = (DeadlineAdminInline,)
def force_publish(self,request,queryset):
for cislo in queryset:
# cn = CisloNode.objects.get(cislo=cislo)
# for ch in tl.all_children(cn):
# if isinstance(ch, TemaVCisleNode):
# if ch.tema.stav not in (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
# ch.tema.stav = Problem.STAV_ZADANY
# ch.tema.save()
#
# if isinstance(ch, UlohaZadaniNode) or isinstance(ch, UlohaVzorakNode):
# if ch.uloha.stav not in (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
# ch.uloha.stav = Problem.STAV_ZADANY
# ch.uloha.save()
# if isinstance(ch, ReseniNode):
# for problem in ch.reseni.problem_set:
# if problem not in (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
# problem.stav = Problem.STAV_ZADANY
# problem.save()
for ch in Uloha.objects.filter(cislo_zadani=cislo):
if ch.stav not in (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
ch.stav = Problem.STAV_ZADANY
ch.save()
hp = ch.hlavni_problem
if hp.stav not in (Problem.STAV_ZADANY, Problem.STAV_VYRESENY):
hp.stav = Problem.STAV_ZADANY
hp.save()
# TODO Řešení, vzoráky?
# TODO Konfera/Článek?
cislo.verejne_db = True
cislo.save()
force_publish.short_description = 'Zveřejnit vybraná čísla a všechny návrhy úloh v nich učinit zadanými'
# Jen pro superuživatele
@admin.action(permissions=['bazmek'], description='Přegenerovat výsledkovky všech deadlinů vybraných čísel')
def pregeneruj_vysledkovky(self, req, qs):
for cislo in qs:
for deadline in cislo.deadline_v_cisle.all():
deadline.vygeneruj_vysledkovku()
def has_bazmek_permission(self, request):
# Boilerplate: potřebujeme nějakou permission, protože nějaká haluz v Djangu…
return request.user.is_superuser
@admin.register(Problem)
class ProblemAdmin(PolymorphicParentModelAdmin):
base_model = Problem
child_models = [
Tema,
Clanek,
Uloha,
soustredeni.models.Konfera,
]
# Pokud chceme orezavat na aktualni rocnik, musime do modelu pridat odkaz na rocnik. Zatim bere vse.
search_fields = ['nazev']
# V ProblemAdmin to nejde, protoze se to nepropise do deti
class ProblemAdminMixin(object):
show_in_index = True
autocomplete_fields = ['nadproblem','autor','garant']
filter_horizontal = ['opravovatele']
@admin.register(Tema)
class TemaAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = Tema
@admin.register(Clanek)
class ClanekAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = Clanek
@admin.register(Uloha)
class UlohaAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = Uloha
@admin.register(soustredeni.models.Konfera)
class KonferaAdmin(ProblemAdminMixin,PolymorphicChildModelAdmin):
base_model = soustredeni.models.Konfera

6
tvorba/apps.py Normal file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class TvorbaConfig(AppConfig):
name = 'tvorba'
verbose_name = 'Tvorba'

View file

View file

@ -1,6 +1,6 @@
from django.urls import path, include, re_path
from . import views
from .utils import org_required
from seminar.utils import org_required
urlpatterns = [
# path('aktualni/temata/', views.TemataRozcestnikView),

View file

@ -82,7 +82,7 @@ def get_problemy_k_tematu(tema):
#class AktualniZadaniView(generic.TemplateView):
# template_name = 'seminar/treenode.html'
# template_name = 'treenode/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):
@ -100,7 +100,7 @@ def get_problemy_k_tematu(tema):
def AktualniZadaniView(request):
nastaveni = get_object_or_404(Nastaveni)
verejne = nastaveni.aktualni_cislo.verejne()
return render(request, 'seminar/zadani/AktualniZadani.html',
return render(request, 'tvorba/zadani/AktualniZadani.html',
{'nastaveni': nastaveni,
'verejne': verejne,
},
@ -111,7 +111,7 @@ def ZadaniTemataView(request):
verejne = nastaveni.aktualni_cislo.verejne()
akt_rocnik = nastaveni.aktualni_cislo.rocnik
temata = s.Tema.objects.filter(rocnik=akt_rocnik, stav='zadany')
return render(request, 'seminar/tematka/rozcestnik.html',
return render(request, 'tvorba/tematka/rozcestnik.html',
{
'tematka': temata,
'verejne': verejne,
@ -126,7 +126,7 @@ def ZadaniTemataView(request):
# 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',
# return render(request, 'tvorba/zadani/Temata.html',
# {
# 'temata': temata,
# }
@ -145,7 +145,7 @@ def ZadaniTemataView(request):
# if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou
# pass
#
# return render(request, 'seminar/tematka/toaletak.html', {})
# return render(request, 'tvorba/tematka/toaletak.html', {})
#
#
#def TemataRozcestnikView(request):
@ -181,7 +181,7 @@ def ZadaniTemataView(request):
# "obrazek": tematko_object.obrazek,
# "cisla" : cisla
# })
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
# return render(request, 'tvorba/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
#
def ZadaniAktualniVysledkovkaView(request):
@ -205,7 +205,7 @@ def ZadaniAktualniVysledkovkaView(request):
context['rocnik'] = rocnik
return render(
request,
'seminar/zadani/AktualniVysledkovka.html',
'tvorba/zadani/AktualniVysledkovka.html',
context
)
@ -224,7 +224,7 @@ def aktualni_temata(rocnik):
class ArchivView(generic.ListView):
model = Rocnik
template_name='seminar/archiv/cisla.html'
template_name = 'tvorba/archiv/cisla.html'
def get_context_data(self, **kwargs):
context = super(ArchivView, self).get_context_data(**kwargs)
@ -252,7 +252,7 @@ class ArchivView(generic.ListView):
class RocnikView(generic.DetailView):
model = Rocnik
template_name = 'seminar/archiv/rocnik.html'
template_name = 'tvorba/archiv/rocnik.html'
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
def get_object(self, queryset=None):
@ -292,7 +292,7 @@ def resiteleRocnikuCsvExportView(request, rocnik):
# s.Clanek: "clanek",
# }
# context = super().get_context_data(**kwargs)
# return ['seminar/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
# return ['tvorba/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
#
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
@ -308,7 +308,7 @@ def resiteleRocnikuCsvExportView(request, 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 = 'seminar/archiv/cislo.html'
template_name = 'tvorba/archiv/cislo.html'
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
def get_object(self, queryset=None):
@ -351,7 +351,7 @@ class CisloView(generic.DetailView):
class ArchivTemataView(generic.ListView):
model = Problem
template_name = 'seminar/archiv/temata.html'
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):
@ -362,7 +362,7 @@ class ArchivTemataView(generic.ListView):
return ctx
class OdmenyView(generic.TemplateView):
template_name = 'seminar/archiv/odmeny.html'
template_name = 'tvorba/archiv/odmeny.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -408,7 +408,7 @@ 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'
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'
@ -439,7 +439,7 @@ 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'
template_name = 'tvorba/archiv/cislo_vysledkovka.tex'
content_type = 'text/plain; charset=UTF8'
def get_object(self, queryset=None):
@ -473,7 +473,7 @@ class PosledniCisloVysledkovkaView(generic.DetailView):
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'
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'
@ -517,7 +517,7 @@ def TitulyView(request, rocnik, cislo):
else:
jmenovci = True
return render(request, 'seminar/archiv/tituly.tex',
return render(request, 'tvorba/archiv/tituly.tex',
{'resitele': resitele,'jmenovci':jmenovci},content_type="text/plain")
@ -548,7 +548,7 @@ def group_by_rocnik(clanky):
# 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'
template_name = 'tvorba/clanky/resitelske_clanky.html'
# FIXME: QuerySet není pole!
def get_queryset(self):
@ -564,7 +564,7 @@ class ClankyResitelView(generic.ListView):
# 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'
# template_name = 'tvorba/clanky/organizatorske_clanky.html'
# queryset = Problem.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')

View file

@ -1 +1,6 @@
from solo.admin import SingletonModelAdmin
from django.contrib import admin
from .models import Nastaveni
admin.site.register(Nastaveni, SingletonModelAdmin)

View file

@ -11,7 +11,7 @@ from django.views import generic
import novinky.views
import seminar.utils
import seminar.views
import tvorba.views
from personalni.models import Resitel
from seminar import models as m
@ -34,7 +34,7 @@ class TitulniStranaView(generic.ListView):
# Aktuální témata
nazvy_a_odkazy_na_aktualni_temata = []
akt_temata = seminar.views.aktualni_temata(nastaveni.aktualni_rocnik)
akt_temata = tvorba.views.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