# coding:utf-8
from django . shortcuts import get_object_or_404 , render
from django . http import HttpResponse , HttpResponseRedirect , HttpResponseForbidden , JsonResponse
from django . urls import reverse , reverse_lazy
from django . core . exceptions import PermissionDenied , ObjectDoesNotExist
from django . views import generic
from django . utils . translation import ugettext as _
from django . http import Http404 , HttpResponseBadRequest , HttpResponseRedirect
from django . db . models import Q , Sum , Count
from django . views . decorators . csrf import ensure_csrf_cookie
from django . views . generic . edit import FormView , CreateView
from django . contrib . auth import authenticate , login , get_user_model , logout
from django . contrib . auth import views as auth_views
from django . contrib . auth . models import User
from django . contrib . auth . mixins import LoginRequiredMixin
from django . db import transaction
from dal import autocomplete
import seminar . models as s
from . 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 . import utils
from . unicodecsv import UnicodeWriter
from . forms import PrihlaskaForm , LoginForm , ProfileEditForm
import seminar . forms as f
from datetime import timedelta , date , datetime
from django . utils import timezone
from itertools import groupby
import tempfile
import subprocess
import shutil
import os
import os . path as op
from django . conf import settings
import unicodedata
import json
import traceback
import sys
import csv
import logging
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 ' )
def temata_v_rocniku ( rocnik ) :
return Problem . objects . filter ( typ = Problem . TYP_TEMA , rocnik = rocnik )
def get_problemy_k_tematu ( tema ) :
return Problemy . objects . filter ( nadproblem = tema )
class VlozBodyView ( generic . ListView ) :
template_name = ' seminar/org/vloz_body.html '
def get_queryset ( self ) :
self . tema = get_object_or_404 ( Problem , id = self . kwargs [ ' tema ' ] )
print ( self . tema )
self . problemy = Problem . objects . filter ( nadproblem = self . tema )
print ( self . problemy )
self . reseni = Reseni . objects . filter ( problem__in = self . problemy )
print ( self . reseni )
return self . reseni
class ObalkovaniView ( generic . ListView ) :
template_name = ' seminar/org/obalkovani.html '
def get_queryset ( self ) :
rocnik = get_object_or_404 ( Rocnik , rocnik = self . kwargs [ ' rocnik ' ] )
cislo = get_object_or_404 ( Cislo , rocnik = rocnik , poradi = self . kwargs [ ' cislo ' ] )
self . cislo = cislo
self . hodnoceni = s . Hodnoceni . objects . filter ( cislo_body = cislo )
self . reseni = Reseni . objects . filter ( hodnoceni__in = self . hodnoceni ) . annotate ( Sum ( ' hodnoceni__body ' ) ) . annotate ( Count ( ' hodnoceni ' ) ) . order_by ( ' resitele__osoba ' )
return self . reseni
def get_context_data ( self , * * kwargs ) :
context = super ( ObalkovaniView , self ) . get_context_data ( * * kwargs )
print ( self . cislo )
context [ ' cislo ' ] = self . cislo
return context
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 ,
}
)
# 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 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
# vysledkovka = vysledkovka_rocniku(nastaveni.aktualni_rocnik)
# # kdyz neni verejna vysledkovka, tak zobraz starou
# if not vysledkovka:
# try:
# minuly_rocnik = Rocnik.objects.get(
# prvni_rok=(nastaveni.aktualni_rocnik.prvni_rok-1))
# vysledkovka = vysledkovka_rocniku(minuly_rocnik)
# except ObjectDoesNotExist:
# pass
# # vysledkovka s neverejnyma vysledkama
# vysledkovka_s_neverejnymi = vysledkovka_rocniku(nastaveni.aktualni_rocnik, jen_verejne=False)
# return render(
# request,
# 'seminar/zadani/AktualniVysledkovka.html',
# {
# 'nastaveni': nastaveni,
# 'vysledkovka': vysledkovka,
# 'vysledkovka_s_neverejnymi': vysledkovka_s_neverejnymi,
# }
# )
### Titulni strana
class TitulniStranaView ( generic . ListView ) :
model = Novinky
template_name = ' seminar/titulnistrana.html '
queryset = Novinky . objects . order_by ( ' -datum ' ) [ : 5 ]
def get_context_data ( self , * * kwargs ) :
context = super ( TitulniStranaView , self ) . get_context_data ( * * kwargs )
nastaveni = get_object_or_404 ( Nastaveni )
# zjisteni spravneho terminu
if nastaveni . aktualni_cislo . datum_deadline_soustredeni :
cas_deadline_soustredeni = nastaveni . aktualni_cislo . \
datum_deadline_soustredeni
if ( datetime . now ( ) . date ( ) < = cas_deadline_soustredeni ) :
cas_deadline = cas_deadline_soustredeni
deadline_soustredeni = True
else :
cas_deadline = nastaveni . aktualni_cislo . datum_deadline
deadline_soustredeni = False
else :
cas_deadline = nastaveni . aktualni_cislo . datum_deadline
deadline_soustredeni = False
# Pokud neni zverejnene cislo nezverejnuj odpocet
if nastaveni . aktualni_cislo . verejne ( ) :
# pokus se zjistit termin odeslani a pokud neni zadany,
# nezverejnuj odpocet
context [ ' deadline_soustredeni ' ] = deadline_soustredeni
try :
context [ ' dead ' ] = datetime . combine ( cas_deadline ,
datetime . max . time ( ) )
context [ ' ted ' ] = datetime . now ( )
except :
context [ ' dead ' ] = None
else :
context [ ' dead ' ] = None
context [ ' deadline_soustredeni ' ] = deadline_soustredeni
return context
class StareNovinkyView ( generic . ListView ) :
model = Novinky
template_name = ' seminar/stare_novinky.html '
queryset = Novinky . objects . filter ( zverejneno = True ) . order_by ( ' -datum ' )
### Co je M&M
# Organizatori
def aktivniOrganizatori ( datum = timezone . now ( ) ) :
return Organizator . objects . exclude (
organizuje_do__isnull = False ,
organizuje_do__lt = datum
) . order_by ( ' osoba__jmeno ' )
class CojemamOrganizatoriView ( generic . ListView ) :
model = Organizator
template_name = ' seminar/cojemam/organizatori.html '
queryset = aktivniOrganizatori ( )
def get_context_data ( self , * * kwargs ) :
context = super ( CojemamOrganizatoriView , self ) . get_context_data ( * * kwargs )
context [ ' aktivni ' ] = True
return context
class CojemamOrganizatoriStariView ( generic . ListView ) :
model = Organizator
template_name = ' seminar/cojemam/organizatori.html '
queryset = Organizator . objects . exclude (
id__in = aktivniOrganizatori ( ) ) . order_by ( ' -organizuje_do ' )
### 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 )
vyska = 297 # px
sirka = 210 # px
cisla = Cislo . objects . filter ( verejne_db = True ) [ : 10 ]
png_dir = op . join ( settings . MEDIA_ROOT , " cislo " , " png " )
# seznam [(url obrázku, číslo)]
urls = [ ]
for i , c in enumerate ( cisla ) :
if not c . pdf :
continue
filename = os . path . split ( c . pdf . file . name ) [ 1 ] . split ( " . " ) [ 0 ]
png_filename = " {} - {} px.png " . format ( filename , vyska )
# Pokud obrázek neexistuje nebo není aktuální, vytvoř jej
png_path = op . join ( png_dir , png_filename )
if not op . exists ( png_path ) or \
op . getmtime ( png_path ) < op . getmtime ( c . pdf . path ) :
subprocess . call ( [
" convert " ,
" -density " , " 180x180 " ,
" -geometry " , " {} x {} " . format ( vyska , vyska ) ,
" -background " , " white " ,
" -flatten " ,
" -rotate " , str ( 90 * i ) ,
" {} [0] " . format ( c . pdf . path ) , # titulní strana
png_path
] )
urls . append (
( op . join ( settings . MEDIA_URL , " cislo " , " png " , png_filename ) , c )
)
vyska , sirka = sirka , vyska / 2
tags = [ ]
def spirala ( urls , tags , idx ) :
""" Rekurzivně prochází urls a generuje strom elementů do tags """
if idx > = len ( urls ) :
return
img_url , cislo = urls [ idx ]
tags . append (
" <div style= ' top: {} % ;left: {} % ;width: {} % ;height: {} % ; ' > "
. format (
50 if idx % 4 == 2 else 0 ,
50 if idx % 4 == 1 else 0 ,
50 if idx % 2 == 1 else 100 ,
50 if idx > 0 and idx % 2 == 0 else 100
)
)
tags . append ( " <a href= ' {} ' title= ' {} ' > " . format (
cislo . verejne_url ( ) , cislo . kod ( )
) )
tags . append (
" <img src= ' {} ' style= ' top: {} % ;left: {} % ;width: {} % ;height: {} % ; ' > "
. format (
img_url ,
50 if idx % 4 == 3 else 0 ,
50 if idx % 4 == 2 else 0 ,
50 if idx % 2 == 0 else 100 ,
50 if idx % 2 == 1 else 100
)
)
tags . append ( " </a> " )
spirala ( urls , tags , idx + 1 )
tags . append ( " </div> " )
spirala ( urls , tags , 0 )
context [ " nahledy " ] = " \n " . join ( tags )
return context
### Výsledky
# ze setřízeného(!) seznamu všech bodů vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.)
def sloupec_s_poradim ( seznam_s_body ) :
aktualni_poradi = 1
sloupec_s_poradim = [ ]
# seskupíme seznam všech bodů podle hodnot
for index in range ( 0 , len ( seznam_s_body ) ) :
# pokud je pořadí větší než číslo řádku, tak jsme vypsali větší rozsah a chceme
# vypsat už jen prázdné místo, než dojdeme na správný řádek
if ( index + 1 ) < aktualni_poradi :
sloupec_s_poradim . append ( " " )
continue
velikost_skupiny = 0
# zjistíme počet po sobě jdoucích stejných hodnot
while seznam_s_body [ index ] == seznam_s_body [ index + velikost_skupiny ] :
velikost_skupiny = velikost_skupiny + 1
# na konci musíme ošetřit přetečení seznamu
if ( index + velikost_skupiny ) > len ( seznam_s_body ) - 1 :
break
# pokud je velikost skupiny 1, vypíšu pořadí
if velikost_skupiny == 1 :
sloupec_s_poradim . append ( " {} . " . format ( aktualni_poradi ) )
# pokud je skupina větší, vypíšu rozsah
else :
sloupec_s_poradim . append ( " {} .– {} . " . format ( aktualni_poradi ,
aktualni_poradi + velikost_skupiny - 1 ) )
# zvětšíme aktuální pořadí o tolik, kolik pozic bylo přeskočeno
aktualni_poradi = aktualni_poradi + velikost_skupiny
return sloupec_s_poradim
# spočítá součet bodů získaných daným řešitelem za zadaný problém a všechny jeho podproblémy
def __soucet_resitele_problemu ( problem , resitel , cislo , soucet ) :
# sečteme body za daný problém přes všechna řešení daného problému
# od daného řešitele
reseni_resitele = problem . hodnoceni_set . filter ( reseni__resitele = resitel ,
cislo_body = cislo )
# XXX chyba na řádku výše - řešení může mít více řešitelů, asi chceme contains
# nebo in
for r in reseni_resitele :
soucet + = r . body
# a přičteme k tomu hodnocení všech podproblémů
for p in problem . podproblem . all ( ) :
# i přes jméno by to měla být množina jeho podproblémů
soucet + = __soucet_resitele_problemu ( p , resitel , soucet )
return soucet
# spočítá součet všech bodů ze všech podproblémů daného problému daného řešitele
def body_resitele_problemu_v_cisle ( problem , resitel , cislo ) :
# probably FIXED: nezohledňuje číslo, do kterého se body počítají
return __soucet_resitele_problemu ( problem , resitel , cislo , 0 )
# vrátí list všech problémů s body v daném čísle, které již nemají nadproblém
def hlavni_problemy_cisla ( cislo ) :
hodnoceni = cislo . hodnoceni . select_related ( ' problem ' , ' reseni ' ) . all ( ) # hodnocení, která se vážou k danému číslu
reseni = [ h . reseni for h in hodnoceni ]
problemy = [ h . problem for h in hodnoceni ]
problemy_set = set ( problemy ) # chceme každý problém unikátně,
problemy = ( list ( problemy_set ) ) # převedení na množinu a zpět to zaručí
# hlavní problémy čísla
# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém)
hlavni_problemy = [ ]
for p in problemy :
while not ( p . nadproblem == None ) :
p = p . nadproblem
hlavni_problemy . append ( p )
# zunikátnění
hlavni_problemy_set = set ( hlavni_problemy )
hlavni_problemy = list ( hlavni_problemy_set )
hlavni_problemy . sort ( key = lambda k : k . kod_v_rocniku ( ) ) # setřídit podle t1, t2, c3, ...
return hlavni_problemy
def body_resitele_odjakziva ( resitel ) :
body = 0
resitelova_hodnoceni = Hodnoceni . objects . select_related ( ' body ' ) . all ( ) . filter ( reseni_resitele = resitel )
# TODO: v radku nahore chceme _in nebo _contains
for hodnoceni in resitelova_hodnoceni :
body = body + hodnoceni . body
return body
# spočítá součet všech bodů řešitele za dané číslo
def body_resitele_v_cisle ( resitel , cislo ) :
hlavni_problemy = hlavni_problemy_cisla ( cislo )
body_resitele = 0
for h in hlavni_problemy :
body_resitele = body_resitele + body_resitele_problemu_v_cisle ( h , resitel , cislo )
# TODO: je rozdíl mezi odevzdanou úlohou za 0 a tím, když řešitel nic neodevzdal
# řešit přes kontrolu velikosti množiny řešení daného problému do daného čísla?
# Tady to ale nevadí, tady se počítá součet za číslo.
return body_resitele
# spočítá součet všech bodů řešitele za daný rok (nebo jen do daného čísla včetně)
def body_resitele_v_rocniku ( resitel , rocnik , do_cisla = None ) :
# pokud do_cisla=None, tak do posledního čísla v ročníku
# do_cisla je objekt Cislo
cisla = rocnik . cisla . all ( ) # funkce vrátí pole objektů
# Cislo už lexikograficky setřízené, viz models
body = 0
for cislo in cisla :
if cislo . poradi == do_cisla . poradi : break
# druhá část zaručuje, že máme výsledky do daného čísla včetně
body = body + body_resitele_v_cisle ( resitel , cislo )
return body
#def vysledkovka_rocniku(rocnik, jen_verejne=True):
# """Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve
# formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html"
# """
#
# #vyberu vsechny vysledky z rocniku
# cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__rocnik=rocnik).order_by('cislo')
# if jen_verejne:
# cisla_v_rocniku = cisla_v_rocniku.filter(cislo__verejna_vysledkovka=True)
#
# #pokud žádné nejsou, výsledkovka se nezobrazí
# if not cisla_v_rocniku:
# return None
#
# #vybere vsechny vysledky z posledniho (verejneho) cisla a setridi sestupne dle bodu
# vysledky = list(cisla_v_rocniku.filter(cislo = cisla_v_rocniku[0].poradi).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno').select_related('resitel'))
#
# class Vysledkovka:
# def __init__(self):
# self.rocnik = rocnik.rocnik
# self.radky = []
# self.cisla = []
#
# vysledkovka = Vysledkovka()
# vysledkovka.cisla = (rocnik.verejne_vysledkovky_cisla() if jen_verejne else rocnik.cisla.all().order_by('cislo'))
#
# # doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině
# for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky):
# v.poradi = poradi
# v.resitel.rocnik = v.resitel.rocnik(rocnik)
#
# verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__rocnik=rocnik, cislo=cisla_v_rocniku[0].poradi)
# if jen_verejne:
# verejne_vysl_odjakziva = verejne_vysl_odjakziva.filter(cislo__verejna_vysledkovka=True)
#
# v.body_odjakziva = verejne_vysl_odjakziva.filter(resitel = v.resitel)[0].body
# v.titul = v.resitel.get_titul(v.body_odjakziva)
# v.body_rocnik = v.body
# v.body_cisla = []
#
# #pokud pro dany rok a cislo nema resitel vysledky, ma defaultne 0
# for cis in vysledkovka.cisla:
# if not jen_verejne or cis.verejna_vysledkovka:
# #seznam vysledku se spravnym rocnikem a cislem pro resitele
# #zobrazim jen je-li vysledkovka verejna
# body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik=rocnik).filter(cislo = cis).filter(resitel = v.resitel)
# if body_za_cislo:
# #neprazdne vysledky by mely obsahovat prave jeden vysledek
# v.body_cisla.append(body_za_cislo[0].body)
# else:
# #resitel nema za cislo body
# v.body_cisla.append(0)
#
# vysledkovka.radky.append(v)
#
# return vysledkovka
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 ( )
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 ( RocnikView , self ) . get_context_data ( * * kwargs )
#context['vysledkovka'] = vysledkovka_rocniku(context["rocnik"])
#context['vysledkovka_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False)
context [ ' temata_v_rocniku ' ] = verejna_temata ( context [ " rocnik " ] )
return context
class ProblemView ( generic . DetailView ) :
model = Problem
def _je_clanek ( self , problem ) :
return problem . typ in [ Problem . TYP_ORG_CLANEK , Problem . TYP_RES_CLANEK ]
def get_template_names ( self , * * kwargs ) :
context = super ( ProblemView , self ) . get_context_data ( * * kwargs )
return [ ' seminar/archiv/problem_ ' + ( ' clanek.html ' if self . _je_clanek ( context [ ' problem ' ] ) else ' uloha_tema.html ' ) ]
def get_context_data ( self , * * kwargs ) :
context = super ( ProblemView , self ) . get_context_data ( * * kwargs )
if not context [ ' problem ' ] . verejne ( ) and not self . request . user . is_staff :
raise PermissionDenied ( )
if context [ ' problem ' ] . typ == Problem . TYP_RES_CLANEK :
context [ ' reseni ' ] = Reseni . objects . filter ( problem = context [ ' problem ' ] ) . select_related ( ' resitel ' ) . order_by ( ' resitel__prijmeni ' )
return context
class VysledkyResitele ( object ) :
""" Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový
počet bodů za konkrétní ročník do daného čísla a za dané číslo . """
def __init__ ( self , resitel , cislo , rocnik ) :
self . resitel = resitel
self . cislo = cislo
self . body_cislo = body_resitele_v_cisle ( resitel , cislo )
self . body = [ ]
self . rocnik = rocnik
self . body_rocnik = body_resitele_v_rocniku ( resitel , rocnik , cislo )
self . body_celkem_odjakziva = resitel . vsechny_body ( )
self . poradi = 0
class CisloView ( generic . DetailView ) :
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 )
## TODO upravit dle nového modelu
cislo = context [ ' cislo ' ]
hlavni_problemy = hlavni_problemy_cisla ( cislo )
## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele
## TODO možná chytřeji vybírat aktivní řešitele
## chceme letos něco poslal
aktivni_resitele = Resitel . objects . filter (
rok_maturity__gte = cislo . rocnik . druhy_rok ( ) )
# TODO: zkusit hodnoceni__rocnik...
#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik)
radky_vysledkovky = [ ]
for ar in aktivni_resitele :
# získáme výsledky řešitele - součty přes číslo a ročník
vr = VysledkyResitele ( ar , cislo , cislo . rocnik )
for hp in hlavni_problemy :
vr . body . append (
body_resitele_problemu_v_cisle ( hp , ar , cislo ) )
radky_vysledkovky . append ( vr )
# setřídíme řádky výsledkovky/objekty VysledkyResitele podle bodů
radky_vysledkovky . sort ( key = lambda vr : vr . body_rocnik , reverse = True )
# generujeme sloupec s pořadím pomocí stejně zvané funkce
pocty_bodu = [ rv . body_rocnik for rv in radky_vysledkovky ]
sloupec_poradi = sloupec_s_poradim ( pocty_bodu )
# každému řádku výsledkovky přidáme jeho pořadí
i = 0
for rv in radky_vysledkovky :
rv . poradi = sloupec_poradi [ i ]
i = i + 1
# vytahané informace předáváme do kontextu
context [ ' cislo ' ] = cislo
context [ ' radky_vysledkovky ' ] = radky_vysledkovky
context [ ' problemy ' ] = hlavni_problemy
# context['v_cisle_zadane'] = TODO
# context['resene_problemy'] = resene_problemy
#XXX testovat
#XXX opravit to, že se nezobrazují body za jednotlivé úlohy
return context
# problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku()))
# #setridi problemy podle typu a poradi zadani
# problem_index = {}
# for i in range(len(problemy)):
# #umoznuje zjistit index podle id problemu
#
# vysledky_resitele = {}
# vysledkovka = []
#
# # doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině
# for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky):
# v.poradi = poradi
# v.body_celkem_rocnik = v.body
# v.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body
# v.resitel.rocnik = v.resitel.rocnik(v.cislo.rocnik)
#
# # je tady '', aby se nezobrazovala 0, pokud se řešitel o řešení úlohy ani nepokusil
# v.body_ulohy = [''] * len(problemy)
#
# v.titul = v.resitel.get_titul(v.body_celkem_odjakziva)
#
# body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo'])
# v.body_cislo = body_cislo_q[0].body if body_cislo_q else 0
#
# vysledkovka.append(v)
#
# # připravíme si odkaz na řádek, abychom do něj mohli doplnit body za jednotlivé úlohy
# vysledky_resitele[v.resitel.id] = v
#
# # za každé řešení doplníme k příslušnému řešiteli a úloze body
# for r in reseni:
# vysledky_resitele[r.resitel.id].body_ulohy[problem_index[r.problem.id]] = r.body
#
# context['vysledkovka'] = vysledkovka
# context['problemy'] = problemy
# context['v_cisle_zadane'] = v_cisle_zadane
# context['resene_problemy'] = resene_problemy
class ArchivTemataView ( generic . ListView ) :
model = Problem
template_name = ' seminar/archiv/temata.html '
queryset = Tema . objects . filter ( stav = Problem . STAV_ZADANY ) . select_related ( ' cislo_zadani__rocnik ' ) . order_by ( ' -cislo_zadani__rocnik__rocnik ' , ' kod ' )
### Generovani vysledkovky
#class CisloVysledkovkaView(CisloView):i
# poradi | titul. jmeno prijmeni | ulohy | za cislo | celkem | odjakziva
#
#
#
# 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
#
#class RocnikVysledkovkaView(RocnikView):
# 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
### Generovani obalek
class CisloObalkyStruct :
rocnik = None
cisla = None
# Vraci QuerySet aktualnich resitelu = nekdy neco poslali, ale jeste neodmaturovali
def aktualniResitele ( rocnik ) :
letos = Rocnik . objects . get ( rocnik = rocnik )
return Resitel . objects . filter ( rok_maturity__gt = letos . prvni_rok )
# # ALERT: pokud nekdo nema vypleny rok maturity, tak neni aktualni, protoze Karel Tesar a jini
# return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None))
# Vraci QuerySet aktivnich resitelu =
# jeste neodmaturovali &&
# (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali
# jinak letos neco poslali)
def aktivniResitele ( rocnik , cislo ) :
letos = CisloObalkyStruct ( )
loni = CisloObalkyStruct ( )
aktualni_resitele = aktualniResitele ( rocnik )
letos . rocnik = Rocnik . objects . get ( rocnik = rocnik )
loni . rocnik = Rocnik . objects . get ( rocnik = int ( rocnik ) - 1 )
letos . cisla = Cislo . objects . filter ( rocnik = letos . rocnik , cislo__lte = cislo )
loni . cisla = Cislo . objects . filter ( rocnik = loni . rocnik )
if int ( cislo ) > 3 :
problemy = Problem . objects . filter ( cislo_zadani__in = letos . cisla )
else :
problemy = Problem . objects . filter ( Q ( cislo_zadani__in = letos . cisla ) | Q ( cislo_zadani__in = loni . cisla ) )
resitele = aktualni_resitele . filter ( reseni__in = Reseni . objects . filter ( problem__in = problemy ) ) . distinct ( )
return resitele
def cisloObalkyView ( request , rocnik , cislo ) :
return obalkyView ( request , aktivniResitele ( rocnik , 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 )
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
def oldObalkovaniView ( request , rocnik , cislo ) :
rocnik = Rocnik . objects . get ( rocnik = rocnik )
cislo = Cislo . objects . get ( rocnik = rocnik , cislo = cislo )
reseni = (
Reseni . objects . filter ( cislo_body = cislo )
. order_by (
' resitel__prijmeni ' ,
' resitel__jmeno ' ,
' problem__typ ' ,
' problem__kod '
)
)
problemy = sorted ( set ( r . problem for r in reseni ) , key = lambda p : ( p . typ , p . kod ) )
return render (
request ,
' seminar/archiv/cislo_obalkovani.html ' ,
{ ' cislo ' : cislo , ' problemy ' : problemy , ' reseni ' : reseni }
)
### Tituly
# TODO udelat neco jako get_objects_or_404
# FIXME: prepsat, aby nepouzivalo VysledkyK...
#def TitulyView(request, rocnik, cislo):
# rocnik_obj = Rocnik.objects.get(rocnik = rocnik)
# resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok)
# cislo_obj = Cislo.objects.get(rocnik = rocnik_obj, cislo = cislo)
#
# asciijmena = []
# broken = False
#
# for resitel in resitele:
# try:
# vys = VysledkyKCisluOdjakziva.objects.get(resitel = resitel, cislo = cislo_obj)
# body = vys.body
# except ObjectDoesNotExist:
# body = 0
# resitel.titul = resitel.get_titul(body)
# resitel.ascii = unicodedata.normalize('NFKD',resitel.jmeno+resitel.prijmeni).encode("ascii","ignore").replace(" ","")
# if resitel.ascii not in asciijmena:
# asciijmena.append(resitel.ascii)
# else:
# broken = True
#
# return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele,'broken':broken},content_type="text/plain")
### Soustredeni
class SoustredeniListView ( generic . ListView ) :
model = Soustredeni
template_name = ' seminar/soustredeni/seznam_soustredeni.html '
class SoustredeniView ( generic . DetailView ) :
model = Soustredeni
template_name = ' seminar/archiv/soustredeni.html '
def soustredeniObalkyView ( request , soustredeni ) :
soustredeni = get_object_or_404 ( Soustredeni , id = soustredeni )
return obalkyView ( request , soustredeni . ucastnici . all ( ) )
class SoustredeniUcastniciBaseView ( generic . ListView ) :
model = Soustredeni_Ucastnici
def get_queryset ( self ) :
soustredeni = get_object_or_404 (
Soustredeni ,
pk = self . kwargs [ " soustredeni " ]
)
return Soustredeni_Ucastnici . objects . filter (
soustredeni = soustredeni ) . select_related ( ' resitel ' )
class SoustredeniMailyUcastnikuView ( SoustredeniUcastniciBaseView ) :
""" Seznam e-mailů řešitelů oddělených čárkami """
model = Soustredeni_Ucastnici
template_name = ' seminar/soustredeni/maily_ucastniku.txt '
class SoustredeniUcastniciView ( SoustredeniUcastniciBaseView ) :
""" HTML tabulka účastníků pro tisk """
model = Soustredeni_Ucastnici
template_name = ' seminar/soustredeni/seznam_ucastniku.html '
def soustredeniUcastniciExportView ( request , soustredeni ) :
soustredeni = get_object_or_404 ( Soustredeni , id = soustredeni )
ucastnici = Resitel . objects . filter ( soustredeni = soustredeni )
response = HttpResponse ( content_type = ' text/csv ' )
response [ ' Content-Disposition ' ] = ' attachment; filename= " ucastnici.csv " '
writer = UnicodeWriter ( response )
writer . writerow ( [ " jmeno " , " prijmeni " , " rok_maturity " , " telefon " , " email " , " ulice " , " mesto " , " psc " , " stat " ] )
for u in ucastnici :
writer . writerow ( [ u . jmeno , u . prijmeni , str ( u . rok_maturity ) , u . telefon , u . email , u . ulice , u . mesto , u . psc , u . stat . name ] )
return response
### Články
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
class ClankyResitelView ( generic . ListView ) :
model = Problem
template_name = ' seminar/clanky/resitelske_clanky.html '
queryset = Clanek . objects . filter ( stav = Problem . STAV_ZADANY ) . select_related ( ' cislo_zadani__rocnik ' ) . order_by ( ' -cislo_zadani__rocnik__rocnik ' , ' kod ' )
# 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')
### Status
def StavDatabazeView ( request ) :
# nastaveni = Nastaveni.objects.get()
problemy = utils . seznam_problemu ( )
muzi = Resitel . objects . filter ( pohlavi_muz = True )
zeny = Resitel . objects . filter ( pohlavi_muz = False )
return render ( request , ' seminar/stav_databaze.html ' ,
{
# 'nastaveni': nastaveni,
' problemy ' : problemy ,
' resitele ' : Resitel . objects . all ( ) ,
' muzi ' : muzi ,
' zeny ' : zeny ,
' jmena_muzu ' : utils . histogram ( [ r . jmeno for r in muzi ] ) ,
' jmena_zen ' : utils . histogram ( [ r . jmeno for r in zeny ] ) ,
} )
@ensure_csrf_cookie
def TeXUploadLoginView ( request ) :
""" Pro přihlášení při nahrávání z texu """
q = request . POST
# nastavení cookie csrftoken
if not q :
return JsonResponse ( { " ok " : 1 } )
if " username " in q :
username = q [ " username " ]
password = q [ " password " ]
user = authenticate ( username = username , password = password )
if user is not None and user . is_staff :
login ( request , user )
return JsonResponse ( { " ok " : 1 } )
else :
return JsonResponse ( { " error " : " Neplatné uživatelské jméno nebo heslo " } )
@ensure_csrf_cookie
def texUploadView ( request ) :
def uloz_soubory ( files , rocnik , cislo ) :
for filename , f in files :
path = os . path . join (
settings . MEDIA_ROOT ,
settings . CISLO_IMG_DIR ,
rocnik ,
cislo ,
filename
)
adresar = os . path . dirname ( path )
if not os . path . exists ( adresar ) :
os . makedirs ( adresar )
with open ( path , " wb+ " ) as fout :
for chunk in f . chunks ( ) :
fout . write ( chunk )
q = request . POST
# nastavení cookie csrftoken
if not q :
return JsonResponse ( { " ok " : 1 } )
# Odchytíme všechny výjimky a traceback pošleme v odpovědi
try :
meta = json . loads ( q [ " meta " ] )
html = q [ " html " ]
if meta [ " typ " ] in [ " uloha " , " serial " , " reseni " , " tema " ] :
# Uložíme soubory
if meta [ " typ " ] != " reseni " :
c = meta [ " cislo " ]
else :
# Řešení má nastavené číslo svojí úlohy, ale obrázky jsou
# ukládány do čísla, kde řešení vyšlo
c = meta [ " cislo_reseni " ]
# Zjistíme typ ukládaného problému
typy = {
" uloha " : Problem . TYP_ULOHA ,
" serial " : Problem . TYP_SERIAL ,
" reseni " : Problem . TYP_ULOHA ,
" tema " : Problem . TYP_TEMA ,
}
problem_typ = typy [ meta [ " typ " ] ]
# Pokud už problém existuje, vytáhneme jej z db a upravíme
# Pokud neexistuje, vytvoříme jej jedině pokud je to vynucené
# Pokud ročník/číslo ještě neexistuje, vyhodí to výjimku ->
# číslo/ročník se musí založit ručně v adminu
rocnik = Rocnik . objects . get ( rocnik = meta [ " rocnik " ] )
cislo = Cislo . objects . get ( rocnik = rocnik , cislo = meta [ " cislo " ] )
existujici = Problem . objects . filter (
typ = problem_typ ,
stav = Problem . STAV_ZADANY ,
cislo_zadani = cislo ,
kod = meta [ " kod " ]
)
problem = None
if existujici :
problem = existujici [ 0 ]
elif " vytvor " in q :
# vytvoříme nový
problem = Problem (
typ = problem_typ ,
stav = Problem . STAV_ZADANY ,
kod = meta [ " kod " ] ,
cislo_zadani = cislo
)
else :
return JsonResponse ( {
" error " : " Problém neexistuje: {} {} . {} kód {} " . format (
meta [ " typ " ] , meta [ " rocnik " ] , meta [ " cislo " ] , meta [ " kod " ]
)
} )
uloz_soubory ( request . FILES . items ( ) , meta [ " rocnik " ] , c )
if meta [ " typ " ] == " reseni " :
problem . text_reseni = html
# Pokud ročník/číslo ještě neexistuje, vyhodí to výjimku ->
# číslo/ročník se musí založit ručně v adminu
problem . cislo_reseni = Cislo . objects . get (
rocnik = rocnik ,
cislo = meta [ " cislo_reseni " ]
)
# při nahrávání řešení už původní zadání atd. neměníme
else :
problem . text_zadani = html
problem . nazev = meta [ " nazev " ]
if meta [ " typ " ] != " tema " :
problem . body = meta [ " body " ]
problem . save ( )
cislo . faze = cislo . FAZE_NAHRANO
cislo . save ( )
# Vrátíme id dané úlohy, aby se k ní dala případně připojit pohádka
return JsonResponse ( { " db_id " : problem . id } )
elif meta [ " typ " ] == " pohadka " :
uloha = Problem . objects . get ( typ = Problem . TYP_ULOHA , pk = meta [ " uloha " ] )
# Pokud už příslušná pohádka existuje, jen ji upravíme
existujici = Pohadka . objects . filter ( uloha = uloha , pred = meta [ " pred " ] )
pohadka = None
if existujici :
pohadka = existujici [ 0 ]
else :
pohadka = Pohadka ( uloha = uloha , pred = meta [ " pred " ] )
pohadka . text = q [ " html " ]
pohadka . save ( )
return JsonResponse ( { " db_id " : pohadka . id } )
except Exception as e :
# Pošleme zpátky traceback, ať uživatel ví, v čem je problém
tb = " " . join ( traceback . format_exception ( type ( e ) , e , sys . exc_info ( ) [ 2 ] ) )
return JsonResponse ( { " error " : tb } )
def texDownloadView ( request , rocnik , cislo ) :
""" View posílající JSON se zadanými a řešenými problémy pro založení čísla
"""
cislo = Cislo . objects . get ( rocnik__rocnik = rocnik , cislo = cislo )
if cislo . faze == cislo . FAZE_NAHRANO :
# obsah byl nahrán z TeXu na web, už je příliš složitý
return JsonResponse (
{ " error " : " Obsah čísla už byl nahrán z TeXu na web. " }
)
zadane = Problem . objects . filter (
cislo_zadani = cislo ,
stav = Problem . STAV_ZADANY
)
resene = Problem . objects . filter (
cislo_reseni = cislo ,
stav = Problem . STAV_ZADANY ,
typ = Problem . TYP_ULOHA
)
pred_pohadky = Pohadka . objects . filter ( uloha__cislo_zadani = cislo , pred = True )
po_pohadky = Pohadka . objects . filter ( uloha__cislo_zadani = cislo , pred = False )
response = {
" zadane " : [
{
" nazev " : p . nazev ,
" typ " : p . typ ,
" kod " : p . kod ,
" body " : p . body ,
" zadani " : p . text_zadani ,
" pred_pohadky " : [ x . text for x in pred_pohadky . filter ( uloha = p ) ] ,
" po_pohadky " : [ x . text for x in po_pohadky . filter ( uloha = p ) ] ,
} for p in zadane
] ,
" resene " : [
{
" nazev " : p . nazev ,
" typ " : p . typ ,
" kod " : p . kod ,
" body " : p . body ,
" zadani " : p . text_zadani ,
" reseni " : p . text_reseni ,
" cislo_zadani " : p . cislo_zadani . poradi ,
} for p in resene
] ,
}
cislo . faze = Cislo . FAZE_TEX
cislo . save ( )
return JsonResponse ( response )
class ResitelView ( LoginRequiredMixin , generic . DetailView ) :
model = Resitel
template_name = ' seminar/resitel.html '
def get_object ( self , queryset = None ) :
print ( self . request . user )
return Resitel . objects . get ( osoba__user = self . request . user )
## Formulare
class AddSolutionView ( LoginRequiredMixin , FormView ) :
template_name = ' seminar/org/vloz_reseni.html '
form_class = f . VlozReseniForm
success_url = ' / '
class SubmitSolutionView ( LoginRequiredMixin , CreateView ) :
model = s . Reseni
template_name = ' seminar/nahraj_reseni.html '
form_class = f . NahrajReseniForm
def get_context_data ( self , * * kwargs ) :
data = super ( ) . get_context_data ( * * kwargs )
if self . request . POST :
data [ ' prilohy ' ] = f . ReseniSPrilohamiFormSet ( self . request . POST , self . request . FILES )
else :
data [ ' prilohy ' ] = f . ReseniSPrilohamiFormSet ( )
return data
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
# Inspirace: https://stackoverflow.com/questions/41599809/using-a-django-filefield-in-an-inline-formset
def form_valid ( self , form ) :
context = self . get_context_data ( )
prilohy = context [ ' prilohy ' ]
with transaction . atomic ( ) :
self . object = form . save ( )
self . object . resitele . add ( Resitel . objects . get ( osoba__user = self . request . user ) )
self . object . cas_doruceni = datetime . now ( )
self . object . forma = s . Reseni . FORMA_UPLOAD
if prilohy . is_valid ( ) :
prilohy . instance = self . object
prilohy . save ( )
else :
raise Exception ( " Uploadovane soubory nebyly validni " )
return HttpResponseRedirect ( self . get_success_url ( ) )
def resetPasswordView ( request ) :
pass
def loginView ( request ) :
if request . method == ' POST ' :
form = LoginForm ( request . POST )
if form . is_valid ( ) :
user = authenticate ( request ,
username = form . cleaned_data [ ' username ' ] ,
password = form . cleaned_data [ ' password ' ] )
print ( form . cleaned_data )
if user is not None :
login ( request , user )
return HttpResponseRedirect ( ' / ' )
else :
return render ( request ,
' seminar/login.html ' ,
{ ' form ' : form , ' login_error ' : ' Neplatné jméno nebo heslo ' } )
else :
form = LoginForm ( )
return render ( request , ' seminar/login.html ' , { ' form ' : form } )
def logoutView ( request ) :
form = LoginForm ( )
if request . user . is_authenticated :
logout ( request )
return render ( request , ' seminar/login.html ' , { ' form ' : form , ' login_error ' : ' Byli jste úspěšně odhlášeni ' } )
return render ( request , ' seminar/login.html ' , { ' form ' : form } )
def prihlaska_log_gdpr_safe ( logger , gdpr_logger , msg , form_data ) :
msg = " {} , form_hash: {} " . format ( msg , hash ( form_data ) )
logger . warn ( msg )
gdpr_logger . warn ( msg + " , form: {} " . format ( 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
u = request . user
osoba_edit = Osoba . objects . get ( user = u )
resitel_edit = osoba_edit . resitel
user_edit = osoba_edit . user
## Vytvoření slovníku, kterým předvyplním formulář
prefill_1 = model_to_dict ( user_edit )
prefill_2 = model_to_dict ( resitel_edit )
prefill_3 = model_to_dict ( osoba_edit )
prefill_1 . update ( prefill_2 )
prefill_1 . update ( prefill_3 )
form = ProfileEditForm ( initial = prefill_1 )
## Změna údajů a jejich uložení
if request . method == ' POST ' :
form = ProfileEditForm ( request . POST )
if form . is_valid ( ) :
## Změny v osobě
fcd = form . cleaned_data
osoba_edit . jmeno = fcd [ ' jmeno ' ]
osoba_edit . prijmeni = fcd [ ' prijmeni ' ]
osoba_edit . pohlavi_muz = fcd [ ' pohlavi_muz ' ]
osoba_edit . email = fcd [ ' email ' ]
osoba_edit . telefon = fcd [ ' telefon ' ]
osoba_edit . ulice = fcd [ ' ulice ' ]
osoba_edit . mesto = fcd [ ' mesto ' ]
osoba_edit . psc = fcd [ ' psc ' ]
## Změny v osobě s podmínkami
if fcd . get ( ' spam ' , False ) :
osoba_edit . datum_souhlasu_zasilani = date . today ( )
if fcd . get ( ' stat ' , ' ' ) in ( ' CZ ' , ' SK ' ) :
osoba_edit . stat = fcd [ ' stat ' ]
else :
## Neznámá země
msg = " Unknown country {} " . format ( fcd [ ' stat_text ' ] )
## Změny v řešiteli
resitel_edit . skola = fcd [ ' skola ' ]
resitel_edit . rok_maturity = fcd [ ' rok_maturity ' ]
resitel_edit . zasilat = fcd [ ' zasilat ' ]
if fcd . get ( ' skola ' ) :
resitel_edit . skola = fcd [ ' skola ' ]
else :
# Unknown school - log it
msg = " Unknown school {} , {} " . format ( fcd [ ' skola_nazev ' ] , fcd [ ' skola_adresa ' ] )
resitel_edit . save ( )
osoba_edit . save ( )
return HttpResponseRedirect ( ' /thanks/ ' )
else :
## Stránka před odeslaním formuláře = předvyplněný formulář
return render ( request , ' seminar/edit.html ' , { ' form ' : form } )
def prihlaskaView ( request ) :
generic_logger = logging . getLogger ( ' seminar.prihlaska ' )
err_logger = logging . getLogger ( ' seminar.prihlaska.problem ' )
form_logger = logging . getLogger ( ' seminar.prihlaska.form ' )
if request . method == ' POST ' :
form = PrihlaskaForm ( request . POST )
# TODO vyresit, co se bude v jakych situacich zobrazovat
if form . is_valid ( ) :
generic_logger . info ( " Form valid " )
fcd = form . cleaned_data
form_hash = hash ( fcd )
form_logger . info ( fcd , form_hash = form_hash )
with transaction . atomic ( ) :
u = User . objects . create_user (
username = fcd [ ' username ' ] ,
password = fcd [ ' password ' ] ,
email = fcd [ ' email ' ] )
u . save ( )
o = Osoba (
jmeno = fcd [ ' jmeno ' ] ,
prijmeni = fcd [ ' prijmeni ' ] ,
pohlavi_muz = fcd [ ' pohlavi_muz ' ] ,
email = fcd [ ' email ' ] ,
telefon = fcd . get ( ' telefon ' , ' ' ) ,
datum_narozeni = fcd . get ( ' datum_narozeni ' , None ) ,
datum_souhlasu_udaje = date . today ( ) ,
datum_registrace = date . today ( ) ,
ulice = fcd . get ( ' ulice ' , ' ' ) ,
mesto = fcd . get ( ' mesto ' , ' ' ) ,
psc = fcd . get ( ' psc ' , ' ' ) ,
poznamka = str ( fcd )
)
if fcd . get ( ' spam ' , False ) :
o . datum_souhlasu_zasilani = date . today ( )
if fcd . get ( ' stat ' , ' ' ) in ( ' CZ ' , ' SK ' ) :
o . stat = fcd [ ' stat ' ]
else :
# Unknown country - log it
msg = " Unknown country {} " . format ( fcd [ ' stat_text ' ] )
err_logger . warn ( msg , form_hash = form_hash )
o . save ( )
o . user = u
o . save ( )
r = Resitel (
rok_maturity = fcd [ ' rok_maturity ' ] ,
zasilat = fcd [ ' zasilat ' ]
)
r . save ( )
r . osoba = o
if fcd . get ( ' skola ' ) :
r . skola = fcd [ ' skola ' ]
else :
# Unknown school - log it
msg = " Unknown school {} , {} " . format ( fcd [ ' skola_nazev ' ] , fcd [ ' skola_adresa ' ] )
err_logger . warn ( msg , form_hash = form_hash )
r . save ( )
return HttpResponseRedirect ( ' /thanks/ ' )
# if a GET (or any other method) we'll create a blank form
else :
form = PrihlaskaForm ( )
return render ( request , ' seminar/prihlaska.html ' , { ' form ' : form } )
class SkolaAutocomplete ( autocomplete . Select2QuerySetView ) :
def get_queryset ( self ) :
# Don't forget to filter out results depending on the visitor !
qs = Skola . objects . all ( )
if self . q :
qs = qs . filter (
Q ( nazev__istartswith = self . q ) |
Q ( kratky_nazev__istartswith = self . q ) |
Q ( ulice__istartswith = self . q ) |
Q ( mesto__istartswith = self . q ) )
return qs
class LoginRequiredAjaxMixin ( object ) :
def dispatch ( self , request , * args , * * kwargs ) :
#if request.is_ajax() and not request.user.is_authenticated: # Pokud to otevřu jako stránku, tak se omezení neuplatní, takže to asi nechceme
if not request . user . is_authenticated :
return JsonResponse ( data = { ' results ' : [ ] , ' pagination ' : { } } , status = 401 )
return super ( LoginRequiredAjaxMixin , self ) . dispatch ( request , * args , * * kwargs )
class ResitelAutocomplete ( LoginRequiredAjaxMixin , autocomplete . Select2QuerySetView ) :
def get_queryset ( self ) :
qs = Resitel . objects . all ( )
if self . q :
qs = qs . filter (
Q ( osoba__jmeno__startswith = self . q ) |
Q ( osoba__prijmeni__startswith = self . q ) |
Q ( osoba__prezdivka__startswith = self . q )
)
return qs
class OdevzdatelnyProblemAutocomplete ( autocomplete . Select2QuerySetView ) :
def get_queryset ( self ) :
nastaveni = get_object_or_404 ( Nastaveni )
rocnik = nastaveni . aktualni_rocnik
temata = s . Tema . objects . filter ( rocnik = rocnik , stav = s . Problem . STAV_ZADANY )
ulohy = s . Uloha . objects . filter ( cislo_deadline__rocnik = rocnik )
ulohy . union ( temata )
qs = ulohy
if self . q :
qs = qs . filter (
Q ( nazev__startswith = self . q ) )
return qs
# Ceka na autocomplete v3
# class OrganizatorAutocomplete(autocomplete.Select2QuerySetView):
# def get_queryset(self):
# if not self.request.user.is_authenticated():
# return Organizator.objects.none()
#
# qs = aktivniOrganizatori()
#
# if self.q:
# if self.q[0] == "!":
# qs = Organizator.objects.all()
# query = self.q[1:]
# else:
# query = self.q
# qs = qs.filter(
# Q(prezdivka__isstartswith=query)|
# Q(user__first_name__isstartswith=query)|
# Q(user__last_name__isstartswith=query))
#
# return qs
# FIXME: Tohle asi vlastně vůbec nepatří do aplikace 'seminar'
class LoginView ( auth_views . LoginView ) :
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL
template_name = ' seminar/login.html '
# Přesměrovací URL má být v kontextu:
def get_context_data ( self , * * kwargs ) :
ctx = super ( ) . get_context_data ( * * kwargs )
ctx [ ' next ' ] = reverse ( ' titulni_strana ' )
return ctx
class LogoutView ( auth_views . LogoutView ) :
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL
template_name = ' seminar/logout.html '
# Pavel: Vůbec nevím, proč to s _lazy funguje, ale bez toho to bylo rozbité.
next_page = reverse_lazy ( ' titulni_strana ' )
# "Chci resetovat heslo"
class PasswordResetView ( auth_views . PasswordResetView ) :
#template_name = 'seminar/password_reset.html'
# TODO: vlastní email_template_name a subject_template_name a html_email_template_name
success_url = reverse_lazy ( ' reset_password_done ' )
from_email = ' login@mam.mff.cuni.cz '
# "Poslali jsme e-mail (pokud bylo kam))"
class PasswordResetDoneView ( auth_views . PasswordResetDoneView ) :
#template_name = 'seminar/password_reset_done.html'
pass
# "Vymysli si heslo"
class PasswordResetConfirmView ( auth_views . PasswordResetConfirmView ) :
#template_name = 'seminar/password_confirm_done.html'
success_url = reverse_lazy ( ' reset_password_complete ' )
# "Heslo se asi změnilo."
class PasswordResetCompleteView ( auth_views . PasswordResetCompleteView ) :
#template_name = 'seminar/password_complete_done.html'
pass
class PasswordChangeView ( auth_views . PasswordChangeView ) :
#template_name = 'seminar/password_change.html'
success_url = reverse_lazy ( ' titulni_strana ' )