diff --git a/seminar/migrations/0078_otistenereseninode.py b/seminar/migrations/0078_otistenereseninode.py
new file mode 100644
index 00000000..2f426a17
--- /dev/null
+++ b/seminar/migrations/0078_otistenereseninode.py
@@ -0,0 +1,27 @@
+# Generated by Django 2.2.9 on 2020-03-18 23:59
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('seminar', '0077_auto_20200318_2146'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='OtisteneReseniNode',
+ fields=[
+ ('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.TreeNode')),
+ ('reseni', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='seminar.Reseni', verbose_name='reseni')),
+ ],
+ options={
+ 'verbose_name': 'Otištěné řešení (Node)',
+ 'verbose_name_plural': 'Otištěná řešení (Node)',
+ 'db_table': 'seminar_nodes_otistene_reseni',
+ },
+ bases=('seminar.treenode',),
+ ),
+ ]
diff --git a/seminar/models.py b/seminar/models.py
index 25e4130d..82b09944 100644
--- a/seminar/models.py
+++ b/seminar/models.py
@@ -1474,6 +1474,26 @@ class CastNode(TreeNode):
nadpis = models.CharField('Nadpis', max_length=100, help_text = 'Nadpis podvěšené části obsahu')
+ def aktualizuj_nazev(self):
+ self.nazev = "CastNode: "+str(self.nadpis)
+
+ def getOdkazStr(self):
+ return str(self.nadpis)
+
+class OtisteneReseniNode(TreeNode):
+ class Meta:
+ db_table = 'seminar_nodes_otistene_reseni'
+ verbose_name = 'Otištěné řešení (Node)'
+ verbose_name_plural = 'Otištěná řešení (Node)'
+ reseni = models.ForeignKey(Reseni,
+ on_delete=models.PROTECT,
+ verbose_name = 'reseni')
+
+ def aktualizuj_nazev(self):
+ self.nazev = "OtisteneReseniNode: "+str(self.reseni)
+
+ def getOdkazStr(self):
+ return str(self.reseni)
## FIXME: Logiku přesunout do views.
#class VysledkyBase(SeminarModelBase):
diff --git a/seminar/templates/seminar/treenode.html b/seminar/templates/seminar/treenode.html
new file mode 100644
index 00000000..0fd734ef
--- /dev/null
+++ b/seminar/templates/seminar/treenode.html
@@ -0,0 +1,10 @@
+{% extends "seminar/archiv/base_ulohy.html" %}
+
+{% load comments %}
+
+{% block content %}
+
+{%with obj=tnldata depth=1 template_name="seminar/treenode_recursive.html" %}
+ {%include template_name%}
+{%endwith%}
+{% endblock content %}
diff --git a/seminar/templates/seminar/treenode_recursive.html b/seminar/templates/seminar/treenode_recursive.html
new file mode 100644
index 00000000..0cf37d9a
--- /dev/null
+++ b/seminar/templates/seminar/treenode_recursive.html
@@ -0,0 +1,28 @@
+{% load treenodes %}
+{# {{depth}} #}
+
+{% if obj.node|isRocnik %}
+
Ročník {{obj.node.rocnik}}
+{% elif obj.node|isCislo %}
+
Číslo {{obj.node.cislo}}
+{% elif obj.node|isTemaVCisle %}
+
Téma {{obj.node.tema.nazev}}
+{% elif obj.node|isUlohaZadani %}
+
Úloha {{obj.node.uloha.kod_v_rocniku}} ({{obj.node.uloha.max_body}} b)
+{% elif obj.node|isUlohaVzorak %}
+
Řešení: {{obj.node.uloha.kod_v_rocniku}}
+{% elif obj.node|isText %}
+{{obj.node.text.na_web}}
+{% else %}
+Objekt jiného typu {{obj.node}}
+{% endif %}
+ {%if obj.children %}
+
+ {%for ch in obj.children %}
+ {%with obj=ch depth=depth|add:"1" template_name="seminar/treenode_recursive.html" %}
+ {%include template_name%}
+ {%endwith%}
+ {%endfor%}
+
+ {%endif%}
+
diff --git a/seminar/templatetags/treenodes.py b/seminar/templatetags/treenodes.py
new file mode 100644
index 00000000..0d60765e
--- /dev/null
+++ b/seminar/templatetags/treenodes.py
@@ -0,0 +1,49 @@
+from django import template
+import seminar.models as m
+
+register = template.Library()
+
+@register.filter
+def isRocnik(value):
+ return isinstance(value, m.RocnikNode)
+
+@register.filter
+def isCislo(value):
+ return isinstance(value, m.CisloNode)
+
+@register.filter
+def isCast(value):
+ return isinstance(value, m.CastNode)
+
+@register.filter
+def isText(value):
+ return isinstance(value, m.TextNode)
+
+@register.filter
+def isTemaVCisle(value):
+ return isinstance(value, m.TemaVCisleNode)
+
+@register.filter
+def isKonfera(value):
+ return isinstance(value, m.KonferaNode)
+
+@register.filter
+def isClanek(value):
+ return isinstance(value, m.ClanekNode)
+
+@register.filter
+def isUlohaVzorak(value):
+ return isinstance(value, m.UlohaVzorakNode)
+
+@register.filter
+def isUlohaZadani(value):
+ return isinstance(value, m.UlohaZadaniNode)
+
+@register.filter
+def isPohadka(value):
+ return isinstance(value, m.PohadkaNode)
+
+#@register.filter
+#def isOtisteneReseniNode(value):
+# return isinstance(value, m.OtisteneReseniNode)
+
diff --git a/seminar/treelib.py b/seminar/treelib.py
index cfb49d86..26b77d1d 100644
--- a/seminar/treelib.py
+++ b/seminar/treelib.py
@@ -1,6 +1,7 @@
from django.core.exceptions import ObjectDoesNotExist
# NOTE: node.prev a node.succ jsou implementovány přímo v models.TreeNode
# TODO: Všechny tyto funkce se naivně spoléhají na to, že jako parametr dostanou nějaký TreeNode (některé možná zvládnou i None)
+# TODO: Chceme, aby všechno nějak zvládlo None jako parametr.
# Slouží k debugování pro rychlé získání představy o podobě podstromu pod tímto TreeNode.
def print_tree(node,indent=0):
@@ -18,9 +19,19 @@ def safe_pred(node):
except ObjectDoesNotExist:
return None
+def first_brother(node):
+ if node is None:
+ return None
+ brother = node
+ while safe_pred(brother) is not None:
+ brother = safe_pred(brother)
+ return brother
+
# A to samé pro .father_of_first
def safe_father_of_first(node):
- return node.prev
+ first = first_brother(node)
+ try:
+ return first.father_of_first
except ObjectDoesNotExist:
return None
@@ -61,14 +72,34 @@ def general_prev(node):
# pred nyní nemá žádné potomky, takže je to poslední rekurzivní potomek původního předchůdce
return pred
-# Generátor bratrů
+# Generátor pravých bratrů (konkrétně sebe a následujících potomků)
# Generátor potomků níže spoléhá na to, že se tohle dá volat i s parametrem None.
-def all_brothers(node):
+def me_and_right_brothers(node):
current = node
while current is not None:
yield current
current = current.succ
+def right_brothers(node):
+ generator = me_and_right_brothers(node.succ)
+ for item in generator:
+ yield item
+
+# Generátor všech sourozenců (vč. sám sebe)
+def all_brothers(node):
+ # Najdeme prvního bratra
+ fb = first_brother(node)
+ marb = me_and_right_brothers(fb)
+ for cur in marb:
+ yield cur
+
+def all_proper_brothers(node):
+ all = all_brothers(node)
+ for br in all:
+ if br is node:
+ continue
+ yield br
+
# Generátor potomků
def all_children(node):
brothers = all_brothers(node.first_child)
@@ -76,44 +107,129 @@ def all_children(node):
yield br
# Generátor následníků v "the-right-order"
+# Bez tohoto vrcholu
+def all_following(node):
+ current = general_next(node)
+ while current is not None:
+ yield current
+ current = general_next(current)
## Filtrační hledání
# Najdi dalšího bratra nějakého typu, nebo None.
# hledá i podtřídy, i.e. get_next_brother_of_type(neco, TreeNode) je prostě succ.
-def get_next_brother_of_type(current, type):
- pass
-def get_prev_brother_of_type(current, type):
- pass
+def get_next_brother_of_type(node, type):
+ for current in right_brothers(node):
+ if isinstance(current, type):
+ return current
+ return None
+
+def get_prev_brother_of_type(node, type):
+ # Na tohle není rozumný generátor, ani ho asi nechceme, prostě to implementujeme cyklem.
+ current = node
+ while safe_pred(current) is not None:
+ current = safe_pred(current)
+ if isinstance(current, type):
+ return current
+ return None
# Totéž pro "the-right-order" pořadí
-def get_next_node_of_type(current, type):
- pass
-def get_next_node_of_type(current, type):
- pass
+def get_next_node_of_type(node, type):
+ for cur in all_folowing(node):
+ if isinstance(cur, type):
+ return cur
+ return None
+
+def get_prev_node_of_type(node, type):
+ # Na tohle není rozumný generátor, ani ho asi nechceme, prostě to implementujeme cyklem.
+ current = node
+ while general_prev(current) is not None:
+ current = general_prev(current)
+ if isinstance(current, type):
+ return current
+ return None
# Editace stromu:
def create_node_after(predecessor, type, **kwargs):
- pass
+ new_node = type.objects.create(**kwargs)
+ new_node.save()
+ succ = predecessor.succ
+ predecessor.succ = new_node
+ predecessor.save()
+ new_node.succ = succ
+ new_node.save()
# Vyrábí prvního syna, ostatní nalepí za (existují-li)
def create_child(parent, type, **kwargs):
- pass
+ new_node = type.objects.create(**kwargs)
+ new_node.save()
+ orig_child = parent.first_child
+ parent.first_child = new_node
+ parent.save()
+ if orig_child is not None:
+ # Přidáme původního prvního syna jako potomka nového vrcholu
+ new_node.succ = orig_child
+ new_node.save()
+
+def create_node_before(successor, type, **kwargs):
+ if safe_pred(successor) is not None:
+ # Easy: přidáme za předchůdce
+ create_node_after(successor.prev, type, **kwargs)
+ # Nemáme předchůdce, jsme tedy první z bratrů. Máme otce?
+ if safe_father_of_first(successor) is not None:
+ # Ano -> Easy: vyrobíme nového potomka
+ # NOTE: Tohle je možná trošku abuse implementace výše, ale to nevadí moc...
+ create_child(successor.father_of_first, type, **kwargs)
+ # Teď už easy: Jsme sirotci, takže se vyrobíme a našeho následníka si přidáme jako succ
+ new = type.objects.create(**kwargs)
+ new.succ = successor
+ new.save()
-def create_node_before(some, arguments, but, i, dont, know, which, yet):
- pass
- # Tohle bude hell.
# ValueError, pokud je (aspoň) jeden parametr None
def swap(node, other):
+ raise NotImplementedError("YAGNI (You aren't gonna need it).")
+
+# Exception, kterou některé metody při špatném použití mohou házet
+# Hlavní důvod je možnost informovat o selhání, aby se příslušný problém dal zobrazit na frontendu,
+class TreeLibError(RuntimeError):
pass
def swap_pred(node):
- pass
+ if node is None:
+ raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.")
+ pred = safe_pred(node)
+ if pred is None:
+ raise TreeLibError("Nelze posunout vlevo, není tam žádný další uzel.")
+ pre_pred = safe_pred(pred)
+ succ = node.succ
+
+ if pre_pred is not None:
+ pre_pred.succ = node
+ pre_pred.save()
+ node.succ = pred
+ node.save()
+ pred.succ = succ
+ pred.save()
+
def swap_succ(node):
- pass
+ if node is None:
+ raise TreeLibError("Nelze přesunout None. Tohle by se nemělo stát.")
+ succ = node.succ
+ if succ is None:
+ raise TreeLibError("Nelze posunout vpravo, není tam žádný další uzel")
+ pred = safe_pred(node)
+ post_succ = succ.succ
+
+ if pred is not None:
+ pred.succ = succ
+ pred.save()
+ succ.succ = node
+ succ.save()
+ node.succ = post_succ
+ node.save()
# Rotace stromu
# Dokumentace viz wiki:
diff --git a/seminar/urls.py b/seminar/urls.py
index 0cd3f5bb..48a4b754 100644
--- a/seminar/urls.py
+++ b/seminar/urls.py
@@ -8,8 +8,8 @@ from django.contrib.auth import views as auth_views
staff_member_required = user_passes_test(lambda u: u.is_staff)
urlpatterns = [
- path('aktualni/temata/', views.TemataRozcestnikView),
- path('/t/', views.TematkoView),
+# path('aktualni/temata/', views.TemataRozcestnikView),
+# path('/t/', views.TematkoView),
# REDIRECTy
path('jak-resit/', RedirectView.as_view(url='/co-je-MaM/jak-resit/')),
@@ -25,6 +25,7 @@ urlpatterns = [
path('rocnik//', views.RocnikView.as_view(), name='seminar_rocnik'),
path('cislo/./', views.CisloView.as_view(), name='seminar_cislo'),
path('problem//', views.ProblemView.as_view(), name='seminar_problem'),
+ path('treenode//', views.TreeNodeView.as_view(), name='seminar_treenode'),
#path('problem/(?P\d+)/(?P\d+)/', views.PrispevekView.as_view(), name='seminar_problem_prispevek'),
# Soustredeni
@@ -59,8 +60,8 @@ urlpatterns = [
),
# Zadani
- path('zadani/aktualni/', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
- path('zadani/temata/', views.ZadaniTemataView, name='seminar_temata'),
+# path('zadani/aktualni/', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
+# path('zadani/temata/', views.ZadaniTemataView, name='seminar_temata'),
#path('zadani/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_vysledky'),
path('stare-novinky/', views.StareNovinkyView.as_view(), name='stare_novinky'),
@@ -107,9 +108,6 @@ urlpatterns = [
path('auth/login/', views.LoginView.as_view(), name='login'),
path('auth/logout/', views.LogoutView.as_view(), name='logout'),
path('auth/resitel/', views.ResitelView.as_view(), name='seminar_resitel'),
- path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
- path('autocomplete/resitel/',views.ResitelAutocomplete.as_view(), name='autocomplete_resitel'),
- path('autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
path('auth/reset_password/', views.PasswordResetView.as_view(), name='reset_password'),
path('auth/change_password/', views.PasswordChangeView.as_view(), name='change_password'),
path('auth/reset_password_done/', views.PasswordResetDoneView.as_view(), name='reset_password_done'),
@@ -117,6 +115,10 @@ urlpatterns = [
path('auth/reset_password_complete/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'),
path('auth/resitel_edit', views.resitelEditView, name='seminar_resitel_edit'),
+ # Autocomplete
+ path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
+ path('autocomplete/resitel/',views.ResitelAutocomplete.as_view(), name='autocomplete_resitel'),
+ path('autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
path('temp/add_solution', views.AddSolutionView.as_view(),name='seminar_vloz_reseni'),
path('temp/submit_solution', views.SubmitSolutionView.as_view(),name='seminar_nahraj_reseni'),
diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py
index 3dcf1331..945d283e 100644
--- a/seminar/views/views_all.py
+++ b/seminar/views/views_all.py
@@ -19,7 +19,7 @@ from django.db import transaction
import seminar.models as s
from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek, Osoba, Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
-from seminar import utils
+from seminar import utils,treelib
from .unicodecsv import UnicodeWriter
from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm
import seminar.forms as f
@@ -83,131 +83,110 @@ class ObalkovaniView(generic.ListView):
context['cislo'] = self.cislo
return context
+class TNLData(object):
+ def __init__(self,anode):
+ self.node = anode
+ self.children = []
+def treenode_strom_na_seznamy(node):
+ out = TNLData(node)
+ for ch in treelib.all_children(node):
+ outitem = treenode_strom_na_seznamy(ch)
+ out.children.append(outitem)
+ return out
-def AktualniZadaniView(request):
- nastaveni = get_object_or_404(Nastaveni)
- verejne = nastaveni.aktualni_cislo.verejne()
- problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany')
- ulohy = problemy.filter(typ = 'uloha').order_by('kod')
- serialy = problemy.filter(typ = 'serial').order_by('kod')
- jednorazove_problemy = [ulohy, serialy]
- return render(request, 'seminar/zadani/AktualniZadani.html',
- {'nastaveni': nastaveni,
- 'jednorazove_problemy': jednorazove_problemy,
- 'temata': verejna_temata(nastaveni.aktualni_rocnik),
- 'verejne': verejne,
- },
- )
-
-def ZadaniTemataView(request):
- 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,
- }
- )
+class TreeNodeView(generic.DetailView):
+ model = s.TreeNode
+ template_name = 'seminar/treenode.html'
-# TODO Napsat tuto funkci znovu rekurzivně podle Jethrorad. Potom se podívat, jak lehce se dá modifikovat pro Rozcestník. Pokud lehce, rozšířit ji. Pokud složitě - použít tuhle
-def vytahniZLesaSeznam(tematko, koren, pouze_zajimave=False):
- returnVal = []
-
- stack = []
- stack.append((koren.first_child, 0, False)) #Tuple of node, depth and relevance
-
- while len(stack) > 0:
- wn, wd, wr = stack.pop()
-
- if wn.succ != None:
- stack.append((wn.succ, wd, wr))
- if isinstance(wn, s.TemaVCisleNode):
- print("TEMA")
- print(wn.tema.id)
- print(tematko.id)
- if wn.tema.id == tematko.id:
- returnVal.append((posledni_cislo, 0))
- print("PRIDANO")
- wr = True
- wd = 1
-
- if wn.srolovatelne:
- tagOpen = s.Text(na_web = "Otevírací srolovací tag")
- tagOpenNode = s.TextNode(text = tagOpen)
- tagClose = s.Text(na_web = "Zavírací srolovací tag")
- tagCloseNode = s.TextNode(text = tagClose)
- stack.append((tagCloseNode, wd, True))
-
- if wn.first_child != None:
- stack.append((wn.first_child, wd + 1, wr))
-
- if isinstance(wn, s.CisloNode):
- posledni_cislo = wn
- print(wn)
-
- if wr:
- print("ZAJIMAVE")
- if pouze_zajimave:
- if not wn.zajimave:
- continue
- returnVal.append((wn, wd))
- return returnVal
-
-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 get_context_data(self,**kwargs):
+ context = super().get_context_data(**kwargs)
+ context['tnldata'] = treenode_strom_na_seznamy(self.object)
+ return context
-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 AktualniZadaniView(request):
+# nastaveni = get_object_or_404(Nastaveni)
+# verejne = nastaveni.aktualni_cislo.verejne()
+# problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany')
+# ulohy = problemy.filter(typ = 'uloha').order_by('kod')
+# serialy = problemy.filter(typ = 'serial').order_by('kod')
+# jednorazove_problemy = [ulohy, serialy]
+# return render(request, 'seminar/zadani/AktualniZadani.html',
+# {'nastaveni': nastaveni,
+# 'jednorazove_problemy': jednorazove_problemy,
+# 'temata': verejna_temata(nastaveni.aktualni_rocnik),
+# 'verejne': verejne,
+# },
+# )
+#
+#def ZadaniTemataView(request):
+# 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)