@ -1,15 +1,17 @@
# coding:utf-8
# coding:utf-8
from django . shortcuts import get_object_or_404 , render
from django . shortcuts import get_object_or_404 , render
from django . http import HttpResponse , HttpResponseRedirect , HttpResponseForbidden
from django . http import HttpResponse , HttpResponseRedirect , HttpResponseForbidden , JsonResponse
from django . core . urlresolvers import reverse
from django . core . urlresolvers import reverse
from django . core . exceptions import PermissionDenied , ObjectDoesNotExist
from django . core . exceptions import PermissionDenied , ObjectDoesNotExist
from django . views import generic
from django . views import generic
from django . utils . translation import ugettext as _
from django . utils . translation import ugettext as _
from django . http import Http404
from django . http import Http404
from django . db . models import Q
from django . db . models import Q
from django . views . decorators . csrf import ensure_csrf_cookie
from django . contrib . auth import authenticate , login
from . models import Problem , Cislo , Reseni , Nastaveni , Rocnik , Soustredeni , Organizator , Resitel , Novinky , Soustredeni_Ucastnici
from . models import Problem , Cislo , Reseni , Nastaveni , Rocnik , Soustredeni , Organizator , Resitel , Novinky , Soustredeni_Ucastnici , Pohadka , Prispevek
from . models import VysledkyZaCislo , VysledkyKCisluZaRocnik , VysledkyKCisluOdjakziva
from . models import VysledkyZaCislo , VysledkyKCisluZaRocnik , VysledkyKCisluOdjakziva
from . import utils
from . import utils
@ -21,6 +23,10 @@ import shutil
import os
import os
from django . conf import settings
from django . conf import settings
import unicodedata
import unicodedata
import json
import traceback
import sys
def verejna_temata ( rocnik ) :
def verejna_temata ( rocnik ) :
""" Vrací queryset zveřejněných témat v daném ročníku.
""" Vrací queryset zveřejněných témat v daném ročníku.
@ -45,9 +51,15 @@ def AktualniZadaniView(request):
def ZadaniTemataView ( request ) :
def ZadaniTemataView ( request ) :
nastaveni = get_object_or_404 ( Nastaveni )
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 ' ,
return render ( request , ' seminar/zadani/Temata.html ' ,
{
{
' temata ' : verejna_temata ( nastaveni . aktualni_rocnik )
' temata ' : temata ,
}
}
)
)
@ -241,6 +253,45 @@ class ProblemView(generic.DetailView):
context [ ' reseni ' ] = Reseni . objects . filter ( problem = context [ ' problem ' ] ) . select_related ( ' resitel ' ) . order_by ( ' resitel__prijmeni ' )
context [ ' reseni ' ] = Reseni . objects . filter ( problem = context [ ' problem ' ] ) . select_related ( ' resitel ' ) . order_by ( ' resitel__prijmeni ' )
return context
return context
class PrispevekView ( generic . DetailView ) :
model = Prispevek
template_name = ' seminar/archiv/prispevek.html '
# Vlastni ziskavani objektu z databaze podle prispevku
# pokud je prispevek neverejny zobrazi se jenom orgum
def get_object ( self , queryset = None ) :
if queryset is None :
queryset = self . get_queryset ( )
problem_arg = self . kwargs . get ( ' pk ' )
prispevek_arg = self . kwargs . get ( ' prispevek ' )
queryset = queryset . filter ( pk = prispevek_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 } )
if self . request . user . is_staff or obj . zverejnit :
return obj
else :
raise Http404 ( )
def get_context_data ( self , * * kwargs ) :
context = super ( PrispevekView , self ) . get_context_data ( * * kwargs )
# snaho o ziskani titulu
titul = ' '
try :
resitel = context [ ' prispevek ' ] . reseni . resitel
cislo = context [ ' prispevek ' ] . reseni . cislo_body
body = VysledkyKCisluOdjakziva . objects . get ( resitel = resitel ,
cislo = cislo ) . body
titul = resitel . get_titul ( body )
except :
pass
context [ ' titul ' ] = titul
return context
class RadekVysledkovky ( object ) :
class RadekVysledkovky ( object ) :
@ -318,7 +369,7 @@ class CisloView(generic.DetailView):
# za každé řešení doplníme k příslušnému řešiteli a úloze body
# za každé řešení doplníme k příslušnému řešiteli a úloze body
for r in reseni :
for r in reseni :
vysledky_resitele [ r . resitel . id ] . body_ulohy [ problem_index [ r . problem . id ] ] = r . body
vysledky_resitele [ r . resitel . id ] . body_ulohy [ problem_index [ r . problem . id ] ] = r . body
context [ ' vysledkovka ' ] = vysledkovka
context [ ' vysledkovka ' ] = vysledkovka
context [ ' problemy ' ] = problemy
context [ ' problemy ' ] = problemy
context [ ' v_cisle_zadane ' ] = v_cisle_zadane
context [ ' v_cisle_zadane ' ] = v_cisle_zadane
@ -360,9 +411,9 @@ def aktualniResitele(rocnik):
return Resitel . objects . filter ( rok_maturity__gt = letos . prvni_rok )
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
# # 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))
# return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None))
# Vraci QuerySet aktivnich resitelu =
# Vraci QuerySet aktivnich resitelu =
# jeste neodmaturovali &&
# jeste neodmaturovali &&
# (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali
# (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali
# jinak letos neco poslali)
# jinak letos neco poslali)
def aktivniResitele ( rocnik , cislo ) :
def aktivniResitele ( rocnik , cislo ) :
@ -370,11 +421,11 @@ def aktivniResitele(rocnik,cislo):
loni = CisloObalkyStruct ( )
loni = CisloObalkyStruct ( )
aktualni_resitele = aktualniResitele ( rocnik )
aktualni_resitele = aktualniResitele ( rocnik )
letos . rocnik = Rocnik . objects . get ( rocnik = rocnik )
letos . rocnik = Rocnik . objects . get ( rocnik = rocnik )
loni . rocnik = Rocnik . objects . get ( rocnik = int ( rocnik ) - 1 )
loni . rocnik = Rocnik . objects . get ( rocnik = int ( rocnik ) - 1 )
letos . cisla = Cislo . objects . filter ( rocnik = letos . rocnik , cislo__lte = cislo )
letos . cisla = Cislo . objects . filter ( rocnik = letos . rocnik , cislo__lte = cislo )
loni . cisla = Cislo . objects . filter ( rocnik = loni . rocnik )
loni . cisla = Cislo . objects . filter ( rocnik = loni . rocnik )
if int ( cislo ) > 3 :
if int ( cislo ) > 3 :
problemy = Problem . objects . filter ( cislo_zadani = letos . cisla )
problemy = Problem . objects . filter ( cislo_zadani = letos . cisla )
else :
else :
@ -382,7 +433,7 @@ def aktivniResitele(rocnik,cislo):
resitele = aktualni_resitele . filter ( reseni = Reseni . objects . filter ( problem = problemy ) ) . distinct ( )
resitele = aktualni_resitele . filter ( reseni = Reseni . objects . filter ( problem = problemy ) ) . distinct ( )
return resitele
return resitele
def cisloObalkyView ( request , rocnik , cislo ) :
def cisloObalkyView ( request , rocnik , cislo ) :
return obalkyView ( request , aktivniResitele ( rocnik , cislo ) )
return obalkyView ( request , aktivniResitele ( rocnik , cislo ) )
@ -408,11 +459,22 @@ def obalkovaniView(request, rocnik, cislo):
rocnik = Rocnik . objects . get ( rocnik = rocnik )
rocnik = Rocnik . objects . get ( rocnik = rocnik )
cislo = Cislo . objects . get ( rocnik = rocnik , cislo = cislo )
cislo = Cislo . objects . get ( rocnik = rocnik , cislo = cislo )
reseni = Reseni . objects . filter ( cislo_body = cislo )
reseni = (
serazena_reseni = sorted ( reseni , key = lambda r : ( r . resitel . prijmeni , r . resitel . jmeno , r . problem . typ , r . problem . kod ) )
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 ) )
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 ' : serazena_reseni } )
return render (
request ,
' seminar/archiv/cislo_obalkovani.html ' ,
{ ' cislo ' : cislo , ' problemy ' : problemy , ' reseni ' : reseni }
)
### Tituly
### Tituly
@ -438,7 +500,7 @@ def TitulyView(request, rocnik, cislo):
else :
else :
broken = True
broken = True
return render ( request , ' seminar/archiv/tituly.tex ' , { ' resitele ' : resitele , ' broken ' : broken } )
return render ( request , ' seminar/archiv/tituly.tex ' , { ' resitele ' : resitele , ' broken ' : broken } , content_type = " text/plain " )
### Soustredeni
### Soustredeni
@ -487,3 +549,177 @@ def StavDatabazeView(request):
' jmena_muzu ' : utils . histogram ( [ r . jmeno for r in muzi ] ) ,
' jmena_muzu ' : utils . histogram ( [ r . jmeno for r in muzi ] ) ,
' jmena_zen ' : utils . histogram ( [ r . jmeno for r in zeny ] ) ,
' jmena_zen ' : utils . histogram ( [ r . jmeno for r in zeny ] ) ,
} )
} )
@ensure_csrf_cookie
def LoginView ( 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 " ] :
# 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 " ]
uloz_soubory ( request . FILES . items ( ) , meta [ " rocnik " ] , c )
# Zjistíme typ ukládaného problému
typy = {
" uloha " : Problem . TYP_ULOHA ,
" serial " : Problem . TYP_SERIAL ,
" reseni " : Problem . TYP_ULOHA ,
}
problem_typ = typy [ meta [ " typ " ] ]
# Pokud už problém existuje, vytáhneme jej z db a upravíme
# 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 ]
# Jinak vytvoříme nový
else :
problem = Problem (
typ = problem_typ ,
stav = Problem . STAV_ZADANY ,
kod = meta [ " kod " ] ,
cislo_zadani = cislo
)
if meta [ " typ " ] == " reseni " :
problem . text_reseni = html
#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 " ]
problem . body = meta [ " body " ]
problem . 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 , 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 )
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 . cislo ,
} for p in resene
] ,
}
return JsonResponse ( response )