2021-09-02 19:35:21 +02:00
from django . contrib . auth . tokens import PasswordResetTokenGenerator
from django . contrib . sites . shortcuts import get_current_site
2020-05-07 00:53:54 +02:00
from django . shortcuts import get_object_or_404 , render , redirect
2016-02-17 16:17:11 +01:00
from django . http import HttpResponse , HttpResponseRedirect , HttpResponseForbidden , JsonResponse
2019-12-19 01:30:48 +01:00
from django . urls import reverse , reverse_lazy
2016-01-06 19:36:15 +01:00
from django . core . exceptions import PermissionDenied , ObjectDoesNotExist
2021-03-23 23:44:58 +01:00
from django . core . mail import send_mail
2021-09-02 19:35:21 +02:00
from django . utils . encoding import force_bytes
from django . utils . http import urlsafe_base64_encode
2015-03-13 20:08:18 +01:00
from django . views import generic
2015-06-08 22:38:13 +02:00
from django . utils . translation import ugettext as _
2018-12-05 23:37:05 +01:00
from django . http import Http404 , HttpResponseBadRequest , HttpResponseRedirect
2020-01-29 22:22:54 +01:00
from django . db . models import Q , Sum , Count
2016-02-17 16:17:11 +01:00
from django . views . decorators . csrf import ensure_csrf_cookie
2021-09-07 17:23:54 +02:00
from django . views . decorators . debug import sensitive_post_parameters
2020-02-28 21:34:53 +01:00
from django . views . generic . edit import FormView , CreateView
2021-04-28 21:26:30 +02:00
from django . views . generic . base import TemplateView , RedirectView
2019-09-01 22:59:05 +02:00
from django . contrib . auth import authenticate , login , get_user_model , logout
2019-12-13 16:38:56 +01:00
from django . contrib . auth import views as auth_views
2021-09-02 15:43:03 +02:00
from django . contrib . auth . models import User , Permission , Group
2019-09-02 00:01:39 +02:00
from django . contrib . auth . mixins import LoginRequiredMixin
2019-09-01 16:35:20 +02:00
from django . db import transaction
2020-09-03 23:02:28 +02:00
from django . core import serializers
2020-12-01 23:52:03 +01:00
from django . core . exceptions import PermissionDenied
2020-09-03 23:02:28 +02:00
from django . forms . models import model_to_dict
2015-06-08 22:38:13 +02:00
2019-12-05 00:50:04 +01:00
import seminar . models as s
2020-04-15 22:58:47 +02:00
import seminar . models as m
2020-03-03 21:48:55 +01:00
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
2019-04-23 23:26:37 +02:00
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
2020-05-07 00:38:12 +02:00
from seminar import utils , treelib
2021-05-04 20:34:15 +02:00
from seminar . forms import PrihlaskaForm , LoginForm , ProfileEditForm , PoMaturiteProfileEditForm
2020-02-05 23:30:41 +01:00
import seminar . forms as f
2020-09-03 23:02:28 +02:00
import seminar . templatetags . treenodes as tnltt
import seminar . views . views_rest as vr
2021-03-02 22:20:08 +01:00
from seminar . views . vysledkovka import vysledkovka_rocniku , vysledkovka_cisla , body_resitelu
2015-03-27 21:38:48 +01:00
2020-10-13 23:25:39 +02:00
from datetime import timedelta , date , datetime , MAXYEAR
2019-08-14 14:29:24 +02:00
from django . utils import timezone
2015-09-08 21:27:10 +02:00
from itertools import groupby
2020-05-06 23:07:04 +02:00
from collections import OrderedDict
2015-11-15 15:14:21 +01:00
import tempfile
import subprocess
import shutil
import os
2017-02-04 23:28:54 +01:00
import os . path as op
2015-11-15 15:14:21 +01:00
from django . conf import settings
2015-11-15 17:06:50 +01:00
import unicodedata
2016-02-17 16:17:11 +01:00
import json
import traceback
import sys
2016-10-08 21:46:31 +02:00
import csv
2019-09-01 16:35:20 +02:00
import logging
2020-04-15 22:30:58 +02:00
import time
2016-02-17 16:17:11 +01:00
2021-02-24 01:26:50 +01:00
from seminar . utils import aktivniResitele , resi_v_rocniku , problemy_rocniku , cisla_rocniku , hlavni_problemy_f
2015-09-03 22:09:35 +02:00
2020-07-15 11:21:16 +02:00
# ze starého modelu
#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)
2020-01-29 22:22:54 +01:00
2021-09-04 22:07:13 +02:00
logger = logging . getLogger ( __name__ )
2020-01-29 22:22:54 +01:00
def get_problemy_k_tematu ( tema ) :
2020-06-25 19:50:30 +02:00
return Problem . objects . filter ( nadproblem = tema )
2020-01-29 22:22:54 +01:00
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 )
2021-09-02 19:35:21 +02:00
context [ ' cislo ' ] = self . cislo
2020-01-29 22:22:54 +01:00
return context
2020-03-19 00:50:39 +01:00
class TNLData ( object ) :
2020-04-16 00:33:36 +02:00
def __init__ ( self , anode , parent = None , index = None ) :
2020-03-19 00:50:39 +01:00
self . node = anode
2020-09-03 23:02:28 +02:00
self . sernode = vr . TreeNodeSerializer ( anode )
2020-03-19 00:50:39 +01:00
self . children = [ ]
2020-04-15 22:58:47 +02:00
self . parent = parent
self . tema_in_path = False
2020-04-16 00:33:36 +02:00
self . index = index
2020-09-03 23:02:28 +02:00
2020-04-15 22:58:47 +02:00
if parent :
self . tema_in_path = parent . tema_in_path
if isinstance ( anode , m . TemaVCisleNode ) :
self . tema_in_path = True
2020-09-03 23:02:28 +02:00
def add_edit_options ( self ) :
2021-09-02 19:35:21 +02:00
self . deletable = tnltt . deletable ( self )
2020-09-03 23:02:28 +02:00
self . editable_siblings = tnltt . editableSiblings ( self )
self . editable_children = tnltt . editableChildren ( self )
self . text_only_subtree = tnltt . textOnlySubtree ( self )
self . can_podvesit_za = tnltt . canPodvesitZa ( self )
self . can_podvesit_pred = tnltt . canPodvesitPred ( self )
self . appendable_children = tnltt . appendableChildren ( self )
2020-10-21 08:41:20 +02:00
print ( " appChld " , self . appendable_children )
2020-09-03 23:02:28 +02:00
if self . parent :
self . appendable_siblings = tnltt . appendableChildren ( self . parent )
else :
self . appendable_siblings = [ ]
2020-12-01 23:52:03 +01:00
@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 )
2021-09-02 19:35:21 +02:00
uloha = ( isinstance ( parent , s . UlohaVzorakNode ) or
2020-12-01 23:52:03 +01:00
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
2021-09-02 19:35:21 +02:00
2020-12-01 23:52:03 +01:00
@classmethod
def all_public_children ( cls , anode ) :
for ch in treelib . all_children ( anode ) :
if TNLData . public_above ( ch ) :
yield ch
else :
continue
2020-09-03 23:02:28 +02:00
2020-04-15 22:58:47 +02:00
@classmethod
2020-12-01 23:52:03 +01:00
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 :
2021-09-02 19:35:21 +02:00
enum_children = enumerate ( TNLData . all_public_children ( anode ) )
2020-12-01 23:52:03 +01:00
for ( idx , ch ) in enum_children :
outitem = cls . from_treenode ( ch , user , out , idx )
2020-04-15 22:58:47 +02:00
out . children . append ( outitem )
2020-09-03 23:02:28 +02:00
out . add_edit_options ( )
2020-04-15 22:58:47 +02:00
return out
2021-09-02 19:35:21 +02:00
2020-04-22 23:46:18 +02:00
@classmethod
2020-04-23 00:40:15 +02:00
def from_tnldata_list ( cls , tnllist ) :
""" Vyrobíme virtuální TNL, který nemá obsah, ale má za potomky všechna zadaná TNLData """
2020-04-22 23:46:18 +02:00
result = cls ( None )
2020-04-23 00:40:15 +02:00
for idx , tnl in enumerate ( tnllist ) :
2020-04-22 23:46:18 +02:00
result . children . append ( tnl )
tnl . parent = result
tnl . index = idx
2020-09-03 23:02:28 +02:00
result . add_edit_options ( )
2020-04-22 23:46:18 +02:00
return result
2020-01-29 22:22:54 +01:00
2020-04-23 00:40:15 +02:00
@classmethod
def filter_treenode ( cls , treenode , predicate ) :
tnll = cls . _filter_treenode_recursive ( treenode , predicate ) # TreeNodeList List :-)
return TNLData . from_tnldata_list ( tnll )
2020-04-22 23:46:18 +02:00
@classmethod
def _filter_treenode_recursive ( cls , treenode , predicate ) :
if predicate ( treenode ) :
return [ cls . from_treenode ( treenode ) ]
else :
found = [ ]
2021-03-02 22:20:08 +01:00
for tn in treelib . all_children ( treenode ) :
2020-04-22 23:46:18 +02:00
result = cls . filter_treenode ( tn , predicate )
# Result by v tuhle chvíli měl být seznam TNLDat odpovídající treenodům, jež matchnuly predikát.
for tnl in result :
found . append ( tnl )
return found
2021-09-02 19:35:21 +02:00
2020-09-03 23:02:28 +02:00
def to_json ( self ) :
#self.node = anode
#self.children = []
#self.parent = parent
#self.tema_in_path = False
#self.index = index
out = { }
out [ ' node ' ] = self . sernode . data
out [ ' children ' ] = [ n . to_json ( ) for n in self . children ]
out [ ' tema_in_path ' ] = self . tema_in_path
out [ ' index ' ] = self . index
out [ ' deletable ' ] = self . deletable
out [ ' editable_siblings ' ] = self . editable_siblings
out [ ' editable_children ' ] = self . editable_children
out [ ' text_only_subtree ' ] = self . text_only_subtree
out [ ' can_podvesit_za ' ] = self . can_podvesit_za
out [ ' can_podvesit_pod ' ] = self . can_podvesit_pred
out [ ' appendable_children ' ] = self . appendable_children
out [ ' appendable_siblings ' ] = self . appendable_siblings
return out
2020-05-07 00:53:54 +02:00
def __repr__ ( self ) :
return ( " TNL( {} ) " . format ( self . node ) )
2015-09-23 18:16:17 +02:00
2020-03-19 00:50:39 +01:00
class TreeNodeView ( generic . DetailView ) :
model = s . TreeNode
template_name = ' seminar/treenode.html '
def get_context_data ( self , * * kwargs ) :
context = super ( ) . get_context_data ( * * kwargs )
2020-12-01 23:52:03 +01:00
context [ ' tnldata ' ] = TNLData . from_treenode ( self . object , self . request . user )
2020-03-19 00:50:39 +01:00
return context
2020-04-23 00:41:04 +02:00
2020-09-03 23:02:28 +02:00
class TreeNodeJSONView ( generic . DetailView ) :
model = s . TreeNode
def get ( self , request , * args , * * kwargs ) :
self . object = self . get_object ( )
2020-12-01 23:52:03 +01:00
data = TNLData . from_treenode ( self . object , self . request . user ) . to_json ( )
2020-09-03 23:02:28 +02:00
return JsonResponse ( data )
2020-05-07 00:53:54 +02:00
class TreeNodePridatView ( generic . View ) :
type_from_str = {
' rocnikNode ' : m . RocnikNode ,
' cisloNode ' : m . CisloNode ,
' castNode ' : m . CastNode ,
' textNode ' : m . TextNode ,
' temaVCisleNode ' : m . TemaVCisleNode ,
' reseniNode ' : m . ReseniNode ,
' ulohaZadaniNode ' : m . UlohaZadaniNode ,
' ulohaVzorakNode ' : m . UlohaVzorakNode ,
' pohadkaNode ' : m . PohadkaNode ,
' orgText ' : m . OrgTextNode ,
}
def post ( self , request , * args , * * kwargs ) :
2020-06-12 01:56:07 +02:00
######## FIXME: ROZEPSANE, NEFUNGUJE, DOPSAT !!!!!! ###########
2020-05-07 00:53:54 +02:00
node = s . TreeNode . objects . get ( pk = self . kwargs [ ' pk ' ] )
2020-05-21 12:42:15 +02:00
kam = self . kwargs [ ' kam ' ]
2020-06-12 01:56:07 +02:00
co = self . kwargs [ ' co ' ]
typ = self . type_from_str [ co ]
raise NotImplementedError ( ' Neni to dopsane, dopis to! ' )
if kam not in ( ' pred ' , ' syn ' , ' za ' ) :
raise ValidationError ( ' Přidat lze pouze před nebo za node nebo jako syna ' )
2021-09-02 19:35:21 +02:00
2020-06-12 01:56:07 +02:00
if co == m . TextNode :
new_obj = m . Text ( )
new_obj . save ( )
elif co == m . CastNode :
new_obj = m . CastNode ( )
new_obj . nadpis = request . POST . get ( ' pridat-castNode- {} - {} ' . format ( node . id , kam ) )
new_obj . save ( )
elif co == m . ReseniNode :
2020-09-03 23:02:28 +02:00
new_obj = m
2020-06-12 01:56:07 +02:00
pass
elif co == m . UlohaZadaniNode :
pass
elif co == m . UlohaReseniNode :
pass
else :
new_obj = None
if kam == ' pred ' :
pass
2020-05-07 00:53:54 +02:00
if kam == ' syn ' :
2020-05-21 12:42:15 +02:00
if typ == m . TextNode :
text_obj = m . Text ( )
text_obj . save ( )
node = treelib . create_child ( node , typ , text = text_obj )
else :
node = treelib . create_child ( node , typ )
2020-05-07 00:53:54 +02:00
if kam == ' za ' :
2020-05-21 12:42:15 +02:00
if typ == m . TextNode :
text_obj = m . Text ( )
text_obj . save ( )
node = treelib . create_node_after ( node , typ , text = text_obj )
else :
node = treelib . create_node_after ( node , typ )
2020-05-07 00:53:54 +02:00
return redirect ( node . get_admin_url ( ) )
2021-09-02 19:35:21 +02:00
2020-05-07 00:53:54 +02:00
class TreeNodeSmazatView ( generic . base . View ) :
def post ( self , request , * args , * * kwargs ) :
2020-05-21 12:42:15 +02:00
node = s . TreeNode . objects . get ( pk = self . kwargs [ ' pk ' ] )
if node . first_child :
2020-05-30 23:54:09 +02:00
raise NotImplementedError ( ' Mazání TreeNode se syny není zatím podporováno! ' )
2020-06-03 23:50:55 +02:00
treelib . disconnect_node ( node )
node . delete ( )
2020-05-30 23:54:09 +02:00
return redirect ( request . headers . get ( ' referer ' ) )
2020-05-07 00:53:54 +02:00
2020-06-03 23:50:55 +02:00
class TreeNodeOdvesitPrycView ( generic . base . View ) :
2020-05-07 00:53:54 +02:00
def post ( self , request , * args , * * kwargs ) :
2020-05-21 12:42:15 +02:00
node = s . TreeNode . objects . get ( pk = self . kwargs [ ' pk ' ] )
2020-06-03 23:50:55 +02:00
treelib . disconnect_node ( node )
node . root = None
node . save ( )
return redirect ( request . headers . get ( ' referer ' ) )
2020-05-07 00:53:54 +02:00
class TreeNodePodvesitView ( generic . base . View ) :
def post ( self , request , * args , * * kwargs ) :
2020-05-21 12:42:15 +02:00
node = s . TreeNode . objects . get ( pk = self . kwargs [ ' pk ' ] )
kam = self . kwargs [ ' kam ' ]
if kam == ' pred ' :
2020-05-30 23:59:54 +02:00
treelib . lower_node ( node )
2020-05-21 12:42:15 +02:00
elif kam == ' za ' :
2020-05-30 23:54:09 +02:00
raise NotImplementedError ( ' Podvěsit za není zatím podporováno ' )
2020-05-30 23:59:54 +02:00
return redirect ( request . headers . get ( ' referer ' ) )
2020-05-07 00:53:54 +02:00
class TreeNodeProhoditView ( generic . base . View ) :
def post ( self , request , * args , * * kwargs ) :
2020-05-21 12:42:15 +02:00
node = s . TreeNode . objects . get ( pk = self . kwargs [ ' pk ' ] )
treelib . swap_succ ( node )
2020-05-30 23:54:09 +02:00
return redirect ( request . headers . get ( ' referer ' ) )
2020-05-21 12:42:15 +02:00
#FIXME ve formulari predat puvodni url a vratit redirect na ni
2020-05-07 00:53:54 +02:00
2020-06-03 23:50:55 +02:00
class SirotcinecView ( generic . ListView ) :
model = s . TreeNode
template_name = ' seminar/orphanage.html '
2021-09-02 19:35:21 +02:00
2020-06-03 23:50:55 +02:00
def get_queryset ( self ) :
2020-06-12 01:56:07 +02:00
return s . TreeNode . objects . not_instance_of ( s . RocnikNode ) . filter ( root = None , prev = None , succ = None , father_of_first = None )
2020-05-07 00:53:54 +02:00
2020-09-03 23:02:28 +02:00
# FIXME pouzit Django REST Framework
class TextWebView ( generic . DetailView ) :
model = s . Text
def get ( self , request , * args , * * kwargs ) :
self . object = self . get_object ( )
return JsonResponse ( model_to_dict ( self . object , exclude = ' do_cisla ' ) )
2021-09-07 14:42:56 +02:00
# FIXME: Pozor, níž je ještě jeden ProblemView!
#class ProblemView(generic.DetailView):
# model = s.Problem
# # Zkopírujeme template_name od TreeNodeView, protože jsme prakticky jen trošku upravený TreeNodeView
# template_name = TreeNodeView.template_name
#
# 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:
# # Hezčí formátování zbytku :-P
# 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,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,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
# context['tnldata'] = TNLData.filter_treenode(rocniknode, lambda x: isinstance(x, s.TemaVCisleNode))
# else:
# raise ValueError("Obecný problém nejde zobrazit.")
# return context
2020-04-23 00:41:04 +02:00
2019-12-05 00:50:04 +01:00
2021-02-09 21:43:07 +01:00
#class AktualniZadaniView(generic.TemplateView):
# template_name = 'seminar/treenode.html'
2020-10-21 08:41:20 +02:00
# TODO Co chceme vlastně zobrazovat na této stránce? Zatím je zde aktuální číslo, ale může tu být cokoli jiného...
#class AktualniZadaniView(TreeNodeView):
# def get_object(self):
# nastaveni = get_object_or_404(Nastaveni)
# return nastaveni.aktualni_cislo.cislonode
#
# def get_context_data(self,**kwargs):
# nastaveni = get_object_or_404(Nastaveni)
# context = super().get_context_data(**kwargs)
# verejne = nastaveni.aktualni_cislo.verejne()
# context['verejne'] = verejne
# return context
2020-03-19 00:50:39 +01:00
2021-02-09 21:43:07 +01:00
def AktualniZadaniView ( request ) :
nastaveni = get_object_or_404 ( Nastaveni )
verejne = nastaveni . aktualni_cislo . verejne ( )
return render ( request , ' seminar/zadani/AktualniZadani.html ' ,
{ ' nastaveni ' : nastaveni ,
' verejne ' : verejne ,
} ,
)
2020-10-27 23:28:23 +01:00
def ZadaniTemataView ( request ) :
2020-12-01 23:52:03 +01:00
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 ,
} ,
)
2020-10-27 23:28:23 +01:00
2020-03-19 00:50:39 +01:00
# 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})
2020-09-01 23:04:19 +02:00
#
2016-07-24 23:16:06 +02:00
2021-03-02 21:49:12 +01:00
def ZadaniAktualniVysledkovkaView ( request ) :
nastaveni = get_object_or_404 ( Nastaveni )
# Aktualni verejna vysledkovka
2021-09-06 15:25:54 +02:00
rocnik = nastaveni . aktualni_rocnik
vysledkovka = vysledkovka_rocniku ( rocnik )
cisla = cisla_rocniku ( rocnik )
2021-03-02 21:49:12 +01:00
# kdyz neni verejna vysledkovka, tak zobraz starou
if not vysledkovka :
try :
minuly_rocnik = Rocnik . objects . get (
2021-09-06 15:25:54 +02:00
prvni_rok = ( rocnik . prvni_rok - 1 ) )
rocnik = minuly_rocnik
2021-03-02 21:49:12 +01:00
vysledkovka = vysledkovka_rocniku ( minuly_rocnik )
cisla = cisla_rocniku ( minuly_rocnik )
except ObjectDoesNotExist :
pass
# vysledkovka s neverejnyma vysledkama
vysledkovka_s_neverejnymi = vysledkovka_rocniku ( nastaveni . aktualni_rocnik , jen_verejne = False )
2021-03-02 23:26:18 +01:00
cisla_s_neverejnymi = cisla_rocniku ( nastaveni . aktualni_rocnik , jen_verejne = False )
2021-03-02 21:49:12 +01:00
return render (
request ,
' seminar/zadani/AktualniVysledkovka.html ' ,
{
2021-09-06 15:25:54 +02:00
' rocnik ' : rocnik ,
2021-03-02 21:49:12 +01:00
' radky_vysledkovky ' : vysledkovka ,
' cisla ' : cisla ,
' vysledkovka_s_neverejnymi ' : vysledkovka_s_neverejnymi ,
2021-03-02 23:26:18 +01:00
' cisla_s_neverejnymi ' : cisla_s_neverejnymi ,
2021-03-02 21:49:12 +01:00
}
)
2015-09-23 17:28:14 +02:00
2015-09-03 22:09:35 +02:00
### Titulni strana
2020-06-26 02:12:01 +02:00
def spravne_novinky ( request ) :
"""
Vrátí správný QuerySet novinek , tedy ten , který daný uživatel smí vidět .
Tj . Organizátorům všechny , ostatním jen veřejné
"""
user = request . user
# Využíváme líné vyhodnocování QuerySetů
qs = Novinky . objects . all ( )
2021-02-24 00:54:39 +01:00
if not user . je_org :
2020-06-26 02:12:01 +02:00
qs = qs . filter ( zverejneno = True )
return qs . order_by ( ' -datum ' )
2020-07-15 11:21:16 +02:00
def aktualni_temata ( rocnik ) :
"""
Vrací PolymorphicQuerySet témat v daném ročníku , ke kterým se aktuálně dá něco odevzdat .
"""
return Tema . objects . filter ( rocnik = rocnik , stav = ' zadany ' ) . order_by ( ' kod ' )
2020-06-26 02:12:01 +02:00
2015-09-03 22:09:35 +02:00
class TitulniStranaView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
template_name = ' seminar/titulnistrana.html '
2020-06-26 01:37:58 +02:00
def get_queryset ( self ) :
2020-07-15 21:12:00 +02:00
return spravne_novinky ( self . request ) [ : 3 ]
2019-05-11 01:15:05 +02:00
def get_context_data ( self , * * kwargs ) :
context = super ( TitulniStranaView , self ) . get_context_data ( * * kwargs )
nastaveni = get_object_or_404 ( Nastaveni )
2021-09-02 19:35:21 +02:00
2021-01-26 20:33:00 +01:00
deadline_soustredeni = ( nastaveni . aktualni_cislo . datum_deadline_soustredeni , " soustredeni " )
preddeadline = ( nastaveni . aktualni_cislo . datum_preddeadline , " preddeadline " )
deadline = ( nastaveni . aktualni_cislo . datum_deadline , " deadline " )
try :
nejblizsi_deadline = sorted ( filter ( lambda dl : dl [ 0 ] is not None and dl [ 0 ] > = date . today ( ) , [ deadline_soustredeni , preddeadline , deadline ] ) ) [ 0 ]
if nejblizsi_deadline [ 0 ] == deadline_soustredeni [ 0 ] :
nejblizsi_deadline = deadline_soustredeni
except IndexError :
nejblizsi_deadline = ( None , None ) # neni zadna aktualni deadline
if nejblizsi_deadline [ 0 ] is not None :
context [ ' nejblizsi_deadline ' ] = datetime . combine ( nejblizsi_deadline [ 0 ] , datetime . max . time ( ) )
else :
context [ ' nejblizsi_deadline ' ] = None
2021-09-02 19:35:21 +02:00
2021-01-26 20:33:00 +01:00
context [ ' typ_deadline ' ] = nejblizsi_deadline [ 1 ]
2020-07-14 23:21:55 +02:00
# Aktuální témata
2020-07-15 11:21:16 +02:00
nazvy_a_odkazy_na_aktualni_temata = [ ]
akt_temata = aktualni_temata ( nastaveni . aktualni_rocnik )
for tema in akt_temata :
# FIXME: netuším, jestli funguje tema.verejne_url(), nemáme testdata na témátka - je to asi url vzhledem k ročníku
nazvy_a_odkazy_na_aktualni_temata . append ( { ' nazev ' : tema . nazev , ' url ' : tema . verejne_url ( ) } )
context [ ' aktualni_temata ' ] = nazvy_a_odkazy_na_aktualni_temata
print ( context )
2020-07-14 23:21:55 +02:00
2019-05-11 01:15:05 +02:00
return context
2015-09-07 17:00:19 +02:00
2015-09-12 00:22:17 +02:00
class StareNovinkyView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
template_name = ' seminar/stare_novinky.html '
2020-06-26 02:12:01 +02:00
def get_queryset ( self ) :
return spravne_novinky ( self . request )
2015-09-12 00:22:17 +02:00
2015-06-29 17:51:18 +02:00
### Co je M&M
2015-06-03 14:16:30 +02:00
2017-01-20 12:13:25 +01:00
# Organizatori
2019-08-14 14:29:24 +02:00
def aktivniOrganizatori ( datum = timezone . now ( ) ) :
2019-05-11 01:15:05 +02:00
return Organizator . objects . exclude (
organizuje_do__isnull = False ,
organizuje_do__lt = datum
2019-07-25 21:20:15 +02:00
) . order_by ( ' osoba__jmeno ' )
2017-01-20 12:13:25 +01:00
2015-08-23 15:06:47 +02:00
2015-06-28 22:07:27 +02:00
class CojemamOrganizatoriView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Organizator
template_name = ' seminar/cojemam/organizatori.html '
queryset = aktivniOrganizatori ( )
2017-01-20 12:13:25 +01:00
2019-05-11 01:15:05 +02:00
def get_context_data ( self , * * kwargs ) :
context = super ( CojemamOrganizatoriView , self ) . get_context_data ( * * kwargs )
context [ ' aktivni ' ] = True
return context
2015-08-23 15:06:47 +02:00
2017-01-20 12:13:25 +01:00
2015-08-23 15:06:47 +02:00
class CojemamOrganizatoriStariView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Organizator
template_name = ' seminar/cojemam/organizatori.html '
queryset = Organizator . objects . exclude (
id__in = aktivniOrganizatori ( ) ) . order_by ( ' -organizuje_do ' )
2015-06-03 14:16:30 +02:00
2015-06-29 17:51:18 +02:00
### Archiv
2020-03-25 23:57:11 +01:00
2017-02-04 23:28:54 +01:00
class ArchivView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Rocnik
template_name = ' seminar/archiv/cisla.html '
def get_context_data ( self , * * kwargs ) :
context = super ( ArchivView , self ) . get_context_data ( * * kwargs )
2020-04-15 21:03:10 +02:00
cisla = Cislo . objects . filter ( poradi = 1 )
2020-04-01 23:09:58 +02:00
urls = { }
2019-05-11 01:15:05 +02:00
for i , c in enumerate ( cisla ) :
2021-09-02 19:30:21 +02:00
# Výchozí nastavení
if c . rocnik not in urls :
urls [ c . rocnik ] = op . join ( settings . STATIC_URL , " images " , " no-picture.png " )
# NOTE: tohle možná nastavuje poslední titulku
2020-04-15 21:03:10 +02:00
if c . titulka_nahled :
urls [ c . rocnik ] = c . titulka_nahled . url
2020-04-01 23:09:58 +02:00
context [ " object_list " ] = urls
2021-09-02 19:35:21 +02:00
2019-05-11 01:15:05 +02:00
return context
2017-02-04 23:28:54 +01:00
2021-09-02 19:35:21 +02:00
2021-02-16 22:42:05 +01:00
2015-09-23 17:28:14 +02:00
2015-04-01 14:01:13 +02:00
class RocnikView ( generic . DetailView ) :
2019-05-11 01:15:05 +02:00
model = Rocnik
template_name = ' seminar/archiv/rocnik.html '
2015-04-01 14:01:13 +02:00
2019-05-11 01:15:05 +02:00
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
def get_object ( self , queryset = None ) :
if queryset is None :
queryset = self . get_queryset ( )
2015-06-08 22:38:13 +02:00
2021-02-23 23:48:20 +01:00
return get_object_or_404 ( queryset , rocnik = self . kwargs . get ( ' rocnik ' ) )
2015-06-08 22:38:13 +02:00
2019-05-11 01:15:05 +02:00
def get_context_data ( self , * * kwargs ) :
2021-02-23 23:48:20 +01:00
start = time . time ( )
2019-05-11 01:15:05 +02:00
context = super ( RocnikView , self ) . get_context_data ( * * kwargs )
2015-08-13 10:52:43 +02:00
2020-04-08 23:44:06 +02:00
# vysledkovka = True zajistí vykreslení,
# zkontrolovat, kdy se má a nemá vykreslovat
context [ ' vysledkovka ' ] = True
2021-02-24 00:54:39 +01:00
if self . request . user . je_org :
2021-02-23 23:48:20 +01:00
context [ ' cisla_s_neverejnymi ' ] = cisla_rocniku ( context [ " rocnik " ] , jen_verejne = False )
context [ ' radky_vysledkovky_s_neverejnymi ' ] = vysledkovka_rocniku ( context [ " rocnik " ] , jen_verejne = False )
2021-02-24 01:26:50 +01:00
context [ ' hlavni_problemy_v_rocniku_s_neverejnymi ' ] = hlavni_problemy_f ( problemy_rocniku ( context [ " rocnik " ] , jen_verejne = False ) )
2020-04-08 23:44:06 +02:00
context [ ' cisla ' ] = cisla_rocniku ( context [ " rocnik " ] )
context [ ' radky_vysledkovky ' ] = vysledkovka_rocniku ( context [ " rocnik " ] )
2021-02-24 01:26:50 +01:00
context [ ' hlavni_problemy_v_rocniku ' ] = hlavni_problemy_f ( problemy_rocniku ( context [ " rocnik " ] ) )
2021-02-23 23:48:20 +01:00
end = time . time ( )
print ( " Kontext: " , end - start )
2015-09-13 20:28:38 +02:00
2019-05-11 01:15:05 +02:00
return context
2015-08-13 10:52:43 +02:00
2015-09-13 15:31:34 +02:00
2021-09-07 14:42:56 +02:00
# FIXME: Pozor, výš je ještě jeden ProblemView!
#class ProblemView(generic.DetailView):
# model = Problem
#
# # Používáme funkci, protože přímo template_name neumí mít v přiřazení dost logiky. Ledaže by se to udělalo polymorfně...
# def get_template_names(self, **kwargs):
# # FIXME: Switch podle typu není hezký, ale nechtělo se mi to přepisovat celé. Správně by se tohle mělo řešit polymorfismem.
# spravne_templaty = {
# s.Uloha: "uloha",
# s.Tema: "tema",
# s.Konfera: "konfera",
# s.Clanek: "clanek",
# }
# context = super().get_context_data(**kwargs)
# return ['seminar/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
#
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# # Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče.
# if not context['object'].verejne() and not self.request.user.je_org:
# raise PermissionDenied()
# if isinstance(context['object'], Clanek):
# context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni')
# return context
2015-09-13 15:31:34 +02:00
2015-12-19 23:11:50 +01:00
2020-03-25 23:57:11 +01:00
2019-07-26 00:01:23 +02:00
class CisloView ( generic . DetailView ) :
2020-09-03 23:03:08 +02:00
# FIXME zobrazování témátek a vůbec, teď je tam jen odkaz na číslo v pdf
2019-07-26 00:01:23 +02:00
model = Cislo
template_name = ' seminar/archiv/cislo.html '
2020-06-25 19:50:30 +02:00
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
2019-07-26 00:01:23 +02:00
def get_object ( self , queryset = None ) :
if queryset is None :
queryset = self . get_queryset ( )
rocnik_arg = self . kwargs . get ( ' rocnik ' )
2020-01-09 00:45:20 +01:00
poradi_arg = self . kwargs . get ( ' cislo ' )
queryset = queryset . filter ( rocnik__rocnik = rocnik_arg , poradi = poradi_arg )
2019-07-26 00:01:23 +02:00
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 )
cislo = context [ ' cislo ' ]
2021-01-05 22:54:16 +01:00
context [ ' prevcislo ' ] = Cislo . objects . filter ( ( Q ( rocnik__lt = self . object . rocnik ) | Q ( poradi__lt = self . object . poradi ) ) & Q ( rocnik__lte = self . object . rocnik ) ) . first ( )
2020-03-25 23:57:11 +01:00
# vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky
2020-04-08 23:44:06 +02:00
return vysledkovka_cisla ( cislo , context )
2019-07-26 00:01:23 +02:00
2015-03-13 20:08:18 +01:00
2015-09-09 22:52:06 +02:00
class ArchivTemataView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Problem
template_name = ' seminar/archiv/temata.html '
2020-05-06 23:26:06 +02:00
queryset = Tema . objects . filter ( stav = Problem . STAV_ZADANY ) . select_related ( ' rocnik ' ) . order_by ( ' rocnik ' , ' kod ' )
2020-05-06 23:07:04 +02:00
def get_context_data ( self , * args , * * kwargs ) :
ctx = super ( ) . get_context_data ( * args , * * kwargs )
ctx [ ' rocniky ' ] = OrderedDict ( )
2020-05-06 23:26:06 +02:00
for rocnik , temata in groupby ( ctx [ ' object_list ' ] , lambda tema : tema . rocnik ) :
ctx [ ' rocniky ' ] [ rocnik ] = list ( temata )
2020-05-06 23:07:04 +02:00
return ctx
2015-09-09 22:52:06 +02:00
2021-01-05 22:21:26 +01:00
class OdmenyView ( generic . TemplateView ) :
template_name = ' seminar/archiv/odmeny.html '
def get_context_data ( self , * * kwargs ) :
context = super ( ) . get_context_data ( * * kwargs )
2021-01-05 22:54:16 +01:00
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 ' ) )
2021-01-05 22:21:26 +01:00
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
2021-09-02 19:35:21 +02:00
2021-01-05 22:21:26 +01:00
2015-07-06 21:43:06 +02:00
### Generovani vysledkovky
2020-04-15 22:30:58 +02:00
class CisloVysledkovkaView ( CisloView ) :
2020-04-22 23:16:26 +02:00
""" View vytvořené pro stránku zobrazující výsledkovku čísla v TeXu. """
2020-04-15 22:30:58 +02:00
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
2020-04-08 23:44:06 +02:00
class RocnikVysledkovkaView ( RocnikView ) :
2020-04-22 23:16:26 +02:00
""" View vytvořené pro stránku zobrazující výsledkovku ročníku v TeXu. """
2020-04-08 23:44:06 +02:00
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
2015-08-13 10:52:43 +02:00
2020-05-21 00:12:27 +02:00
def cisloObalkyView ( request , rocnik , cislo ) :
2020-06-25 19:50:30 +02:00
realne_cislo = Cislo . objects . get ( poradi = cislo , rocnik__rocnik = rocnik )
return obalkyView ( request , aktivniResitele ( realne_cislo ) )
2015-11-15 15:14:21 +01:00
2020-05-21 00:12:27 +02:00
def obalkyView ( request , resitele ) :
2019-05-11 01:15:05 +02:00
tex = render ( request , ' seminar/archiv/obalky.tex ' , { ' resitele ' : resitele } ) . content
2015-11-15 15:14:21 +01:00
2019-05-11 01:15:05 +02:00
tempdir = tempfile . mkdtemp ( )
2019-11-13 22:00:08 +01:00
with open ( tempdir + " /obalky.tex " , " w " ) as texfile :
2020-05-21 00:12:27 +02:00
texfile . write ( tex . decode ( ) )
shutil . copy ( os . path . join ( settings . STATIC_ROOT , ' seminar/lisak.pdf ' ) , tempdir )
subprocess . call ( [ " pdflatex " , " obalky.tex " ] , cwd = tempdir )
2015-11-15 15:14:21 +01:00
2019-05-11 01:15:05 +02:00
with open ( tempdir + " /obalky.pdf " , " rb " ) as pdffile :
2020-05-21 00:12:27 +02:00
response = HttpResponse ( pdffile . read ( ) , content_type = ' application/pdf ' )
2019-05-11 01:15:05 +02:00
shutil . rmtree ( tempdir )
return response
2015-11-15 15:14:21 +01:00
2017-04-06 11:58:01 +02:00
2020-01-29 22:22:54 +01:00
def oldObalkovaniView ( request , rocnik , cislo ) :
2019-05-11 01:15:05 +02:00
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 }
)
2016-01-06 19:36:15 +01:00
2020-08-23 23:22:17 +02:00
### Orgostránky
2020-09-01 23:04:19 +02:00
class OrgoRozcestnikView ( TemplateView ) :
2020-08-23 23:22:17 +02:00
''' Zobrazí organizátorský rozcestník. '''
template_name = ' seminar/orgorozcestnik.html '
2020-09-01 23:04:19 +02:00
def get_context_data ( self , * * kwargs ) :
context = super ( ) . get_context_data ( * * kwargs )
context [ ' posledni_soustredeni ' ] = Soustredeni . objects . order_by ( ' -datum_konce ' ) . first ( )
nastaveni = Nastaveni . objects . first ( )
aktualni_rocnik = nastaveni . aktualni_rocnik
context [ ' posledni_cislo_url ' ] = nastaveni . aktualni_cislo . verejne_url ( )
# TODO možná chceme odkazovat na právě rozpracované číslo, a ne to poslední vydané
# pokud nechceme haluzit kód (= poradi) dalšího čísla, bude asi potřeba jít
# přes treenody (a dát si přitom pozor na MezicisloNode)
2021-06-30 04:04:14 +02:00
context [ ' pocet_neobodovanych_reseni ' ] = s . Hodnoceni . objects . filter ( body__isnull = True ) . count ( )
context [ ' pocet_reseni_mimo_cislo ' ] = s . Hodnoceni . objects . filter ( cislo_body__isnull = True ) . count ( )
2020-09-01 23:04:19 +02:00
u = self . request . user
os = s . Osoba . objects . get ( user = u )
organizator = s . Organizator . objects . get ( osoba = os )
2021-06-30 04:03:57 +02:00
#FIXME: přidat stav='STAV_ZADANY'
2021-09-02 19:35:21 +02:00
temata = s . Tema . objects . filter ( Q ( garant = organizator ) | Q ( autor = organizator ) | Q ( opravovatele__in = [ organizator ] ) ,
2021-06-30 04:03:57 +02:00
rocnik = aktualni_rocnik ) . distinct ( )
ulohy = s . Uloha . objects . filter ( Q ( garant = organizator ) | Q ( autor = organizator ) | Q ( opravovatele__in = [ organizator ] ) ,
cislo_zadani__rocnik = aktualni_rocnik ) . distinct ( )
clanky = s . Clanek . objects . filter ( Q ( garant = organizator ) | Q ( autor = organizator ) | Q ( opravovatele__in = [ organizator ] ) ,
cislo__rocnik = aktualni_rocnik ) . distinct ( )
context [ ' temata ' ] = temata
context [ ' ulohy ' ] = ulohy
context [ ' clanky ' ] = clanky
2020-09-01 23:04:19 +02:00
context [ ' organizator ' ] = organizator
return context
#content_type = 'text/plain; charset=UTF8'
2020-08-23 23:22:17 +02:00
#XXX
2015-11-15 16:14:07 +01:00
### Tituly
2020-04-16 00:51:38 +02:00
def TitulyView ( request , rocnik , cislo ) :
2020-04-22 23:16:26 +02:00
""" View pro stažení makra titulů v TeXu. """
2020-04-16 00:51:38 +02:00
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 , poradi = cislo )
asciijmena = [ ]
2021-09-02 19:35:21 +02:00
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
2020-04-22 23:16:26 +02:00
# pokud ano, vrátí se jako true
slovnik_s_body = body_resitelu ( resitele , rocnik_obj )
2020-04-16 00:51:38 +02:00
for resitel in resitele :
resitel . titul = resitel . get_titul ( slovnik_s_body [ resitel . id ] )
jmeno = resitel . osoba . jmeno + resitel . osoba . prijmeni
# převedeme jména a příjmení řešitelů do ASCII
ascii_jmeno_bytes = unicodedata . normalize ( ' NFKD ' , jmeno ) . encode ( " ascii " , " ignore " )
# vrátí se byte string, převedeme na standardní string
ascii_jmeno_divnoznaky = str ( ascii_jmeno_bytes , " utf-8 " , " ignore " ) . replace ( " " , " " )
resitel . ascii = ' ' . join ( a for a in ascii_jmeno_divnoznaky if a . isalnum ( ) )
if resitel . ascii not in asciijmena :
asciijmena . append ( resitel . ascii )
else :
jmenovci = True
2021-09-02 19:35:21 +02:00
2020-04-16 00:51:38 +02:00
return render ( request , ' seminar/archiv/tituly.tex ' ,
{ ' resitele ' : resitele , ' jmenovci ' : jmenovci } , content_type = " text/plain " )
2015-06-29 17:51:18 +02:00
### Soustredeni
2015-03-13 20:08:18 +01:00
2015-06-29 17:51:18 +02:00
class SoustredeniListView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Soustredeni
template_name = ' seminar/soustredeni/seznam_soustredeni.html '
2015-06-29 17:51:18 +02:00
2015-11-15 15:35:47 +01:00
def soustredeniObalkyView ( request , soustredeni ) :
2019-05-11 01:15:05 +02:00
soustredeni = get_object_or_404 ( Soustredeni , id = soustredeni )
return obalkyView ( request , soustredeni . ucastnici . all ( ) )
2015-11-15 15:35:47 +01:00
2017-04-06 11:58:01 +02:00
class SoustredeniUcastniciBaseView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Soustredeni_Ucastnici
2017-04-06 11:58:01 +02:00
2019-05-11 01:15:05 +02:00
def get_queryset ( self ) :
soustredeni = get_object_or_404 (
Soustredeni ,
pk = self . kwargs [ " soustredeni " ]
)
return Soustredeni_Ucastnici . objects . filter (
soustredeni = soustredeni ) . select_related ( ' resitel ' )
2017-04-06 11:58:01 +02:00
class SoustredeniMailyUcastnikuView ( SoustredeniUcastniciBaseView ) :
2020-04-22 23:16:26 +02:00
""" Seznam e-mailů řešitelů oddělených čárkami. """
2019-05-11 01:15:05 +02:00
model = Soustredeni_Ucastnici
template_name = ' seminar/soustredeni/maily_ucastniku.txt '
2017-04-06 11:58:01 +02:00
class SoustredeniUcastniciView ( SoustredeniUcastniciBaseView ) :
2020-04-22 23:16:26 +02:00
""" HTML tabulka účastníků pro tisk. """
2019-05-11 01:15:05 +02:00
model = Soustredeni_Ucastnici
template_name = ' seminar/soustredeni/seznam_ucastniku.html '
2017-04-06 11:58:01 +02:00
2016-10-08 21:46:31 +02:00
def soustredeniUcastniciExportView ( request , soustredeni ) :
2019-05-11 01:15:05 +02:00
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 " '
2016-10-08 21:46:31 +02:00
2020-05-07 00:55:21 +02:00
writer = csv . writer ( response )
2019-05-11 01:15:05 +02:00
writer . writerow ( [ " jmeno " , " prijmeni " , " rok_maturity " , " telefon " , " email " , " ulice " , " mesto " , " psc " , " stat " ] )
for u in ucastnici :
2020-05-07 00:55:21 +02:00
o = u . osoba
writer . writerow ( [ o . jmeno , o . prijmeni , str ( u . rok_maturity ) , o . telefon , o . email , o . ulice , o . mesto , o . psc , o . stat . name ] )
2019-05-11 01:15:05 +02:00
return response
2016-10-08 21:46:31 +02:00
2015-11-15 15:35:47 +01:00
2015-09-13 15:31:34 +02:00
### Články
2020-08-23 18:46:47 +02:00
def group_by_rocnik ( clanky ) :
''' Vezme zadaný seznam článků a seskupí je podle ročníku.
Vrátí seznam seznamů článků ze stejného ročníku . '''
2020-09-03 16:07:52 +02:00
if len ( clanky ) == 0 :
return clanky
2020-08-23 18:46:47 +02:00
clanky . order_by ( ' cislo__rocnik__rocnik ' )
skupiny_clanku = [ ]
skupina = [ ]
rocnik = clanky . first ( ) . cislo . rocnik . rocnik # první ročník
for clanek in clanky :
if clanek . cislo . rocnik . rocnik == rocnik :
skupina . append ( clanek )
else :
skupiny_clanku . append ( skupina )
skupina = [ ]
skupina . append ( clanek )
rocnik = clanek . cislo . rocnik . rocnik
skupiny_clanku . append ( skupina )
return skupiny_clanku
2021-09-02 19:35:21 +02:00
2015-09-13 15:31:34 +02:00
2019-04-23 23:26:37 +02:00
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
2020-09-04 15:37:04 +02:00
# FIXME: Původně tu byl kód přímo v těle třídy, což rozbíjelo migrace. Opravil jsem, ale vůbec nevím, jestli to funguje.
2015-09-13 15:31:34 +02:00
class ClankyResitelView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
model = Problem
template_name = ' seminar/clanky/resitelske_clanky.html '
2020-09-04 15:37:04 +02:00
# FIXME: QuerySet není pole!
def get_queryset ( self ) :
2021-02-16 20:10:34 +01:00
clanky = Clanek . objects . filter ( stav = Problem . STAV_VYRESENY ) . select_related ( ' cislo__rocnik ' ) . order_by ( ' -cislo__rocnik__rocnik ' )
2020-09-04 15:37:04 +02:00
queryset = [ ]
skupiny_clanku = group_by_rocnik ( clanky )
for skupina in skupiny_clanku :
2021-03-02 21:52:37 +01:00
skupina . sort ( key = lambda clanek : clanek . kod_v_rocniku ( ) )
2020-09-04 15:37:04 +02:00
for clanek in skupina :
queryset . append ( clanek )
return queryset
2015-09-13 15:31:34 +02:00
2019-04-23 23:26:37 +02:00
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
#class ClankyOrganizatorView(generic.ListView)<F12>:
2019-05-11 02:00:41 +02:00
# 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')
2015-09-13 15:31:34 +02:00
2015-07-29 11:46:08 +02:00
### Status
def StavDatabazeView ( request ) :
2019-05-11 02:00:41 +02:00
# nastaveni = Nastaveni.objects.get()
2019-05-11 01:15:05 +02:00
problemy = utils . seznam_problemu ( )
2020-06-04 00:38:28 +02:00
muzi = Resitel . objects . filter ( osoba__pohlavi_muz = True )
zeny = Resitel . objects . filter ( osoba__pohlavi_muz = False )
2019-05-11 01:15:05 +02:00
return render ( request , ' seminar/stav_databaze.html ' ,
{
2019-05-11 02:00:41 +02:00
# 'nastaveni': nastaveni,
2019-05-11 01:15:05 +02:00
' problemy ' : problemy ,
2015-07-30 11:56:29 +02:00
2019-05-11 01:15:05 +02:00
' resitele ' : Resitel . objects . all ( ) ,
' muzi ' : muzi ,
' zeny ' : zeny ,
2020-06-04 00:38:28 +02:00
' jmena_muzu ' : utils . histogram ( [ r . osoba . jmeno for r in muzi ] ) ,
' jmena_zen ' : utils . histogram ( [ r . osoba . jmeno for r in zeny ] ) ,
2019-05-11 01:15:05 +02:00
} )
2016-02-17 16:17:11 +01:00
2019-09-02 00:01:39 +02:00
class ResitelView ( LoginRequiredMixin , generic . DetailView ) :
model = Resitel
2020-07-02 14:32:43 +02:00
template_name = ' seminar/profil/resitel.html '
2019-09-02 00:01:39 +02:00
def get_object ( self , queryset = None ) :
print ( self . request . user )
return Resitel . objects . get ( osoba__user = self . request . user )
2020-04-22 23:44:15 +02:00
### Formulare
2020-12-01 21:20:54 +01:00
# 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
2020-02-05 23:30:41 +01:00
class AddSolutionView ( LoginRequiredMixin , FormView ) :
template_name = ' seminar/org/vloz_reseni.html '
form_class = f . VlozReseniForm
2021-05-04 23:52:26 +02:00
def form_valid ( self , form ) :
data = form . cleaned_data
nove_reseni = m . Reseni . objects . create (
cas_doruceni = data [ ' cas_doruceni ' ] ,
forma = data [ ' forma ' ] ,
poznamka = data [ ' poznamka ' ] ,
)
nove_reseni . resitele . add ( data [ ' resitel ' ] )
nove_reseni . problem . add ( data [ ' problem ' ] )
nove_reseni . save ( )
# Chtěl jsem, aby bylo vidět, že se to uložilo, tak přesměrovávám na profil.
return redirect ( reverse ( ' profil ' ) )
2020-02-05 23:30:41 +01:00
2020-05-20 21:44:12 +02:00
class NahrajReseniView ( LoginRequiredMixin , CreateView ) :
2020-02-28 21:34:53 +01:00
model = s . Reseni
2020-07-02 14:32:43 +02:00
template_name = ' seminar/profil/nahraj_reseni.html '
2020-02-28 21:34:53 +01:00
form_class = f . NahrajReseniForm
2021-09-05 14:54:33 +02:00
def get ( self , request , * args , * * kwargs ) :
# Zaříznutí starých řešitelů:
# FIXME: Je to tady dost naprasené, mělo by to asi být jinde…
osoba = m . Osoba . objects . get ( user = self . request . user )
resitel = osoba . resitel
if resitel . rok_maturity < = m . Nastaveni . get_solo ( ) . aktualni_rocnik . prvni_rok :
return render ( request , ' universal.html ' , {
' title ' : ' Nelze odevzdat ' ,
' error ' : ' Zdá se, že jsi již odmaturoval/a, a tedy nemůžeš odevzdat do našeho semináře řešení. ' ,
' text ' : ' Pokud se ti zdá, že to je chyba, napiš nám prosím e-mail. Díky. ' ,
} )
2021-09-05 14:56:55 +02:00
return super ( ) . get ( request , * args , * * kwargs )
2021-09-05 14:54:33 +02:00
2020-02-28 21:34:53 +01:00
def get_context_data ( self , * * kwargs ) :
data = super ( ) . get_context_data ( * * kwargs )
if self . request . POST :
2021-09-02 19:35:21 +02:00
data [ ' prilohy ' ] = f . ReseniSPrilohamiFormSet ( self . request . POST , self . request . FILES )
2020-02-28 21:34:53 +01:00
else :
2021-09-02 19:35:21 +02:00
data [ ' prilohy ' ] = f . ReseniSPrilohamiFormSet ( )
2020-02-28 21:34:53 +01:00
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 ' ]
2020-02-29 18:05:49 +01:00
if not prilohy . is_valid ( ) :
return super ( ) . form_invalid ( form )
2020-02-28 21:34:53 +01:00
with transaction . atomic ( ) :
self . object = form . save ( )
self . object . resitele . add ( Resitel . objects . get ( osoba__user = self . request . user ) )
2021-09-02 19:35:21 +02:00
self . object . cas_doruceni = timezone . now ( )
2020-02-28 21:34:53 +01:00
self . object . forma = s . Reseni . FORMA_UPLOAD
2020-02-28 21:42:06 +01:00
self . object . save ( )
2020-02-29 18:05:49 +01:00
prilohy . instance = self . object
prilohy . save ( )
2021-09-02 19:35:21 +02:00
2021-03-23 23:44:58 +01:00
# Pošleme mail opravovatelům a garantovi
# FIXME: Nechat spočítat databázi? Je to pár dotazů (pravděpodobně), takže to za to možná nestojí
prijemci = set ( )
2021-09-04 18:06:41 +02:00
problemy = [ ]
2021-03-23 23:44:58 +01:00
for prob in form . cleaned_data [ ' problem ' ] :
prijemci . update ( prob . opravovatele . all ( ) )
2021-09-04 22:05:35 +02:00
if prob . garant is not None :
prijemci . add ( prob . garant )
2021-09-04 18:06:41 +02:00
problemy . append ( prob )
2021-03-23 23:44:58 +01:00
# FIXME: Možná poslat mail i relevantním orgům nadproblémů?
2021-09-04 22:05:35 +02:00
if len ( prijemci ) < 1 :
logger . warning ( f " Pozor, neposílám e-mail nikomu. Problémy: { problemy } " )
2021-03-23 23:44:58 +01:00
# FIXME: Víc informativní obsah mailů, možná vč. příloh?
2021-08-04 17:51:50 +02:00
prijemci = map ( lambda it : it . osoba . email , prijemci )
2021-09-04 18:06:41 +02:00
resitel = Osoba . objects . get ( user = self . request . user )
2021-09-04 22:36:15 +02:00
seznam = " problému " + str ( problemy [ 0 ] ) if len ( problemy ) == 1 else ' následujícím problémům: \n ' + ' , \n ' . join ( map ( str , problemy ) )
2021-09-05 23:58:00 +02:00
seznam_do_subjectu = " problému " + str ( problemy [ 0 ] ) + ( " " if len ( problemy ) == 1 else f " (a dalším { len ( problemy ) - 1 } ) " )
2021-09-04 21:32:28 +02:00
2021-03-23 23:44:58 +01:00
send_mail (
2021-09-04 22:34:00 +02:00
subject = " Nové řešení k " + seznam_do_subjectu ,
2021-09-05 10:55:48 +02:00
message = f " Řešitel { ' ' if resitel . pohlavi_muz else ' ka ' } { resitel } právě nahrál { ' ' if resitel . pohlavi_muz else ' a ' } nové řešení k { seznam } . \n \n Hurá do opravování: { self . object . absolute_url ( ) } " ,
2021-03-23 23:44:58 +01:00
from_email = " submitovatko@mam.mff.cuni.cz " , # FIXME: Chceme to mít radši tady, nebo v nastavení?
recipient_list = list ( prijemci ) ,
)
2020-02-28 21:34:53 +01:00
2021-09-06 01:54:21 +02:00
return formularOKView ( self . request , text = ' Řešení úspěšně odevzdáno ' )
2020-02-28 21:34:53 +01:00
2018-12-05 23:37:05 +01:00
2019-11-20 23:56:51 +01:00
def prihlaska_log_gdpr_safe ( logger , gdpr_logger , msg , form_data ) :
2020-09-03 16:07:52 +02:00
msg = " {} , form_hash: {} " . format ( msg , hash ( frozenset ( form_data . items ) ) )
2019-11-20 23:56:51 +01:00
logger . warn ( msg )
2021-09-02 19:35:21 +02:00
gdpr_logger . warn ( msg + " , form: {} " . format ( form_data ) )
2019-11-20 23:56:51 +01:00
2019-11-27 23:45:45 +01:00
from django . forms . models import model_to_dict
2021-09-07 17:23:54 +02:00
@sensitive_post_parameters ( ' jmeno ' , ' prijmeni ' , ' email ' , ' telefon ' , ' datum_narozeni ' , ' ulice ' , ' mesto ' , ' psc ' , ' skola ' )
2019-11-27 23:45:45 +01:00
def resitelEditView ( request ) :
2020-09-01 23:04:19 +02:00
err_logger = logging . getLogger ( ' seminar.prihlaska.problem ' )
2020-12-24 07:43:05 +01:00
## Načtení objektů Osoba a Resitel patřících k aktuálně přihlášenému uživateli
2020-09-01 23:04:19 +02:00
u = request . user
osoba_edit = Osoba . objects . get ( user = u )
Osobni udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozitOsobni
udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozit.
2021-01-26 21:45:03 +01:00
if hasattr ( osoba_edit , ' resitel ' ) :
resitel_edit = osoba_edit . resitel
else :
resitel_edit = None
2020-09-01 23:04:19 +02:00
user_edit = osoba_edit . user
## Vytvoření slovníku, kterým předvyplním formulář
prefill_1 = model_to_dict ( user_edit )
2021-05-04 19:49:01 +02:00
if resitel_edit :
Osobni udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozitOsobni
udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozit.
2021-01-26 21:45:03 +01:00
prefill_2 = model_to_dict ( resitel_edit )
prefill_1 . update ( prefill_2 )
2020-09-01 23:04:19 +02:00
prefill_3 = model_to_dict ( osoba_edit )
prefill_1 . update ( prefill_3 )
2021-04-14 08:02:38 +02:00
if ' datum_narozeni ' in prefill_1 :
prefill_1 [ ' datum_narozeni ' ] = str ( prefill_1 [ ' datum_narozeni ' ] )
2021-05-04 20:34:15 +02:00
if ' rok_maturity ' not in prefill_1 or prefill_1 [ ' rok_maturity ' ] < date . today ( ) . year :
form = PoMaturiteProfileEditForm ( initial = prefill_1 )
else :
form = ProfileEditForm ( initial = prefill_1 )
2020-09-01 23:04:19 +02:00
## Změna údajů a jejich uložení
if request . method == ' POST ' :
2021-09-02 17:17:08 +02:00
POST = request . POST . copy ( )
POST [ " username " ] = osoba_edit . user . username
2021-05-04 20:34:15 +02:00
if ' rok_maturity ' not in prefill_1 or prefill_1 [ ' rok_maturity ' ] < date . today ( ) . year :
2021-09-02 17:17:08 +02:00
form = PoMaturiteProfileEditForm ( POST )
2021-05-04 20:34:15 +02:00
else :
2021-09-02 17:17:08 +02:00
form = ProfileEditForm ( POST )
2021-09-05 22:10:12 +02:00
form . username = user_edit . username
2020-09-01 23:04:19 +02:00
if form . is_valid ( ) :
## Změny v osobě
fcd = form . cleaned_data
2021-09-05 21:36:50 +02:00
form_hash = hash ( frozenset ( fcd . items ( ) ) )
form_logger = logging . getLogger ( ' seminar.prihlaska.form ' )
form_logger . info ( " EDIT: " + str ( fcd ) + str ( form_hash ) ) # TODO možná logovat jinak
2020-09-01 23:04:19 +02:00
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 ' ]
2021-04-14 08:02:38 +02:00
osoba_edit . datum_narozeni = fcd [ ' datum_narozeni ' ]
2020-09-01 23:04:19 +02:00
## 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 ' ] )
2021-05-04 19:49:01 +02:00
if resitel_edit :
Osobni udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozitOsobni
udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozit.
2021-01-26 21:45:03 +01:00
## Změny v řešiteli
2020-09-01 23:04:19 +02:00
resitel_edit . skola = fcd [ ' skola ' ]
Osobni udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozitOsobni
udaje edit | Preskocit resitelske veci, pokud org nema resitele.
Pokud org nema resitele, tak se ve formulari sice zobrazi skola a rok
maturity, ale zadana data se ignoruji, protoze neni, kam je ulozit.
2021-01-26 21:45:03 +01:00
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 :
# Unknown school - log it
msg = " Unknown school {} , {} " . format ( fcd [ ' skola_nazev ' ] , fcd [ ' skola_adresa ' ] )
resitel_edit . save ( )
2020-09-01 23:04:19 +02:00
osoba_edit . save ( )
2021-09-06 01:48:17 +02:00
return formularOKView ( request , text = f ' Údaje byly úspěšně uloženy. <a href= " { reverse ( " profil " ) } >Vrátit se zpět na profil.</a> ' )
2021-09-05 21:38:29 +02:00
return render ( request , ' seminar/profil/edit.html ' , { ' form ' : form } )
2019-11-20 23:56:51 +01:00
2021-09-07 17:23:54 +02:00
@sensitive_post_parameters ( ' jmeno ' , ' prijmeni ' , ' email ' , ' telefon ' , ' datum_narozeni ' , ' ulice ' , ' mesto ' , ' psc ' , ' skola ' )
2019-08-13 23:16:44 +02:00
def prihlaskaView ( request ) :
2019-11-20 23:56:51 +01:00
generic_logger = logging . getLogger ( ' seminar.prihlaska ' )
2019-11-08 00:11:33 +01:00
err_logger = logging . getLogger ( ' seminar.prihlaska.problem ' )
form_logger = logging . getLogger ( ' seminar.prihlaska.form ' )
2019-05-11 01:15:05 +02:00
if request . method == ' POST ' :
2019-08-13 23:16:44 +02:00
form = PrihlaskaForm ( request . POST )
2019-11-20 23:56:51 +01:00
# TODO vyresit, co se bude v jakych situacich zobrazovat
2019-05-11 01:15:05 +02:00
if form . is_valid ( ) :
2019-11-20 23:56:51 +01:00
generic_logger . info ( " Form valid " )
2019-11-08 00:11:33 +01:00
fcd = form . cleaned_data
2020-09-03 16:07:52 +02:00
form_hash = hash ( frozenset ( fcd . items ( ) ) )
2020-09-03 22:00:54 +02:00
form_logger . info ( str ( fcd ) + str ( form_hash ) ) # TODO možná logovat jinak
2021-09-02 19:35:21 +02:00
2019-09-01 16:35:20 +02:00
with transaction . atomic ( ) :
2019-09-01 22:59:05 +02:00
u = User . objects . create_user (
2019-11-08 00:11:33 +01:00
username = fcd [ ' username ' ] ,
email = fcd [ ' email ' ] )
2019-09-01 16:35:20 +02:00
u . save ( )
2020-09-05 19:20:41 +02:00
resitel_perm = Permission . objects . filter ( codename__exact = ' resitel ' ) . first ( )
u . user_permissions . add ( resitel_perm )
2021-09-02 15:55:03 +02:00
resitel_grp = Group . objects . filter ( name__exact = ' resitel ' ) . first ( )
2021-09-02 15:56:24 +02:00
u . groups . add ( resitel_grp )
2019-09-01 16:35:20 +02:00
o = Osoba (
2019-11-08 00:11:33 +01:00
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 ) ,
2019-09-01 16:35:20 +02:00
datum_souhlasu_udaje = date . today ( ) ,
datum_registrace = date . today ( ) ,
2019-11-08 00:11:33 +01:00
ulice = fcd . get ( ' ulice ' , ' ' ) ,
mesto = fcd . get ( ' mesto ' , ' ' ) ,
psc = fcd . get ( ' psc ' , ' ' ) ,
poznamka = str ( fcd )
2019-09-01 16:35:20 +02:00
)
2021-09-05 21:35:13 +02:00
2019-11-08 00:11:33 +01:00
if fcd . get ( ' spam ' , False ) :
2019-09-01 16:35:20 +02:00
o . datum_souhlasu_zasilani = date . today ( )
2019-11-08 00:11:33 +01:00
if fcd . get ( ' stat ' , ' ' ) in ( ' CZ ' , ' SK ' ) :
o . stat = fcd [ ' stat ' ]
2019-09-01 16:35:20 +02:00
else :
2019-11-08 00:11:33 +01:00
# Unknown country - log it
2019-11-20 23:56:51 +01:00
msg = " Unknown country {} " . format ( fcd [ ' stat_text ' ] )
2020-09-03 22:00:54 +02:00
err_logger . warn ( msg + str ( form_hash ) )
2019-09-01 16:35:20 +02:00
2021-09-05 21:35:13 +02:00
# Dovolujeme doregistraci uživatele pro existující mail, takže naopak chceme doplnit/aktualizovat údaje do stávajícího objektu
try :
orig_osoba = m . Osoba . objects . get ( email = fcd [ ' email ' ] )
2021-09-05 22:07:10 +02:00
orig_osoba . poznamka + = ' \n DOREGISTRACE K EXISTUJÍCÍMU E-MAILU, diff níže. '
2021-09-05 21:35:13 +02:00
except m . Osoba . DoesNotExist :
# Trik: Budeme aktualizovat údaje nové osoby, takže se asi nic nezmění, ale fungovat to bude.
orig_osoba = o
# Porovnání údajů
assert orig_osoba . user is None , " Právě-registrující-se osoba už má Uživatele! "
osoba_attrs = [ ' jmeno ' , ' prijmeni ' , ' pohlavi_muz ' , ' email ' , ' telefon ' , ' datum_narozeni ' , ' ulice ' , ' mesto ' , ' psc ' , ' stat ' , ' datum_souhlasu_udaje ' , ' datum_souhlasu_zasilani ' , ' datum_registrace ' ]
diffattrs = [ ]
for attr in osoba_attrs :
new = getattr ( o , attr )
old = getattr ( orig_osoba , attr )
if new != old :
orig_osoba . poznamka + = f ' \n Rozdíl v { attr } : Původní { old } , nový { new } '
diffattrs . append ( f ' Osoba. { attr } ' )
setattr ( orig_osoba , attr , new )
# Datum registrace chceme původní / nižší:
orig_osoba . datum_registrace = min ( orig_osoba . datum_registrace , o . datum_registrace )
# Od této chvíle dál je správná osoba ta "původní", novou podle formuláře si ale zachováme
o , o_form = orig_osoba , o
2021-09-05 22:17:57 +02:00
2019-09-01 16:35:20 +02:00
o . save ( )
o . user = u
o . save ( )
2021-09-05 22:17:57 +02:00
# Jednoduchá kvazi-kontrola duplicitních Osob
kolize = m . Osoba . objects . filter ( jmeno = o . jmeno , prijmeni = o . prijmeni )
if kolize . count ( ) > 1 : # Jednu z nich jsme právě uložili
err_logger . warning ( f ' Zaregistrovala se osoba s kolizním jménem. ID osob: { [ o . id for o in kolize ] } ' )
2019-09-01 16:35:20 +02:00
r = Resitel (
2019-11-08 00:11:33 +01:00
rok_maturity = fcd [ ' rok_maturity ' ] ,
2020-12-01 21:20:54 +01:00
zasilat = fcd [ ' zasilat ' ] ,
zasilat_cislo_emailem = fcd [ ' zasilat_cislo_emailem ' ]
2019-09-01 16:35:20 +02:00
)
2021-09-02 19:35:21 +02:00
2019-11-08 00:11:33 +01:00
if fcd . get ( ' skola ' ) :
r . skola = fcd [ ' skola ' ]
2019-09-01 16:35:20 +02:00
else :
2019-11-08 00:11:33 +01:00
# Unknown school - log it
2019-11-20 23:56:51 +01:00
msg = " Unknown school {} , {} " . format ( fcd [ ' skola_nazev ' ] , fcd [ ' skola_adresa ' ] )
2020-09-03 22:00:54 +02:00
err_logger . warn ( msg + str ( form_hash ) )
2021-09-05 21:35:13 +02:00
# Porovnání údajů u řešitele
try :
orig_resitel = o . resitel
2021-09-05 22:07:10 +02:00
orig_resitel . poznamka + = ' \n DOREGISTRACE ŘEŠITELE, diff: '
2021-09-05 21:35:13 +02:00
except m . Resitel . DoesNotExist :
# Stejný trik:
orig_resitel = r
2021-09-05 22:07:10 +02:00
resitel_attrs = [ ' skola ' , ' rok_maturity ' , ' zasilat ' , ' zasilat_cislo_emailem ' ]
2021-09-05 21:35:13 +02:00
for attr in resitel_attrs :
new = getattr ( r , attr )
old = getattr ( orig_resitel , attr )
if new != old :
orig_resitel . poznamka + = f ' \n Rozdíl v { attr } : Původní { old } , nový { new } '
diffattrs . append ( f ' Resitel. { attr } ' )
setattr ( orig_resitel , attr , new )
r , r_form = orig_resitel , r
r . save ( )
r . osoba = o # Tohle by mělo být bezpečné…
2019-09-01 16:35:20 +02:00
r . save ( )
2019-08-31 19:36:12 +02:00
2021-09-05 21:35:13 +02:00
if diffattrs : err_logger . warning ( f ' Different fields when matching Řešitel id { r . id } or Osoba id { o . id } : { diffattrs } ' )
2021-09-02 19:35:21 +02:00
uid = urlsafe_base64_encode ( force_bytes ( u . pk ) )
token = PasswordResetTokenGenerator ( ) . make_token ( u )
url = " https:// %s %s " % (
str ( get_current_site ( request ) ) ,
2021-09-07 17:04:14 +02:00
str ( reverse_lazy ( " reset_password_confirm " , args = [ uid , token ] ) )
2021-09-02 19:35:21 +02:00
)
u . email_user (
2021-09-02 20:33:52 +02:00
subject = " Vítej mezi řešiteli M&M! " ,
message = """ Milý řešiteli, milá řešitelko,
tvůj e - mail byl právě zaregistrován na mam . matfyz . cz . Heslo si prosím nastav na : % s
Těšíme se na tvé příspěvky do našeho semináře ,
Organizátoři M & M
- -
Tento e - mail byl vygenerován automaticky , chceš - li nás kontaktovat , napiš nám na adresu mam @matfyz.cz .
""" % u rl,
2021-09-02 19:35:21 +02:00
# TODO: templates/seminar/registrace a django/contrib/auth/forms.py říkají, jak na to lépe
2021-08-04 18:03:37 +02:00
from_email = " registrace@mam.mff.cuni.cz " , # FIXME: Chceme to mít radši tady, nebo v nastavení?
)
2019-08-31 19:36:12 +02:00
2021-09-06 01:48:17 +02:00
return formularOKView ( request , text = ' Na tvůj e-mail jsme právě poslali odkaz pro nastavení hesla. ' )
2019-05-11 01:15:05 +02:00
# if a GET (or any other method) we'll create a blank form
else :
2019-08-13 23:16:44 +02:00
form = PrihlaskaForm ( )
2019-05-11 01:15:05 +02:00
2020-07-02 14:32:43 +02:00
return render ( request , ' seminar/profil/prihlaska.html ' , { ' form ' : form } )
2016-11-14 09:06:48 +01:00
2019-12-13 16:38:56 +01:00
# 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
2020-07-02 14:32:43 +02:00
template_name = ' seminar/profil/login.html '
2019-12-13 16:38:56 +01:00
2019-12-19 01:30:48 +01:00
class LogoutView ( auth_views . LogoutView ) :
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL
2020-07-02 14:32:43 +02:00
template_name = ' seminar/profil/logout.html '
2019-12-19 01:30:48 +01:00
# Pavel: Vůbec nevím, proč to s _lazy funguje, ale bez toho to bylo rozbité.
next_page = reverse_lazy ( ' titulni_strana ' )
2021-09-07 17:23:54 +02:00
# Nejsem si jistý, který view co dostává, tak zahazuji všechny POSTy
2019-12-19 01:30:48 +01:00
class PasswordResetView ( auth_views . PasswordResetView ) :
2020-04-22 23:44:15 +02:00
""" Chci resetovat heslo. """
2021-09-02 22:55:02 +02:00
template_name = ' seminar/registrace/reset_hesla.html '
2019-12-19 01:30:48 +01:00
success_url = reverse_lazy ( ' reset_password_done ' )
from_email = ' login@mam.mff.cuni.cz '
2021-03-30 22:06:02 +02:00
email_template_name = ' seminar/registrace/password_reset_email.html '
subject_template_name = ' seminar/registrace/password_reset_subject.txt '
2019-12-19 01:30:48 +01:00
class PasswordResetDoneView ( auth_views . PasswordResetDoneView ) :
2020-04-22 23:44:15 +02:00
""" Poslali jsme e-mail (pokud bylo kam)). """
2021-09-02 22:55:02 +02:00
template_name = ' seminar/registrace/reset_poslan.html '
2019-12-19 01:30:48 +01:00
class PasswordResetConfirmView ( auth_views . PasswordResetConfirmView ) :
2020-04-22 23:44:15 +02:00
""" Vymysli si heslo. """
2021-09-02 22:55:02 +02:00
template_name = ' seminar/registrace/nove_heslo.html '
2019-12-19 01:30:48 +01:00
success_url = reverse_lazy ( ' reset_password_complete ' )
class PasswordResetCompleteView ( auth_views . PasswordResetCompleteView ) :
2020-04-22 23:44:15 +02:00
""" Heslo se asi změnilo. """
2021-09-02 22:55:02 +02:00
template_name = ' seminar/registrace/nove_nastaveno.html '
2019-12-19 01:30:48 +01:00
class PasswordChangeView ( auth_views . PasswordChangeView ) :
#template_name = 'seminar/password_change.html'
success_url = reverse_lazy ( ' titulni_strana ' )
2020-09-03 23:02:28 +02:00
class VueTestView ( generic . TemplateView ) :
template_name = ' seminar/vuetest.html '
2020-10-21 08:36:02 +02:00
class NahrajObrazekKTreeNoduView ( LoginRequiredMixin , CreateView ) :
model = s . Obrazek
form_class = f . NahrajObrazekKTreeNoduForm
def get_initial ( self ) :
initial = super ( ) . get_initial ( )
initial [ ' na_web ' ] = self . request . FILES [ ' upload ' ]
return initial
def form_valid ( self , form ) :
print ( self . request . headers )
print ( self . request . headers [ ' Textid ' ] )
print ( form . instance )
print ( form )
self . object = form . save ( commit = False )
print ( self . object . na_web )
self . object . text = m . Text . objects . get ( pk = int ( self . request . headers [ ' Textid ' ] ) )
self . object . save ( )
return JsonResponse ( { " url " : self . object . na_web . url } )
2021-09-02 19:35:21 +02:00
2020-09-04 16:28:38 +02:00
# Jen hloupé rozhazovátko
def profilView ( request ) :
user = request . user
2020-09-05 19:20:41 +02:00
if user . has_perm ( ' auth.org ' ) :
2020-09-04 16:28:38 +02:00
return OrgoRozcestnikView . as_view ( ) ( request )
2020-09-05 19:20:41 +02:00
if user . has_perm ( ' auth.resitel ' ) :
2020-09-04 16:28:38 +02:00
return ResitelView . as_view ( ) ( request )
else :
return LoginView . as_view ( ) ( request )
2020-09-04 18:05:33 +02:00
# Interní, nemá se nikdy objevit v urls (jinak to účastníci vytrolí)
2021-09-06 01:48:17 +02:00
def formularOKView ( request , text = ' ' ) :
2020-09-04 18:05:33 +02:00
template_name = ' seminar/formular_ok.html '
odkazy = [
# (Text, odkaz)
( ' Vrátit se na titulní stránku ' , reverse ( ' titulni_strana ' ) ) ,
( ' Zobrazit aktuální zadání ' , reverse ( ' seminar_aktualni_zadani ' ) ) ,
]
context = {
' odkazy ' : odkazy ,
2021-09-06 01:48:17 +02:00
' text ' : text ,
2020-09-04 18:05:33 +02:00
}
return render ( request , template_name , context )
2020-09-21 13:19:07 +02:00
#------------------ Jak řešit - možná má být udělané úplně jinak
2021-09-02 19:35:21 +02:00
2020-09-21 13:19:07 +02:00
class JakResitView ( generic . ListView ) :
template_name = ' seminar/jak-resit.html '
2021-09-02 19:35:21 +02:00
2020-09-21 13:19:07 +02:00
def get_queryset ( self ) :
2020-10-13 23:25:39 +02:00
return None
2021-04-28 21:26:30 +02:00
class AktualniRocnikRedirectView ( RedirectView ) :
permanent = False
pattern_name = ' seminar_rocnik '
def get_redirect_url ( self , * args , * * kwargs ) :
aktualni_rocnik = m . Nastaveni . get_solo ( ) . aktualni_rocnik . rocnik
return super ( ) . get_redirect_url ( rocnik = aktualni_rocnik , * args , * * kwargs )