2015-09-07 09:37:29 +02:00
# coding:utf-8
2015-03-13 20:08:18 +01:00
from django . shortcuts import get_object_or_404 , render
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
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
2020-02-28 21:34:53 +01:00
from django . views . generic . edit import FormView , CreateView
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
2019-11-08 00:11:33 +01:00
from django . contrib . auth . models import User
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
2015-06-08 22:38:13 +02:00
2019-12-05 00:50:04 +01:00
import seminar . models as s
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
2020-03-03 21:48:55 +01:00
from seminar . forms import PrihlaskaForm , LoginForm , ProfileEditForm
2020-02-05 23:30:41 +01:00
import seminar . forms as f
2015-03-27 21:38:48 +01:00
2015-09-13 16:52:30 +02:00
from datetime import timedelta , date , datetime
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
2015-09-03 22:09:35 +02:00
2015-09-23 18:16:17 +02:00
def verejna_temata ( rocnik ) :
2019-05-11 01:15:05 +02:00
""" Vrací queryset zveřejněných témat v daném ročníku.
"""
2019-07-26 00:01:23 +02:00
return Problem . objects . filter ( typ = Problem . TYP_TEMA , cislo_zadani__rocnik = rocnik , cislo_zadani__verejne_db = True ) . order_by ( ' kod ' )
2015-09-23 18:16:17 +02:00
2020-01-29 22:22:54 +01:00
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 )
2020-03-25 23:57:11 +01:00
self . reseni = Reseni . objects . filter ( problem__in = self . problemy )
2020-01-29 22:22:54 +01:00
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 )
2020-03-25 23:57:11 +01: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 ) :
def __init__ ( self , anode ) :
self . node = anode
self . children = [ ]
2020-01-29 22:22:54 +01:00
2020-03-19 00:50:39 +01:00
def treenode_strom_na_seznamy ( node ) :
out = TNLData ( node )
for ch in treelib . all_children ( node ) :
outitem = treenode_strom_na_seznamy ( ch )
out . children . append ( outitem )
return out
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 )
context [ ' tnldata ' ] = treenode_strom_na_seznamy ( self . object )
return context
2019-12-18 22:50:17 +01:00
2020-03-26 00:09:38 +01: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
2019-12-05 00:50:04 +01:00
2020-03-26 00:09:38 +01:00
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
2020-03-25 23:57:11 +01:00
#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,
# },
# )
#
2020-03-19 00:50:39 +01:00
#def ZadaniTemataView(request):
# nastaveni = get_object_or_404(Nastaveni)
# temata = verejna_temata(nastaveni.aktualni_rocnik)
# for t in temata:
# if request.user.is_staff:
# t.prispevky = t.prispevek_set.filter(problem=t)
# else:
# t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True)
# return render(request, 'seminar/zadani/Temata.html',
# {
# 'temata': temata,
# }
# )
#
#
#
#def TematkoView(request, rocnik, tematko):
# nastaveni = s.Nastaveni.objects.first()
# rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik)
# tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko)
# seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode)
# for node, depth in seznam:
# if node.isinstance(node, s.KonferaNode):
# raise Exception("Not implemented yet")
# if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou
# pass
#
# return render(request, 'seminar/tematka/toaletak.html', {})
#
#
#def TemataRozcestnikView(request):
# print("=============================================")
# nastaveni = s.Nastaveni.objects.first()
# tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik())
# tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
# for tematko_object in tematka_objects:
# print("AKTUALNI TEMATKO")
# print(tematko_object.id)
# odkazy = vytahniZLesaSeznam(tematko_object, nastaveni.aktualni_rocnik().rocniknode, pouze_zajimave = True) #Odkazy jsou tuply (node, depth) v listu
# print(odkazy)
# cisla = [] # List tuplů (nazev cisla, list odkazů)
# vcisle = []
# cislo = None
# for odkaz in odkazy:
# if odkaz[1] == 0:
# if cislo != None:
# cisla.append((cislo, vcisle))
# cislo = (odkaz[0].getOdkazStr(), odkaz[0].getOdkaz())
# vcisle = []
# else:
# print(odkaz[0].getOdkaz())
# vcisle.append((odkaz[0].getOdkazStr(), odkaz[0].getOdkaz()))
# if cislo != None:
# cisla.append((cislo, vcisle))
#
# print(cisla)
# tematka.append({
# "kod" : tematko_object.kod,
# "nazev" : tematko_object.nazev,
# "abstrakt" : tematko_object.abstrakt,
# "obrazek": tematko_object.obrazek,
# "cisla" : cisla
# })
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
#
2016-07-24 23:16:06 +02:00
2019-04-23 23:26:37 +02:00
#def ZadaniAktualniVysledkovkaView(request):
2019-05-11 02:00:41 +02:00
# 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,
# }
# )
2015-09-23 17:28:14 +02:00
2015-09-03 22:09:35 +02:00
### Titulni strana
class TitulniStranaView ( generic . ListView ) :
2019-05-11 01:15:05 +02:00
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 ,
2019-05-11 02:00:41 +02:00
datetime . max . time ( ) )
2019-05-11 01:15:05 +02:00
context [ ' ted ' ] = datetime . now ( )
except :
context [ ' dead ' ] = None
else :
context [ ' dead ' ] = None
context [ ' deadline_soustredeni ' ] = deadline_soustredeni
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
model = Novinky
template_name = ' seminar/stare_novinky.html '
queryset = Novinky . objects . filter ( zverejneno = True ) . order_by ( ' -datum ' )
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
2020-04-15 21:03:10 +02:00
for i , c in enumerate ( cisla ) :
if c . titulka_nahled :
urls [ c . rocnik ] = c . titulka_nahled . url
else :
urls [ c . rocnik ] = op . join ( settings . MEDIA_URL , " cislo " , " png " , " default.png " )
2020-04-01 23:09:58 +02:00
context [ " object_list " ] = urls
2020-04-01 23:28:26 +02:00
2019-05-11 01:15:05 +02:00
return context
2017-02-04 23:28:54 +01:00
2019-10-16 20:11:02 +02:00
### Výsledky
2015-09-08 21:27:10 +02:00
2020-04-08 23:44:06 +02:00
def sloupec_s_poradim ( setrizene_body ) :
2020-04-22 23:16:26 +02:00
""" Ze seznamu obsahujícího sestupně setřízené body řešitelů za daný ročník
vytvoří seznam s pořadími ( včetně 3. - 5. a pak 2 volná místa atp . ) ,
podle toho , jak jdou za sebou ve výsledkovce .
Parametr :
setrizene_body ( seznam integerů ) : sestupně setřízená čísla
Výstup :
sloupec_s_poradim ( seznam stringů )
"""
2020-04-08 23:44:06 +02:00
# ze seznamu obsahujícího setřízené body spočítáme sloupec s pořadím
2019-11-20 23:56:51 +01:00
aktualni_poradi = 1
sloupec_s_poradim = [ ]
# seskupíme seznam všech bodů podle hodnot
2020-04-08 23:44:06 +02:00
for index in range ( 0 , len ( setrizene_body ) ) :
2019-11-20 23:56:51 +01:00
# 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
2020-01-09 00:45:20 +01:00
if ( index + 1 ) < aktualni_poradi :
2019-11-20 23:56:51 +01:00
sloupec_s_poradim . append ( " " )
continue
velikost_skupiny = 0
# zjistíme počet po sobě jdoucích stejných hodnot
2020-04-08 23:44:06 +02:00
while setrizene_body [ index ] == setrizene_body [ index + velikost_skupiny ] :
2019-11-20 23:56:51 +01:00
velikost_skupiny = velikost_skupiny + 1
# na konci musíme ošetřit přetečení seznamu
2020-04-08 23:44:06 +02:00
if ( index + velikost_skupiny ) > len ( setrizene_body ) - 1 :
2019-11-20 23:56:51 +01:00
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
2019-05-11 01:15:05 +02:00
else :
2020-03-25 23:57:11 +01:00
sloupec_s_poradim . append ( " {} .– {} . " . format ( aktualni_poradi ,
2019-11-20 23:56:51 +01:00
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
2015-09-08 21:27:10 +02:00
2020-04-08 23:44:06 +02:00
def cisla_rocniku ( rocnik , jen_verejne = True ) :
2020-04-22 23:16:26 +02:00
""" Vrátí všechna čísla daného ročníku.
Parametry :
rocnik ( Rocnik ) : ročník semináře
jen_verejne ( bool ) : zda se mají vrátit jen veřejná , nebo všechna čísla
Vrátí :
seznam objektů typu Cislo
"""
2020-04-08 23:44:06 +02:00
if jen_verejne :
return rocnik . verejna_cisla ( )
else :
return rocnik . cisla . all ( )
2020-03-11 23:00:54 +01:00
def hlavni_problem ( problem ) :
2020-04-22 23:16:26 +02:00
""" Pro daný problém vrátí jeho nejvyšší nadproblém. """
2020-03-11 23:00:54 +01:00
while not ( problem . nadproblem == None ) :
problem = problem . nadproblem
return problem
2019-10-16 20:11:02 +02:00
2020-04-08 23:44:06 +02:00
def hlavni_problemy_rocniku ( rocnik , jen_verejne = True ) :
2020-04-22 23:16:26 +02:00
""" Pro zadaný ročník vrátí hlavní problémy ročníku,
tj . ty , které už nemají nadproblém . """
2020-04-08 23:44:06 +02:00
hlavni_problemy = [ ]
for cislo in cisla_rocniku ( rocnik , jen_verejne ) :
for problem in hlavni_problemy_cisla ( cislo ) :
hlavni_problemy . append ( problem )
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 pořadí
return hlavni_problemy
2019-10-16 20:11:02 +02:00
def hlavni_problemy_cisla ( cislo ) :
2020-04-22 23:16:26 +02:00
""" Vrátí seznam všech problémů s body v daném čísle, které již nemají nadproblém. """
2020-03-25 23:57:11 +01:00
hodnoceni = cislo . hodnoceni . select_related ( ' problem ' , ' reseni ' ) . all ( )
# hodnocení, která se vážou k danému číslu
2019-10-16 20:11:02 +02:00
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čí
2020-03-25 23:57:11 +01:00
# hlavní problémy čísla
2019-10-16 20:11:02 +02:00
# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém)
hlavni_problemy = [ ]
for p in problemy :
2020-03-11 23:00:54 +01:00
hlavni_problemy . append ( hlavni_problem ( p ) )
2019-10-16 20:11:02 +02:00
# zunikátnění
hlavni_problemy_set = set ( hlavni_problemy )
hlavni_problemy = list ( hlavni_problemy_set )
2020-01-09 00:45:20 +01:00
hlavni_problemy . sort ( key = lambda k : k . kod_v_rocniku ( ) ) # setřídit podle t1, t2, c3, ...
2020-03-25 23:57:11 +01:00
2019-10-16 20:11:02 +02:00
return hlavni_problemy
2020-04-22 23:16:26 +02:00
def body_resitelu ( resitele , za , odjakziva = True ) :
""" Funkce počítající počty bodů pro zadané řešitele,
buď odjakživa do daného ročníku / čísla anebo za daný ročník / číslo .
Parametry :
resitele ( seznam obsahující položky typu Resitel ) : aktivní řešitelé
za ( Rocnik / Cislo ) : za co se mají počítat body
( generování starších výsledkovek )
odjakziva ( bool ) : zda se mají počítat body odjakživa , nebo jen za číslo / ročník
zadané v " za "
Výstup :
slovník ( Resitel . id ) : body
"""
resitele_id = [ r . id for r in resitele ]
# Zjistíme, typ objektu v parametru "za"
if isinstance ( za , Rocnik ) :
cislo = None
rocnik = za
rok = rocnik . prvni_rok
elif isinstance ( za , Cislo ) :
cislo = za
rocnik = None
rok = cislo . rocnik . prvni_rok
else :
assert True , " body_resitelu: za není ani číslo ani ročník. "
# Kvůli rychlosti používáme sčítáme body už v databázi, viz
# https://docs.djangoproject.com/en/3.0/topics/db/aggregation/,
# sekce Filtering on annotations (protože potřebujeme filtrovat výsledky
# jen do nějakého data, abychom uměli správně nagenerovat výsledkovky i
# za historická čísla.
# Níže se vytváří dotaz na součet bodů za správně vyfiltrovaná hodnocení,
# který se použije ve výsledném dotazu.
if cislo and odjakziva : # Body se sčítají odjakživa do zadaného čísla.
# Vyfiltrujeme všechna hodnocení, která jsou buď ze starších ročníků,
# anebo ze stejného ročníku, jak je zadané číslo, tam ale sčítáme jen
# pro čísla s pořadím nejvýše stejným, jako má zadané číslo.
body_k_zapocteni = Sum ( ' reseni__hodnoceni__body ' ,
filter = ( Q ( reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lt = rok ) |
Q ( reseni__hodnoceni__cislo_body__rocnik__prvni_rok = rok ,
reseni__hodnoceni__cislo_body__poradi__lte = cislo . poradi ) ) )
elif cislo and not odjakziva : # Body se sčítají za dané číslo.
body_k_zapocteni = Sum ( ' reseni__hodnoceni__body ' ,
2020-05-21 00:12:27 +02:00
filter = ( Q ( reseni__hodnoceni__cislo_body__rocnik__prvni_rok = rok ,
reseni__hodnoceni__cislo_body__poradi__lte = cislo . poradi ) ) )
2020-04-22 23:16:26 +02:00
elif rocnik and odjakziva : # Spočítáme body za starší ročníky až do zadaného včetně.
body_k_zapocteni = Sum ( ' reseni__hodnoceni__body ' ,
filter = Q ( reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte = rok ) )
elif rocnik and not odjakziva : # Spočítáme body za daný ročník.
body_k_zapocteni = Sum ( ' reseni__hodnoceni__body ' ,
filter = Q ( reseni__hodnoceni__cislo_body__rocnik = rocnik ) )
else :
assert True , " body_resitelu: Neplatná kombinace za a odjakživa. "
2020-04-15 23:41:01 +02:00
# Následující řádek přidá ke každému řešiteli údaj ".body" se součtem jejich bodů
2020-04-22 23:16:26 +02:00
resitele_s_body = Resitel . objects . filter ( id__in = resitele_id ) . annotate (
body = body_k_zapocteni )
# Teď jen z QuerySetu řešitelů anotovaných body vygenerujeme slovník
# indexovaný řešitelským id obsahující body.
# Pokud jsou body None, nahradíme za 0.
slovnik = { int ( res . id ) : ( res . body if res . body else 0 ) for res in resitele_s_body }
return slovnik
2020-03-11 23:00:54 +01:00
2020-04-08 23:44:06 +02:00
class RadekVysledkovkyRocniku ( object ) :
2020-04-22 23:16:26 +02:00
""" Obsahuje věci, které se hodí vědět při konstruování výsledkovky.
2020-04-08 23:44:06 +02:00
Umožňuje snazší práci v templatu ( lepší , než seznam ) . """
2020-04-15 22:30:58 +02:00
def __init__ ( self , poradi , resitel , body_cisla_sezn , body_rocnik , body_odjakziva , rok ) :
2020-04-08 23:44:06 +02:00
self . poradi = poradi
self . resitel = resitel
2020-04-15 22:30:58 +02:00
self . rocnik_resitele = resitel . rocnik ( rok )
2020-04-08 23:44:06 +02:00
self . body_rocnik = body_rocnik
self . body_celkem_odjakziva = body_odjakziva
self . body_cisla_sezn = body_cisla_sezn
2020-04-15 22:53:17 +02:00
self . titul = resitel . get_titul ( body_odjakziva )
2020-04-08 23:44:06 +02:00
2020-06-03 23:26:16 +02:00
def setrid_resitele_a_body ( slov_resitel_body ) :
setrizeni_resitele_id = [ dvojice [ 0 ] for dvojice in slov_resitel_body ]
setrizeni_resitele = [ Resitel . objects . get ( id = i ) for i in setrizeni_resitele_id ]
setrizene_body = [ dvojice [ 1 ] for dvojice in slov_resitel_body ]
return setrizeni_resitele_id , setrizeni_resitele , setrizene_body
2020-04-08 23:44:06 +02:00
def vysledkovka_rocniku ( rocnik , jen_verejne = True ) :
2020-04-22 23:16:26 +02:00
""" Přebírá ročník (např. context[ " rocnik " ]) a vrací výsledkovou listinu ve
2020-04-08 23:44:06 +02:00
formě vhodné pro šablonu " seminar/vysledkovka_rocniku.html "
"""
## TODO možná chytřeji vybírat aktivní řešitele
# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají
# u alespoň jedné hodnoty něco jiného než NULL
2020-05-21 00:12:27 +02:00
aktivni_resitele = list ( resi_v_rocniku ( rocnik ) )
2020-04-08 23:44:06 +02:00
cisla = cisla_rocniku ( rocnik , jen_verejne )
body_cisla_slov = { }
for cislo in cisla :
# získáme body za číslo
_ , cislobody = secti_body_za_cislo ( cislo , aktivni_resitele )
2020-04-15 22:53:17 +02:00
body_cisla_slov [ cislo . id ] = cislobody
2020-04-08 23:44:06 +02:00
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně
resitel_rocnikbody_sezn = secti_body_za_rocnik ( rocnik , aktivni_resitele )
# setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší
2020-06-03 23:26:16 +02:00
setrizeni_resitele_id , setrizeni_resitele , setrizene_body = setrid_resitele_a_body ( resitel_rocnikbody_sezn )
2020-04-08 23:44:06 +02:00
poradi = sloupec_s_poradim ( setrizene_body )
# získáme body odjakživa
2020-04-22 23:16:26 +02:00
resitel_odjakzivabody_slov = body_resitelu ( aktivni_resitele , rocnik )
2020-04-08 23:44:06 +02:00
# vytvoříme jednotlivé sloupce výsledkovky
radky_vysledkovky = [ ]
i = 0
for ar_id in setrizeni_resitele_id :
# seznam počtu bodů daného řešitele pro jednotlivá čísla
body_cisla_sezn = [ ]
for cislo in cisla :
2020-04-15 22:53:17 +02:00
body_cisla_sezn . append ( body_cisla_slov [ cislo . id ] [ ar_id ] )
2020-04-08 23:44:06 +02:00
# vytáhneme informace pro daného řešitele
radek = RadekVysledkovkyRocniku (
poradi [ i ] , # pořadí
Resitel . objects . get ( id = ar_id ) , # řešitel (z id)
body_cisla_sezn , # seznam bodů za čísla
setrizene_body [ i ] , # body za ročník (spočítané výše s pořadím)
2020-04-15 22:30:58 +02:00
resitel_odjakzivabody_slov [ ar_id ] , # body odjakživa
rocnik ) # ročník semináře pro získání ročníku řešitele
2020-04-08 23:44:06 +02:00
radky_vysledkovky . append ( radek )
i + = 1
return radky_vysledkovky
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 ( )
rocnik_arg = self . kwargs . get ( ' rocnik ' )
queryset = queryset . filter ( rocnik = rocnik_arg )
2015-06-08 22:38:13 +02:00
2019-05-11 01:15:05 +02:00
try :
obj = queryset . get ( )
except queryset . model . DoesNotExist :
raise Http404 ( _ ( " No %(verbose_name)s found matching the query " ) %
2019-05-11 02:00:41 +02:00
{ ' verbose_name ' : queryset . model . _meta . verbose_name } )
2019-05-11 01:15:05 +02:00
return obj
2015-06-08 22:38:13 +02:00
2019-05-11 01:15:05 +02:00
def get_context_data ( self , * * kwargs ) :
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
context [ ' cisla_s_neverejnymi ' ] = cisla_rocniku ( context [ " rocnik " ] , jen_verejne = False )
context [ ' cisla ' ] = cisla_rocniku ( context [ " rocnik " ] )
context [ ' radky_vysledkovky ' ] = vysledkovka_rocniku ( context [ " rocnik " ] )
2020-04-15 22:30:58 +02:00
context [ ' radky_vysledkovky_s_neverejnymi ' ] = vysledkovka_rocniku (
context [ " rocnik " ] , jen_verejne = False )
2020-04-08 23:44:06 +02:00
context [ ' hlavni_problemy_v_rocniku ' ] = hlavni_problemy_rocniku ( context [ " rocnik " ] )
context [ ' hlavni_problemy_v_rocniku_s_neverejnymi ' ] = hlavni_problemy_rocniku ( context [ " rocnik " ] , jen_verejne = False )
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
2015-03-13 20:08:18 +01:00
class ProblemView ( generic . DetailView ) :
2019-05-11 01:15:05 +02:00
model = Problem
2015-09-13 15:31:34 +02:00
2020-04-22 22:21:23 +02:00
# 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ě...
2019-05-11 01:15:05 +02:00
def get_template_names ( self , * * kwargs ) :
2020-04-22 22:21:23 +02:00
# 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 ' ]
2015-09-13 15:31:34 +02:00
2019-05-11 01:15:05 +02:00
def get_context_data ( self , * * kwargs ) :
2020-04-22 22:21:23 +02:00
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 . is_staff :
2019-05-11 01:15:05 +02:00
raise PermissionDenied ( )
2020-04-22 22:21:23 +02:00
if isinstance ( context [ ' object ' ] , Clanek ) :
context [ ' reseni ' ] = Reseni . objects . filter ( problem = context [ ' object ' ] ) . select_related ( ' resitel ' ) . order_by ( ' resitel__prijmeni ' )
2019-05-11 01:15:05 +02:00
return context
2015-09-13 15:31:34 +02:00
2015-12-19 23:11:50 +01:00
2020-04-08 23:44:06 +02:00
class RadekVysledkovkyCisla ( object ) :
2020-03-11 23:00:54 +01:00
""" Obsahuje věci, které se hodí vědět při konstruování výsledkovky.
Umožňuje snazší práci v templatu ( lepší , než seznam ) . """
2015-03-24 01:13:34 +01:00
2020-03-19 01:31:00 +01:00
def __init__ ( self , poradi , resitel , body_problemy_sezn ,
2020-04-15 22:30:58 +02:00
body_cislo , body_rocnik , body_odjakziva , rok ) :
2020-01-09 00:45:20 +01:00
self . resitel = resitel
2020-04-15 22:30:58 +02:00
self . rocnik_resitele = resitel . rocnik ( rok )
2020-03-11 23:00:54 +01:00
self . body_cislo = body_cislo
self . body_rocnik = body_rocnik
2020-03-19 01:31:00 +01:00
self . body_celkem_odjakziva = body_odjakziva
2020-03-11 23:00:54 +01:00
self . poradi = poradi
self . body_problemy_sezn = body_problemy_sezn
2020-03-25 21:01:36 +01:00
self . titul = resitel . get_titul ( body_odjakziva )
2020-03-19 01:31:00 +01:00
def pricti_body ( slovnik , resitel , body ) :
2020-04-22 23:16:26 +02:00
""" Přiřazuje danému řešiteli body do slovníku. """
2020-03-19 01:31:00 +01:00
# testujeme na None (""), pokud je to první řešení
# daného řešitele, předěláme na 0
# (v dalším kroku přičteme reálný počet bodů),
# rozlišujeme tím mezi 0 a neodevzdaným řešením
2020-04-15 22:53:17 +02:00
if slovnik [ resitel . id ] == " " :
slovnik [ resitel . id ] = 0
2020-03-19 01:31:00 +01:00
2020-04-15 22:53:17 +02:00
slovnik [ resitel . id ] + = body
2019-10-23 23:23:54 +02:00
2020-05-21 00:12:27 +02:00
def secti_body_za_rocnik ( za , aktivni_resitele ) :
""" Spočítá body za ročník (celý nebo do daného čísla),
setřídí je sestupně a vrátí jako seznam .
Parametry :
za ( typu Rocnik nebo Cislo ) spočítá za ročník , nebo za ročník až do
daného čísla
"""
2020-04-22 23:16:26 +02:00
# spočítáme všem řešitelům jejich body za ročník (False => ne odjakživa)
2020-05-21 00:12:27 +02:00
resitel_rocnikbody_slov = body_resitelu ( aktivni_resitele , za , False )
2020-03-25 23:57:11 +01:00
# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně
resitel_rocnikbody_sezn = sorted ( resitel_rocnikbody_slov . items ( ) ,
key = lambda x : x [ 1 ] , reverse = True )
return resitel_rocnikbody_sezn
2020-04-08 23:44:06 +02:00
def secti_body_za_cislo ( cislo , aktivni_resitele , hlavni_problemy = None ) :
2020-04-22 23:16:26 +02:00
""" Spočítá u řešitelů body za číslo a za jednotlivé hlavní problémy (témata). """
2020-03-25 23:57:11 +01:00
# TODO setřídit hlavní problémy čísla podle id, ať jsou ve stejném pořadí pokaždé
# pro každý hlavní problém zavedeme slovník s body za daný hlavní problém
# pro jednotlivé řešitele (slovník slovníků hlavních problémů)
2020-04-08 23:44:06 +02:00
if hlavni_problemy is None :
hlavni_problemy = hlavni_problemy_cisla ( cislo )
2020-03-25 23:57:11 +01:00
hlavni_problemy_slovnik = { }
for hp in hlavni_problemy :
2020-04-15 22:53:17 +02:00
hlavni_problemy_slovnik [ hp . id ] = { }
2020-03-25 23:57:11 +01:00
# zakládání prázdných záznamů pro řešitele
cislobody = { }
for ar in aktivni_resitele :
# řešitele převedeme na řetězec pomocí unikátního id
2020-04-15 22:53:17 +02:00
cislobody [ ar . id ] = " "
2020-03-25 23:57:11 +01:00
for hp in hlavni_problemy :
2020-04-15 22:53:17 +02:00
slovnik = hlavni_problemy_slovnik [ hp . id ]
slovnik [ ar . id ] = " "
2020-03-25 23:57:11 +01:00
# vezmeme všechna řešení s body do daného čísla
reseni_do_cisla = Reseni . objects . prefetch_related ( ' problem ' , ' resitele ' ,
' hodnoceni_set ' ) . filter ( hodnoceni__cislo_body = cislo )
# projdeme všechna řešení do čísla a přičteme body každému řešiteli do celkových
# bodů i do bodů za problém
for reseni in reseni_do_cisla :
# řešení může řešit více problémů
for prob in list ( reseni . problem . all ( ) ) :
nadproblem = hlavni_problem ( prob )
2020-04-15 22:53:17 +02:00
nadproblem_slovnik = hlavni_problemy_slovnik [ nadproblem . id ]
2020-03-25 23:57:11 +01:00
# a mít více hodnocení
for hodn in list ( reseni . hodnoceni_set . all ( ) ) :
body = hodn . body
# a mít více řešitelů
for resitel in list ( reseni . resitele . all ( ) ) :
2020-05-21 00:12:27 +02:00
if resitel not in aktivni_resitele :
print ( " Skipping {} " . format ( resitel . id ) )
continue
2020-03-25 23:57:11 +01:00
pricti_body ( cislobody , resitel , body )
pricti_body ( nadproblem_slovnik , resitel , body )
return hlavni_problemy_slovnik , cislobody
2020-04-08 23:44:06 +02:00
def vysledkovka_cisla ( cislo , context = None ) :
2020-03-25 23:57:11 +01:00
if context is None :
context = { }
hlavni_problemy = hlavni_problemy_cisla ( cislo )
## TODO možná chytřeji vybírat aktivní řešitele
# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají
# u alespoň jedné hodnoty něco jiného než NULL
2020-05-21 00:12:27 +02:00
aktivni_resitele = list ( aktivniResitele ( cislo . rocnik . rocnik , cislo . poradi ) )
2020-03-25 23:57:11 +01:00
# získáme body za číslo
hlavni_problemy_slovnik , cislobody = secti_body_za_cislo ( cislo , aktivni_resitele , hlavni_problemy )
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně
2020-05-21 00:12:27 +02:00
resitel_rocnikbody_sezn = secti_body_za_rocnik ( cislo , aktivni_resitele )
2020-03-25 23:57:11 +01:00
# získáme body odjakživa
2020-04-22 23:16:26 +02:00
resitel_odjakzivabody_slov = body_resitelu ( aktivni_resitele , cislo )
2020-03-25 23:57:11 +01:00
# řešitelé setřídění podle bodů za číslo sestupně
setrizeni_resitele_id = [ dvojice [ 0 ] for dvojice in resitel_rocnikbody_sezn ]
setrizeni_resitele = [ Resitel . objects . get ( id = i ) for i in setrizeni_resitele_id ]
# spočítáme pořadí řešitelů
setrizeni_resitele_body = [ dvojice [ 1 ] for dvojice in resitel_rocnikbody_sezn ]
poradi = sloupec_s_poradim ( setrizeni_resitele_body )
# vytvoříme jednotlivé sloupce výsledkovky
radky_vysledkovky = [ ]
i = 0
for ar_id in setrizeni_resitele_id :
# získáme seznam bodů za problémy pro daného řešitele
problemy = [ ]
for hp in hlavni_problemy :
2020-04-15 22:53:17 +02:00
problemy . append ( hlavni_problemy_slovnik [ hp . id ] [ ar_id ] )
2020-03-25 23:57:11 +01:00
# vytáhneme informace pro daného řešitele
2020-04-08 23:44:06 +02:00
radek = RadekVysledkovkyCisla (
2020-03-25 23:57:11 +01:00
poradi [ i ] , # pořadí
Resitel . objects . get ( id = ar_id ) , # řešitel (z id)
problemy , # seznam bodů za hlavní problémy čísla
cislobody [ ar_id ] , # body za číslo
setrizeni_resitele_body [ i ] , # body za ročník (spočítané výše s pořadím)
2020-04-15 22:30:58 +02:00
resitel_odjakzivabody_slov [ ar_id ] , # body odjakživa
cislo . rocnik ) # ročník semináře pro zjištění ročníku řešitele
2020-03-25 23:57:11 +01:00
radky_vysledkovky . append ( radek )
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
return context
2019-07-26 00:01:23 +02:00
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 ' )
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 ' ]
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
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
2015-11-15 15:14:21 +01:00
### Generovani obalek
2020-05-21 00:12:27 +02:00
def resi_v_rocniku ( rocnik , cislo = None ) :
""" Vrátí seznam řešitelů, co vyřešili nějaký problém v daném ročníku, do daného čísla.
Parametry :
rocnik ( typu Rocnik ) ročník , ze kterého chci řešitele , co něco odevzdali
cislo ( typu Cislo ) číslo , do kterého včetně se počítá , že v daném
ročníku řešitel něco poslal .
Pokud není zadané , počítají se všechna řešení z daného ročníku .
Výstup :
QuerySet objektů typu Resitel """
if cislo is None :
# filtrujeme pouze podle ročníku
letosni_reseni = Reseni . objects . filter ( hodnoceni__cislo_body__rocnik = rocnik )
else : # filtrujeme podle ročníku i čísla
letosni_reseni = Reseni . objects . filter ( hodnoceni__cislo_body__rocnik = rocnik ,
hodnoceni__cislo_body__poradi__lte = cislo . poradi )
# vygenerujeme queryset řešitelů, co letos něco poslali
letosni_resitele = Resitel . objects . none ( )
for reseni in letosni_reseni :
letosni_resitele = letosni_resitele | reseni . resitele . filter ( rok_maturity__gte = rocnik . druhy_rok ( ) )
return letosni_resitele . distinct ( )
2020-06-03 23:26:16 +02:00
def aktivniResitele ( rocnik , cislo , pouze_realni = False ) :
2020-05-21 00:12:27 +02:00
""" Vrací QuerySet aktivních řešitelů, což jsou ti, co ještě neodmaturovali
a letos něco poslali ( anebo loni něco poslali , pokud jde o první tři čísla ) .
Parametry :
rocnik ( typu int ) číslo ročníku , o který se jedná
cislo ( typu int ) pořadí čísla , o které se jedná
2020-06-03 23:26:16 +02:00
pouze_realni jen řešitelé , kteří tento rok něco poslali
2020-04-22 23:44:15 +02:00
2020-05-21 00:12:27 +02:00
"""
2019-05-11 01:15:05 +02:00
letos = Rocnik . objects . get ( rocnik = rocnik )
2020-05-21 00:12:27 +02:00
#TODO: co se stane, když zadané kombinace neexistují? ošetřit
aktualni_cislo = Cislo . objects . get ( rocnik = rocnik , poradi = cislo )
loni = Rocnik . objects . get ( rocnik = rocnik - 1 )
# detekujeme, zda jde o první tři čísla či nikoli
zacatek_rocniku = True
try :
if int ( aktualni_cislo . poradi ) > 3 :
zacatek_rocniku = False
except ValueError :
# pravděpodobně se jedná o číslo 7-8
zacatek_rocniku = False
2020-06-03 23:26:16 +02:00
# nehledě na číslo chceme jen řešitele, kteří letos něco odevzdali
if pouze_realni :
zacatek_rocniku = False
2020-05-21 00:12:27 +02:00
if not zacatek_rocniku :
return resi_v_rocniku ( letos )
2019-05-11 01:15:05 +02:00
else :
2020-05-21 00:12:27 +02:00
# spojíme querysety s řešiteli loni a letos do daného čísla
return ( resi_v_rocniku ( loni ) | resi_v_rocniku ( letos , aktualni_cislo ) ) . distinct ( )
2015-12-06 23:32:25 +01:00
2020-05-21 00:12:27 +02:00
def cisloObalkyView ( request , rocnik , cislo ) :
return obalkyView ( request , aktivniResitele ( rocnik , 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
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 = [ ]
2020-04-22 23:16:26 +02:00
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
# 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
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
2019-04-23 23:26:37 +02:00
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
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-03-25 23:57:11 +01:00
queryset = Clanek . 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
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
template_name = ' seminar/resitel.html '
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-02-05 23:30:41 +01:00
class AddSolutionView ( LoginRequiredMixin , FormView ) :
template_name = ' seminar/org/vloz_reseni.html '
form_class = f . VlozReseniForm
success_url = ' / '
2020-05-20 21:44:12 +02:00
class NahrajReseniView ( LoginRequiredMixin , CreateView ) :
2020-02-28 21:34:53 +01:00
model = s . Reseni
template_name = ' seminar/nahraj_reseni.html '
form_class = f . NahrajReseniForm
2020-02-29 18:05:49 +01:00
success_url = ' / '
2020-02-28 21:34:53 +01:00
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 ' ]
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 ) )
2020-02-28 21:42:06 +01: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 ( )
2020-02-28 21:34:53 +01:00
return HttpResponseRedirect ( self . get_success_url ( ) )
2019-09-02 00:01:39 +02:00
def resetPasswordView ( request ) :
pass
2019-09-01 22:59:05 +02:00
def loginView ( request ) :
if request . method == ' POST ' :
form = LoginForm ( request . POST )
if form . is_valid ( ) :
2020-03-25 23:57:11 +01:00
user = authenticate ( request ,
2019-09-01 22:59:05 +02:00
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 :
2020-03-25 23:57:11 +01:00
return render ( request ,
' seminar/login.html ' ,
2019-09-01 22:59:05 +02:00
{ ' form ' : form , ' login_error ' : ' Neplatné jméno nebo heslo ' } )
else :
form = LoginForm ( )
return render ( request , ' seminar/login.html ' , { ' form ' : form } )
2018-12-05 23:37:05 +01:00
2019-09-01 22:59:05 +02:00
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 } )
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 ) :
msg = " {} , form_hash: {} " . format ( msg , hash ( form_data ) )
logger . warn ( msg )
2020-03-25 23:57:11 +01: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
def resitelEditView ( request ) :
2019-12-04 22:33:20 +01:00
err_logger = logging . getLogger ( ' seminar.prihlaska.problem ' )
2019-11-27 23:45:45 +01:00
## 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
2020-03-25 23:57:11 +01:00
## Vytvoření slovníku, kterým předvyplním formulář
2019-12-04 22:33:20 +01:00
prefill_1 = model_to_dict ( user_edit )
2019-11-27 23:45:45 +01:00
prefill_2 = model_to_dict ( resitel_edit )
2019-12-04 22:33:20 +01:00
prefill_3 = model_to_dict ( osoba_edit )
2019-11-27 23:45:45 +01:00
prefill_1 . update ( prefill_2 )
prefill_1 . update ( prefill_3 )
2020-02-11 21:37:35 +01:00
form = ProfileEditForm ( initial = prefill_1 )
2019-11-27 23:45:45 +01:00
## Změna údajů a jejich uložení
if request . method == ' POST ' :
2020-02-11 21:37:35 +01:00
form = ProfileEditForm ( request . POST )
2019-11-27 23:45:45 +01:00
if form . is_valid ( ) :
2019-12-04 22:33:20 +01:00
## 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 ( )
2019-11-27 23:45:45 +01:00
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 } )
2019-11-20 23:56:51 +01:00
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
2019-11-20 23:56:51 +01:00
form_hash = hash ( fcd )
form_logger . info ( fcd , form_hash = form_hash )
2020-03-25 23:57:11 +01: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 ' ] ,
password = fcd [ ' password ' ] ,
email = fcd [ ' email ' ] )
2019-09-01 16:35:20 +02:00
u . save ( )
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
)
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 ' ] )
err_logger . warn ( msg , form_hash = form_hash )
2019-09-01 16:35:20 +02:00
o . save ( )
o . user = u
o . save ( )
r = Resitel (
2019-11-08 00:11:33 +01:00
rok_maturity = fcd [ ' rok_maturity ' ] ,
zasilat = fcd [ ' zasilat ' ]
2019-09-01 16:35:20 +02:00
)
2020-03-25 23:57:11 +01:00
2019-09-01 16:35:20 +02:00
r . save ( )
r . osoba = o
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 ' ] )
err_logger . warn ( msg , form_hash = form_hash )
2019-09-01 16:35:20 +02:00
r . save ( )
2019-08-31 19:36:12 +02:00
2019-05-11 01:15:05 +02:00
return HttpResponseRedirect ( ' /thanks/ ' )
# 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
return render ( request , ' seminar/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
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
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
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 ' )
class PasswordResetView ( auth_views . PasswordResetView ) :
2020-04-22 23:44:15 +02:00
""" Chci resetovat heslo. """
2019-12-19 01:30:48 +01:00
#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 '
class PasswordResetDoneView ( auth_views . PasswordResetDoneView ) :
2020-04-22 23:44:15 +02:00
""" Poslali jsme e-mail (pokud bylo kam)). """
2019-12-19 01:30:48 +01:00
#template_name = 'seminar/password_reset_done.html'
pass
class PasswordResetConfirmView ( auth_views . PasswordResetConfirmView ) :
2020-04-22 23:44:15 +02:00
""" Vymysli si heslo. """
2019-12-19 01:30:48 +01:00
#template_name = 'seminar/password_confirm_done.html'
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. """
2019-12-19 01:30:48 +01:00
#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 ' )