@ -1,4 +1,4 @@
# coding:utf-8
from django . shortcuts import get_object_or_404 , render , redirect
from django . http import HttpResponse , HttpResponseRedirect , HttpResponseForbidden , JsonResponse
@ -17,6 +17,7 @@ from django.contrib.auth.models import User, Permission
from django . contrib . auth . mixins import LoginRequiredMixin
from django . db import transaction
from django . core import serializers
from django . core . exceptions import PermissionDenied
from django . forms . models import model_to_dict
import seminar . models as s
@ -120,15 +121,57 @@ class TNLData(object):
self . appendable_siblings = tnltt . appendableChildren ( self . parent )
else :
self . appendable_siblings = [ ]
@classmethod
def public_above ( cls , anode ) :
""" Returns output of verejne for closest Rocnik, Cislo or Problem above.
( All of them have method verejne . ) """
parent = anode # chceme začít už od konkrétního node včetně
while True :
rocnik = isinstance ( parent , s . RocnikNode )
cislo = isinstance ( parent , s . CisloNode )
uloha = ( isinstance ( parent , s . UlohaVzorakNode ) or
isinstance ( parent , s . UlohaZadaniNode ) )
tema = isinstance ( parent , s . TemaVCisleNode )
if ( rocnik or cislo or uloha or tema ) or parent == None :
break
else :
parent = treelib . get_parent ( parent )
if rocnik :
return parent . rocnik . verejne ( )
elif cislo :
return parent . cislo . verejne ( )
elif uloha :
return parent . uloha . verejne ( )
elif tema :
return parent . tema . verejne ( )
elif None :
print ( " Existuje TreeNode, který není pod číslem, ročníkem, úlohou "
" ani tématem. {} " . format ( anode ) )
return False
@classmethod
def all_public_children ( cls , anode ) :
for ch in treelib . all_children ( anode ) :
if TNLData . public_above ( ch ) :
yield ch
else :
continue
@classmethod
def from_treenode ( cls , anode , parent = None , index = None ) :
out = cls ( anode , parent , index )
for ( idx , ch ) in enumerate ( treelib . all_children ( anode ) ) :
# FIXME přidat filtrování na veřejnost
outitem = cls . from_treenode ( ch , out , idx )
def from_treenode ( cls , anode , user , parent = None , index = None ) :
if TNLData . public_above ( anode ) or user . has_perm ( ' auth.org ' ) :
out = cls ( anode , parent , index )
else :
raise PermissionDenied ( )
if user . has_perm ( ' auth.org ' ) :
enum_children = enumerate ( treelib . all_children ( anode ) )
else :
enum_children = enumerate ( TNLData . all_public_children ( anode ) )
for ( idx , ch ) in enum_children :
outitem = cls . from_treenode ( ch , user , out , idx )
out . children . append ( outitem )
out . add_edit_options ( )
return out
@ -195,7 +238,7 @@ class TreeNodeView(generic.DetailView):
def get_context_data ( self , * * kwargs ) :
context = super ( ) . get_context_data ( * * kwargs )
context [ ' tnldata ' ] = TNLData . from_treenode ( self . object )
context [ ' tnldata ' ] = TNLData . from_treenode ( self . object , self . request . user )
return context
class TreeNodeJSONView ( generic . DetailView ) :
@ -203,7 +246,7 @@ class TreeNodeJSONView(generic.DetailView):
def get ( self , request , * args , * * kwargs ) :
self . object = self . get_object ( )
data = TNLData . from_treenode ( self . object ) . to_json ( )
data = TNLData . from_treenode ( self . object , self . request . user ) . to_json ( )
return JsonResponse ( data )
@ -332,6 +375,7 @@ class ProblemView(generic.DetailView):
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 :
@ -339,11 +383,11 @@ class ProblemView(generic.DetailView):
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 )
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 )
tnl_vzorak = TNLData . from_treenode ( self . object . ulohavzoraknode )
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
@ -385,16 +429,16 @@ class AktualniZadaniView(generic.TemplateView):
# )
#
def ZadaniTemataView ( request ) :
nastaveni = get_object_or_404 ( Nastaveni )
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 ' ,
{
' tematka ' : temata ,
' verejne ' : verejne ,
} ,
)
nastaveni = get_object_or_404 ( Nastaveni )
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 ' ,
{
' tematka ' : temata ,
' verejne ' : verejne ,
} ,
)
# nastaveni = get_object_or_404(Nastaveni)
@ -945,18 +989,30 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None):
if hlavni_problemy is None :
hlavni_problemy = hlavni_problemy_cisla ( cislo )
def ne_clanek_ne_konfera ( problem ) :
return not ( isinstance ( problem . get_real_instance ( ) , m . Clanek ) or isinstance ( problem . get_real_instance ( ) , m . Konfera ) )
temata_a_spol = list ( filter ( ne_clanek_ne_konfera , hlavni_problemy ) )
def cosi ( problem ) :
return problem . id
hlavni_problemy_slovnik = { }
for hp in hlavni_problemy :
for hp in temata_a_spol :
hlavni_problemy_slovnik [ hp . id ] = { }
hlavni_problemy_slovnik [ - 1 ] = { }
# zakládání prázdných záznamů pro řešitele
cislobody = { }
for ar in aktivni_resitele :
# řešitele převedeme na řetězec pomocí unikátního id
cislobody [ ar . id ] = " "
for hp in hlavni_problemy :
for hp in temata_a_spol :
slovnik = hlavni_problemy_slovnik [ hp . id ]
slovnik [ ar . id ] = " "
hlavni_problemy_slovnik [ - 1 ] [ ar . id ] = " "
# vezmeme všechna řešení s body do daného čísla
reseni_do_cisla = Reseni . objects . prefetch_related ( ' problem ' , ' resitele ' ,
@ -969,7 +1025,10 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None):
# řešení může řešit více problémů
for prob in list ( reseni . problem . all ( ) ) :
nadproblem = hlavni_problem ( prob )
nadproblem_slovnik = hlavni_problemy_slovnik [ nadproblem . id ]
if ne_clanek_ne_konfera ( nadproblem ) :
nadproblem_slovnik = hlavni_problemy_slovnik [ nadproblem . id ]
else :
nadproblem_slovnik = hlavni_problemy_slovnik [ - 1 ]
# a mít více hodnocení
for hodn in list ( reseni . hodnoceni_set . all ( ) ) :
@ -1014,11 +1073,26 @@ def vysledkovka_cisla(cislo, context=None):
# vytvoříme jednotlivé sloupce výsledkovky
radky_vysledkovky = [ ]
i = 0
def ne_clanek_ne_konfera ( problem ) :
return not ( isinstance ( problem . get_real_instance ( ) , m . Clanek ) or isinstance ( problem . get_real_instance ( ) , m . Konfera ) )
temata_a_spol = list ( filter ( ne_clanek_ne_konfera , hlavni_problemy ) )
# def not_empty(value):
# return value != ''
#
# je_nejake_ostatni = any(filter(not_empty, hlavni_problemy_slovnik[-1].values())) > 0
je_nejake_ostatni = len ( hlavni_problemy ) - len ( temata_a_spol ) > 0
for ar_id in setrizeni_resitele_id :
# získáme seznam bodů za problémy pro daného řešitele
problemy = [ ]
for hp in hlavni_problemy :
for hp in temata_a_spol :
problemy . append ( hlavni_problemy_slovnik [ hp . id ] [ ar_id ] )
if je_nejake_ostatni :
problemy . append ( hlavni_problemy_slovnik [ - 1 ] [ ar_id ] )
# vytáhneme informace pro daného řešitele
radek = RadekVysledkovkyCisla (
poradi [ i ] , # pořadí
@ -1034,7 +1108,8 @@ def vysledkovka_cisla(cislo, context=None):
# vytahané informace předáváme do kontextu
context [ ' cislo ' ] = cislo
context [ ' radky_vysledkovky ' ] = radky_vysledkovky
context [ ' problemy ' ] = hlavni_problemy
context [ ' problemy ' ] = temata_a_spol
context [ ' ostatni ' ] = je_nejake_ostatni
#context['v_cisle_zadane'] = TODO
#context['resene_problemy'] = resene_problemy
return context
@ -1063,6 +1138,7 @@ class CisloView(generic.DetailView):
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 ( )
# vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky
return vysledkovka_cisla ( cislo , context )
@ -1079,6 +1155,30 @@ class ArchivTemataView(generic.ListView):
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 = Cislo . objects . get ( rocnik = self . kwargs . get ( ' frocnik ' ) , poradi = self . kwargs . get ( ' fcislo ' ) )
tocislo = Cislo . objects . get ( rocnik = self . kwargs . get ( ' trocnik ' ) , poradi = self . kwargs . get ( ' tcislo ' ) )
resitele = aktivniResitele ( tocislo )
frombody = body_resitelu ( resitele , fromcislo )
tobody = body_resitelu ( resitele , tocislo )
outlist = [ ]
for ( aid , tbody ) in tobody . items ( ) :
fbody = frombody . get ( aid , 0 )
resitel = Resitel . objects . get ( pk = aid )
ftitul = resitel . get_titul ( fbody )
ttitul = resitel . get_titul ( tbody )
if ftitul != ttitul :
outlist . append ( { ' jmeno ' : resitel . osoba . plne_jmeno ( ) , ' ftitul ' : ftitul , ' ttitul ' : ttitul } )
context [ ' zmeny ' ] = outlist
return context
### Generovani vysledkovky
class CisloVysledkovkaView ( CisloView ) :
@ -1332,6 +1432,12 @@ class ResitelView(LoginRequiredMixin,generic.DetailView):
### Formulare
# pro přidání políčka do formuláře je potřeba
# - mít v modelu tu položku, kterou chci upravovat
# - přidat do views (prihlaskaView, resitelEditView)
# - přidat do forms
# - includovat do html
class AddSolutionView ( LoginRequiredMixin , FormView ) :
template_name = ' seminar/org/vloz_reseni.html '
form_class = f . VlozReseniForm
@ -1409,7 +1515,7 @@ def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data):
from django . forms . models import model_to_dict
def resitelEditView ( request ) :
err_logger = logging . getLogger ( ' seminar.prihlaska.problem ' )
## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately
## Načtení objektů Osoba a Resitel patřících k aktuálně přihlášenému uživateli
u = request . user
osoba_edit = Osoba . objects . get ( user = u )
resitel_edit = osoba_edit . resitel
@ -1448,6 +1554,7 @@ def resitelEditView(request):
resitel_edit . skola = fcd [ ' skola ' ]
resitel_edit . rok_maturity = fcd [ ' rok_maturity ' ]
resitel_edit . zasilat = fcd [ ' zasilat ' ]
resitel_edit . zasilat_cislo_emailem = fcd [ ' zasilat_cislo_emailem ' ]
if fcd . get ( ' skola ' ) :
resitel_edit . skola = fcd [ ' skola ' ]
else :
@ -1511,7 +1618,8 @@ def prihlaskaView(request):
r = Resitel (
rok_maturity = fcd [ ' rok_maturity ' ] ,
zasilat = fcd [ ' zasilat ' ]
zasilat = fcd [ ' zasilat ' ] ,
zasilat_cislo_emailem = fcd [ ' zasilat_cislo_emailem ' ]
)
r . save ( )