Podezřelé semináře (#1465) #65
|
@ -5,16 +5,16 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
||||||
views.ExportRocnikView.as_view(),
|
views.ExportRocnikView.as_view(),
|
||||||
name='seminar_export_rocnik'
|
name='aesop_export_rocnik'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
||||||
views.ExportSousView.as_view(),
|
views.ExportSousView.as_view(),
|
||||||
name='seminar_export_sous'
|
name='aesop_export_sous'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'aesop-export/index.csv',
|
'aesop-export/index.csv',
|
||||||
views.ExportIndexView.as_view(),
|
views.ExportIndexView.as_view(),
|
||||||
name='seminar_export_index'
|
name='aesop_export_index'
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,7 +6,8 @@ from django.views import generic
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from .utils import default_ovvpfile
|
from .utils import default_ovvpfile
|
||||||
from seminar.models import Rocnik, Soustredeni
|
from soustredeni.models import Soustredeni
|
||||||
|
from tvorba.models import Rocnik
|
||||||
from vysledkovky import utils
|
from vysledkovky import utils
|
||||||
from tvorba.utils import aktivniResitele
|
from tvorba.utils import aktivniResitele
|
||||||
|
|
||||||
|
@ -14,10 +15,10 @@ class ExportIndexView(generic.View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
ls = []
|
ls = []
|
||||||
for r in Rocnik.objects.filter(exportovat = True):
|
for r in Rocnik.objects.filter(exportovat = True):
|
||||||
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
url = reverse('aesop_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
||||||
ls.append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
for s in Soustredeni.objects.filter(exportovat = True):
|
for s in Soustredeni.objects.filter(exportovat = True):
|
||||||
url = reverse('seminar_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
url = reverse('aesop_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
||||||
ls.append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
|
|
||||||
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.test import TestCase, tag
|
from django.test import TestCase, tag
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
import seminar.models as m
|
from personalni.models import Skola
|
||||||
from personalni.utils import sync_skoly
|
from personalni.utils import sync_skoly
|
||||||
|
|
||||||
@tag('stejny-model-na-produkci')
|
@tag('stejny-model-na-produkci')
|
||||||
|
@ -48,7 +48,7 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
||||||
for pfx, id in self.spravna_data:
|
for pfx, id in self.spravna_data:
|
||||||
with self.subTest(prefix=pfx, spravne_id=id):
|
with self.subTest(prefix=pfx, spravne_id=id):
|
||||||
spravna_skola = m.Skola.objects.get(id=id)
|
spravna_skola = Skola.objects.get(id=id)
|
||||||
# Zeptáme se view, co si myslí
|
# Zeptáme se view, co si myslí
|
||||||
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
||||||
ids = [int(x['id']) for x in resp['results']]
|
ids = [int(x['id']) for x in resp['results']]
|
||||||
|
|
|
@ -17,5 +17,5 @@ urlpatterns = [
|
||||||
# Ceka na autocomplete v3
|
# Ceka na autocomplete v3
|
||||||
# path('autocomplete/organizatori/',
|
# path('autocomplete/organizatori/',
|
||||||
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
||||||
# name='seminar_autocomplete_organizator')
|
# name='autocomplete_organizator')
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,9 @@ from dal import autocomplete
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
import seminar.models as m
|
from personalni.models import Skola, Resitel
|
||||||
|
from tvorba.models import Problem
|
||||||
|
from various.models import Nastaveni
|
||||||
from .helpers import LoginRequiredAjaxMixin
|
from .helpers import LoginRequiredAjaxMixin
|
||||||
|
|
||||||
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
||||||
|
@ -13,7 +15,7 @@ class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """
|
""" View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
# Don't forget to filter out results depending on the visitor !
|
# Don't forget to filter out results depending on the visitor !
|
||||||
qs = m.Skola.objects.all()
|
qs = Skola.objects.all()
|
||||||
if self.q:
|
if self.q:
|
||||||
words = self.q.split(' ') #TODO re split podle bileho znaku
|
words = self.q.split(' ') #TODO re split podle bileho znaku
|
||||||
partq = Q()
|
partq = Q()
|
||||||
|
@ -31,7 +33,7 @@ class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
class ResitelAutocomplete(LoginRequiredAjaxMixin,autocomplete.Select2QuerySetView):
|
class ResitelAutocomplete(LoginRequiredAjaxMixin,autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání řešitelů především v odevzdávátku. """
|
""" View k :mod:`dal.autocomplete` pro vyhledávání řešitelů především v odevzdávátku. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = m.Resitel.objects.all()
|
qs = Resitel.objects.all()
|
||||||
if self.q:
|
if self.q:
|
||||||
parts = self.q.split()
|
parts = self.q.split()
|
||||||
query = Q()
|
query = Q()
|
||||||
|
@ -51,8 +53,8 @@ class PublicResitelAutocomplete(LoginRequiredAjaxMixin, autocomplete.Select2Quer
|
||||||
především v odevzdávátku.
|
především v odevzdávátku.
|
||||||
"""
|
"""
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
letos = m.Nastaveni.get_solo().aktualni_rocnik
|
letos = Nastaveni.get_solo().aktualni_rocnik
|
||||||
qs = m.Resitel.objects.filter(
|
qs = Resitel.objects.filter(
|
||||||
rok_maturity__gte=letos.druhy_rok()
|
rok_maturity__gte=letos.druhy_rok()
|
||||||
).filter(
|
).filter(
|
||||||
prezdivka_resitele__isnull=False
|
prezdivka_resitele__isnull=False
|
||||||
|
@ -70,7 +72,7 @@ class PublicResitelAutocomplete(LoginRequiredAjaxMixin, autocomplete.Select2Quer
|
||||||
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY)
|
qs = Problem.objects.filter(stav=Problem.STAV_ZADANY)
|
||||||
if self.q:
|
if self.q:
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(nazev__icontains=self.q))
|
Q(nazev__icontains=self.q))
|
||||||
|
@ -87,12 +89,12 @@ class ProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
# FIXME i starší úlohy
|
# FIXME i starší úlohy
|
||||||
nastaveni = get_object_or_404(m.Nastaveni)
|
nastaveni = get_object_or_404(Nastaveni)
|
||||||
rocnik = nastaveni.aktualni_rocnik
|
rocnik = nastaveni.aktualni_rocnik
|
||||||
temaQ = Q(Tema___rocnik = rocnik)
|
temaQ = Q(Tema___rocnik = rocnik)
|
||||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik=rocnik)
|
ulohaQ = Q(Uloha___cislo_zadani__rocnik=rocnik)
|
||||||
clanekQ = Q(Clanek___cislo__rocnik=rocnik)
|
clanekQ = Q(Clanek___cislo__rocnik=rocnik)
|
||||||
qs = m.Problem.objects.filter(temaQ | ulohaQ | clanekQ).order_by("-stav", "nazev")
|
qs = Problem.objects.filter(temaQ | ulohaQ | clanekQ).order_by("-stav", "nazev")
|
||||||
if self.q:
|
if self.q:
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(nazev__icontains=self.q))
|
Q(nazev__icontains=self.q))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import seminar.models as m
|
import personalni.models as m
|
||||||
from django.core import serializers as ser
|
from django.core import serializers as ser
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
def exportSkolView(request):
|
def exportSkolView(request):
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
"sort_order": 3,
|
"sort_order": 3,
|
||||||
"title": "Aktuální<br/> ročník",
|
"title": "Aktuální<br/> ročník",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_zadani",
|
"url": "tvorba_aktualni_zadani",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
"sort_order": 5,
|
"sort_order": 5,
|
||||||
"title": "Archiv",
|
"title": "Archiv",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_archiv_rocniky",
|
"url": "tvorba_archiv_rocniky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -289,7 +289,7 @@
|
||||||
"sort_order": 43,
|
"sort_order": 43,
|
||||||
"title": "Výsledková listina",
|
"title": "Výsledková listina",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_vysledky",
|
"url": "tvorba_aktualni_vysledky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -361,7 +361,7 @@
|
||||||
"sort_order": 20,
|
"sort_order": 20,
|
||||||
"title": "Proběhlo",
|
"title": "Proběhlo",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_seznam_soustredeni",
|
"url": "soustredeni_seznam",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -409,7 +409,7 @@
|
||||||
"sort_order": 23,
|
"sort_order": 23,
|
||||||
"title": "Osobní údaje",
|
"title": "Osobní údaje",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_resitel_edit",
|
"url": "personalni_resitel_edit",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -439,7 +439,7 @@
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Nahrát řešení",
|
"title": "Nahrát řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_nahraj_reseni",
|
"url": "odevzdavatko_nahraj_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -463,7 +463,7 @@
|
||||||
"sort_order": 35,
|
"sort_order": 35,
|
||||||
"title": "Témata",
|
"title": "Témata",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_archiv_temata",
|
"url": "tvorba_archiv_temata",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -589,7 +589,7 @@
|
||||||
"sort_order": 15,
|
"sort_order": 15,
|
||||||
"title": "Aktuální číslo",
|
"title": "Aktuální číslo",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_zadani",
|
"url": "tvorba_aktualni_zadani",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -613,7 +613,7 @@
|
||||||
"sort_order": 24,
|
"sort_order": 24,
|
||||||
"title": "Čísla",
|
"title": "Čísla",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_archiv_rocniky",
|
"url": "tvorba_archiv_rocniky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -721,7 +721,7 @@
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Vložit řešení",
|
"title": "Vložit řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_vloz_reseni",
|
"url": "odevzdavatko_vloz_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -804,7 +804,7 @@
|
||||||
"sort_order": 37,
|
"sort_order": 37,
|
||||||
"title": "Moje řešení",
|
"title": "Moje řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_resitel_odevzdana_reseni",
|
"url": "odevzdavatko_resitel_odevzdana_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -828,7 +828,7 @@
|
||||||
"sort_order": 33,
|
"sort_order": 33,
|
||||||
"title": "Aktuální ročník",
|
"title": "Aktuální ročník",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_rocnik",
|
"url": "tvorba_aktualni_rocnik",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -900,7 +900,7 @@
|
||||||
"sort_order": 46,
|
"sort_order": 46,
|
||||||
"title": "Ročník {{rocnik.rocnik}}",
|
"title": "Ročník {{rocnik.rocnik}}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_rocnik rocnik.rocnik",
|
"url": "tvorba_rocnik rocnik.rocnik",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -924,7 +924,7 @@
|
||||||
"sort_order": 47,
|
"sort_order": 47,
|
||||||
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_cislo cislo.rocnik.rocnik cislo.poradi",
|
"url": "tvorba_cislo cislo.rocnik.rocnik cislo.poradi",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -1061,7 +1061,7 @@
|
||||||
"sort_order": 52,
|
"sort_order": 52,
|
||||||
"title": "Nahrát řešení k nadproblému {{nadproblem_id}}",
|
"title": "Nahrát řešení k nadproblému {{nadproblem_id}}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_nahraj_reseni nadproblem_id",
|
"url": "odevzdavatko_nahraj_reseni nadproblem_id",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -1109,10 +1109,10 @@
|
||||||
"sort_order": 54,
|
"sort_order": 54,
|
||||||
"title": "Export do abstraktů sousu {{ soustredeni.id }}",
|
"title": "Export do abstraktů sousu {{ soustredeni.id }}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_soustredeni_abstrakty soustredeni.id",
|
"url": "soustredeni_abstrakty soustredeni.id",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
"pk": 54
|
"pk": 54
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -10,11 +10,9 @@ věci jako chybové hlášky a vzhled M&M stránek (menu, patička, atd.). Aktu
|
||||||
i veškeré csv.
|
i veškeré csv.
|
||||||
|
|
||||||
Další jsou pak jednotlivé aplikace (pokud něco hledáte, tak zřejmě chcete najít
|
Další jsou pak jednotlivé aplikace (pokud něco hledáte, tak zřejmě chcete najít
|
||||||
tu aplikaci, která tomu odpovídá, respektive se k ní dostat přes url), za
|
tu aplikaci, která tomu odpovídá, respektive se k ní dostat přes url).
|
||||||
zmínku stojí seminar, kde jsou takové ty věci, co zbyly. Plus jsou tam aktuálně
|
|
||||||
téměř všechny modely, protože je těžké je přesunout jinam.
|
|
||||||
|
|
||||||
**TLDR: Nevšímejte si složky data/ a souborů přímo v kořenové složce.**
|
**TLDR: Nevšímejte si složek data/ seminar/ a souborů přímo v kořenové složce.**
|
||||||
Kromě věcí potřebných ke gitu, :doc:`ke spuštění <vyvoj>` a fukci djanga,
|
Kromě věcí potřebných ke gitu, :doc:`ke spuštění <vyvoj>` a fukci djanga,
|
||||||
dalších drobností, lokální databáze a již zmíněných aplikací jsou tu ``data``,
|
dalších drobností, lokální databáze a již zmíněných aplikací jsou tu ``data``,
|
||||||
kde je takový ten obsah webu, co by se měl dát snadno měnit (tudíž musí být v
|
kde je takový ten obsah webu, co by se měl dát snadno měnit (tudíž musí být v
|
||||||
|
@ -22,6 +20,9 @@ databázi), tj. statické stránky, menu a obrázky v pozadí menu. Ten je třeb
|
||||||
měnit hlavně na produkci a sekundárně tady (může to dělat i newebař a nechcete
|
měnit hlavně na produkci a sekundárně tady (může to dělat i newebař a nechcete
|
||||||
přepsat jeho práci). Vše, co nejsou aplikace je popsáno :doc:`tady <dalsi_soubory>`.
|
přepsat jeho práci). Vše, co nejsou aplikace je popsáno :doc:`tady <dalsi_soubory>`.
|
||||||
|
|
||||||
|
Ještě je tu aplikace ``seminar/``, kde bylo původně skoro všechno, a tak nám
|
||||||
|
tam zbývá spoustu historických migrací (čehož se jen tak nezbavíme).
|
||||||
|
|
||||||
Základy djanga
|
Základy djanga
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ Aktuálně: Jakýsi coding style zhruba existuje, není popsaný, šíří se li
|
||||||
- Nesmí být striktně vynucovaný
|
- Nesmí být striktně vynucovaný
|
||||||
- Musel by být hodně nastavitelný
|
- Musel by být hodně nastavitelný
|
||||||
- Nechceme mít kód plný `#NOQA: WTF42`
|
- Nechceme mít kód plný `#NOQA: WTF42`
|
||||||
- Nejspíš vždycky bude mít false positives (`tvorba.utils.roman_numerals`) i false negatives (`seminar.models.tvorba.Cislo.posli_cislo_mailem`)
|
- Nejspíš vždycky bude mít false positives (`tvorba.utils.roman_numerals`) i false negatives (`tvorba.models.Cislo.posli_cislo_mailem`)
|
||||||
- Možná dobrý sluha, ale určitě špatný pán (also: špatná zkušenost ☺)
|
- Možná dobrý sluha, ale určitě špatný pán (also: špatná zkušenost ☺)
|
||||||
- __Důsledek:__ Hrozí, že těch falešných varování bude moc, čímž to ztratí smysl úplně
|
- __Důsledek:__ Hrozí, že těch falešných varování bude moc, čímž to ztratí smysl úplně
|
||||||
- Potenciálně by šlo aplikovat jen lokálně na změny?
|
- Potenciálně by šlo aplikovat jen lokálně na změny?
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.template import RequestContext
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from galerie.models import Obrazek, Galerie
|
from galerie.models import Obrazek, Galerie
|
||||||
from seminar.models import Soustredeni
|
from soustredeni.models import Soustredeni
|
||||||
from galerie.forms import KomentarForm, NewGalerieForm
|
from galerie.forms import KomentarForm, NewGalerieForm
|
||||||
|
|
||||||
def zobrazit(galerie, request):
|
def zobrazit(galerie, request):
|
||||||
|
|
|
@ -4,7 +4,7 @@ set -exuo pipefail
|
||||||
. make/lib.sh
|
. make/lib.sh
|
||||||
|
|
||||||
scp vue_frontend/webpack-stats.json "$GIMLI_LOGIN:$TESTWEB/vue_frontend/"
|
scp vue_frontend/webpack-stats.json "$GIMLI_LOGIN:$TESTWEB/vue_frontend/"
|
||||||
rsync -ave ssh seminar/static/seminar/vue "$GIMLI_LOGIN:$TESTWEB/seminar/static/seminar/"
|
rsync -ave ssh treenode/static/treenode/vue "$GIMLI_LOGIN:$TESTWEB/treenode/static/treenode/"
|
||||||
ssh "$GIMLI_LOGIN" "
|
ssh "$GIMLI_LOGIN" "
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
cd $TESTWEB
|
cd $TESTWEB
|
||||||
|
|
|
@ -43,7 +43,7 @@ def get_app_list(self, request, app_label=None):
|
||||||
|
|
||||||
app_dict = self._build_app_dict(request, label=app_label)
|
app_dict = self._build_app_dict(request, label=app_label)
|
||||||
aplikace_nahore = [
|
aplikace_nahore = [
|
||||||
'seminar',
|
'tvorba',
|
||||||
'personalni',
|
'personalni',
|
||||||
'novinky',
|
'novinky',
|
||||||
'korektury',
|
'korektury',
|
||||||
|
@ -57,7 +57,7 @@ def get_app_list(self, request, app_label=None):
|
||||||
|
|
||||||
# Sort the models alphabetically within each app.
|
# Sort the models alphabetically within each app.
|
||||||
for app in app_list:
|
for app in app_list:
|
||||||
app['models'].sort(key=lambda x: locale.strxfrm('žž' + x['name'].lower()) if (x['name'].endswith("(Node)")) else locale.strxfrm(x['name'].lower()))
|
app['models'].sort(key=lambda x: locale.strxfrm(x['name'].lower()))
|
||||||
|
|
||||||
return app_list
|
return app_list
|
||||||
|
|
||||||
|
|
|
@ -279,11 +279,11 @@ LOGGING = {
|
||||||
'filters': ['Http404AsInfo'],
|
'filters': ['Http404AsInfo'],
|
||||||
},
|
},
|
||||||
|
|
||||||
'seminar.prihlaska.form':{
|
'personalni.prihlaska.form':{
|
||||||
'handlers': ['console','registration_logfile'],
|
'handlers': ['console','registration_logfile'],
|
||||||
'level': 'INFO'
|
'level': 'INFO'
|
||||||
},
|
},
|
||||||
'seminar.prihlaska.problem':{
|
'personalni.prihlaska.problem':{
|
||||||
'handlers': ['console','mail_registration','registration_error_log'],
|
'handlers': ['console','mail_registration','registration_error_log'],
|
||||||
'level': 'INFO'
|
'level': 'INFO'
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
{% if not novinka.zverejneno and user.je_org %}
|
{% if not novinka.zverejneno and user.je_org %}
|
||||||
<div class="mam-org-only">
|
<div class="mam-org-only">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/admin/seminar/novinky/{{novinka.pk}}">Upravit novinku</a>
|
<li><a href="{% url 'admin:novinky_novinky_change' novinka.pk %}">Upravit novinku</a>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if novinka.zverejneno or user.je_org %}
|
{% if novinka.zverejneno or user.je_org %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django_reverse_admin import ReverseModelAdmin
|
from django_reverse_admin import ReverseModelAdmin
|
||||||
import seminar.models as m
|
import odevzdavatko.models as m
|
||||||
|
|
||||||
|
|
||||||
class PrilohaReseniInline(admin.TabularInline):
|
class PrilohaReseniInline(admin.TabularInline):
|
||||||
|
|
|
@ -4,8 +4,11 @@ from django.forms import formset_factory
|
||||||
from django.forms.models import inlineformset_factory
|
from django.forms.models import inlineformset_factory
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from seminar.models import Resitel
|
from personalni.models import Resitel
|
||||||
import seminar.models as m
|
from tvorba.models import Problem, Deadline
|
||||||
|
from various.models import Nastaveni
|
||||||
|
|
||||||
|
from odevzdavatko.models import Reseni, PrilohaReseni, Hodnoceni
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -22,7 +25,7 @@ class DateInput(forms.DateInput):
|
||||||
|
|
||||||
class PosliReseniForm(forms.Form):
|
class PosliReseniForm(forms.Form):
|
||||||
problem = forms.ModelMultipleChoiceField(
|
problem = forms.ModelMultipleChoiceField(
|
||||||
queryset=m.Problem.objects.all(),
|
queryset=Problem.objects.all(),
|
||||||
label="Problémy",
|
label="Problémy",
|
||||||
widget=autocomplete.ModelSelect2Multiple(
|
widget=autocomplete.ModelSelect2Multiple(
|
||||||
url='autocomplete_problem',
|
url='autocomplete_problem',
|
||||||
|
@ -58,7 +61,7 @@ class PosliReseniForm(forms.Form):
|
||||||
|
|
||||||
#cas_doruceni = models.DateTimeField('čas_doručení', default=timezone.now, blank=True)
|
#cas_doruceni = models.DateTimeField('čas_doručení', default=timezone.now, blank=True)
|
||||||
|
|
||||||
forma = forms.ChoiceField(label="Forma řešení",choices = m.Reseni.FORMA_CHOICES)
|
forma = forms.ChoiceField(label="Forma řešení",choices = Reseni.FORMA_CHOICES)
|
||||||
#forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False,
|
#forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False,
|
||||||
# default=FORMA_EMAIL)
|
# default=FORMA_EMAIL)
|
||||||
|
|
||||||
|
@ -69,7 +72,7 @@ class PosliReseniForm(forms.Form):
|
||||||
|
|
||||||
class NahrajReseniForm(forms.ModelForm):
|
class NahrajReseniForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
fields = ('problem', 'resitele')
|
fields = ('problem', 'resitele')
|
||||||
help_texts = {'problem':''} # Nezobrazovat help text ve formuláři
|
help_texts = {'problem':''} # Nezobrazovat help text ve formuláři
|
||||||
|
|
||||||
|
@ -109,11 +112,11 @@ class NahrajReseniForm(forms.ModelForm):
|
||||||
def clean_problem(self):
|
def clean_problem(self):
|
||||||
problem = self.cleaned_data.get('problem')
|
problem = self.cleaned_data.get('problem')
|
||||||
for p in problem:
|
for p in problem:
|
||||||
if p.stav != m.Problem.STAV_ZADANY:
|
if p.stav != Problem.STAV_ZADANY:
|
||||||
raise forms.ValidationError("Problém " + str(p) + " již nelze řešit!")
|
raise forms.ValidationError("Problém " + str(p) + " již nelze řešit!")
|
||||||
return problem
|
return problem
|
||||||
|
|
||||||
ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni,
|
ReseniSPrilohamiFormSet = inlineformset_factory(Reseni, PrilohaReseni,
|
||||||
form = NahrajReseniForm,
|
form = NahrajReseniForm,
|
||||||
fields = ('soubor','res_poznamka'),
|
fields = ('soubor','res_poznamka'),
|
||||||
widgets = {'res_poznamka':forms.TextInput()},
|
widgets = {'res_poznamka':forms.TextInput()},
|
||||||
|
@ -125,7 +128,7 @@ ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni,
|
||||||
|
|
||||||
class JednoHodnoceniForm(forms.ModelForm):
|
class JednoHodnoceniForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Hodnoceni
|
model = Hodnoceni
|
||||||
fields = ('problem', 'body', 'deadline_body', 'feedback',)
|
fields = ('problem', 'body', 'deadline_body', 'feedback',)
|
||||||
widgets = {
|
widgets = {
|
||||||
'problem': autocomplete.ModelSelect2(
|
'problem': autocomplete.ModelSelect2(
|
||||||
|
@ -158,7 +161,7 @@ OhodnoceniReseniFormSet = formset_factory(JednoHodnoceniForm,
|
||||||
|
|
||||||
class PoznamkaReseniForm(forms.ModelForm):
|
class PoznamkaReseniForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
fields = ('poznamka',)
|
fields = ('poznamka',)
|
||||||
|
|
||||||
# FIXME: Ideálně by mělo být součástí třídy níž, ale neumím to udělat
|
# FIXME: Ideálně by mělo být součástí třídy níž, ale neumím to udělat
|
||||||
|
@ -198,7 +201,7 @@ class OdevzdavatkoTabulkaFiltrForm(forms.Form):
|
||||||
|
|
||||||
from django.db.utils import OperationalError
|
from django.db.utils import OperationalError
|
||||||
try:
|
try:
|
||||||
aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik
|
aktualni_rocnik = Nastaveni.get_solo().aktualni_rocnik
|
||||||
except OperationalError:
|
except OperationalError:
|
||||||
# django.db.utils.OperationalError: no such table: seminar_nastaveni
|
# django.db.utils.OperationalError: no such table: seminar_nastaveni
|
||||||
# Nemáme databázi, takže to selhalo. Pro jistotu vrátíme aspoň dvě možnosti, ať to nepadá dál
|
# Nemáme databázi, takže to selhalo. Pro jistotu vrátíme aspoň dvě možnosti, ať to nepadá dál
|
||||||
|
@ -214,7 +217,7 @@ class OdevzdavatkoTabulkaFiltrForm(forms.Form):
|
||||||
|
|
||||||
result.append(("0001-01-01", f"Odjakživa"))
|
result.append(("0001-01-01", f"Odjakživa"))
|
||||||
|
|
||||||
for deadline in m.Deadline.objects.filter(
|
for deadline in Deadline.objects.filter(
|
||||||
deadline__lte=timezone.now(),
|
deadline__lte=timezone.now(),
|
||||||
cislo__rocnik=aktualni_rocnik
|
cislo__rocnik=aktualni_rocnik
|
||||||
).order_by("deadline"):
|
).order_by("deadline"):
|
||||||
|
|
|
@ -9,14 +9,14 @@ from django.urls import reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
import tvorba.models as am
|
from tvorba.models import Problem, Deadline, Cislo, Uloha, aux_generate_filename
|
||||||
from seminar.models import base as bm
|
from various.models import SeminarModelBase
|
||||||
|
|
||||||
from odevzdavatko.utils import vzorecek_na_prepocet, inverze_vzorecku_na_prepocet
|
from odevzdavatko.utils import vzorecek_na_prepocet, inverze_vzorecku_na_prepocet
|
||||||
from personalni.models import Resitel
|
from personalni.models import Resitel
|
||||||
|
|
||||||
@reversion.register(ignore_duplicates=True)
|
@reversion.register(ignore_duplicates=True)
|
||||||
class Reseni(bm.SeminarModelBase):
|
class Reseni(SeminarModelBase):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'seminar_reseni'
|
db_table = 'seminar_reseni'
|
||||||
|
@ -29,7 +29,7 @@ class Reseni(bm.SeminarModelBase):
|
||||||
id = models.AutoField(primary_key = True)
|
id = models.AutoField(primary_key = True)
|
||||||
|
|
||||||
# Ke každé dvojici řešní a problém existuje nanejvýš jedno hodnocení, doplnění vazby.
|
# Ke každé dvojici řešní a problém existuje nanejvýš jedno hodnocení, doplnění vazby.
|
||||||
problem = models.ManyToManyField(am.Problem, verbose_name='problém', help_text='Problém',
|
problem = models.ManyToManyField(Problem, verbose_name='problém', help_text='Problém',
|
||||||
through='Hodnoceni')
|
through='Hodnoceni')
|
||||||
|
|
||||||
resitele = models.ManyToManyField(Resitel, verbose_name='autoři řešení',
|
resitele = models.ManyToManyField(Resitel, verbose_name='autoři řešení',
|
||||||
|
@ -79,7 +79,7 @@ class Reseni(bm.SeminarModelBase):
|
||||||
# NOTE: Potenciální DB HOG (bez select_related)
|
# NOTE: Potenciální DB HOG (bez select_related)
|
||||||
|
|
||||||
def deadline_reseni(self):
|
def deadline_reseni(self):
|
||||||
return am.Deadline.objects.filter(deadline__gte=self.cas_doruceni).order_by("deadline").first()
|
return Deadline.objects.filter(deadline__gte=self.cas_doruceni).order_by("deadline").first()
|
||||||
|
|
||||||
## Pravdepodobne uz nebude potreba:
|
## Pravdepodobne uz nebude potreba:
|
||||||
# def save(self, *args, **kwargs):
|
# def save(self, *args, **kwargs):
|
||||||
|
@ -88,7 +88,7 @@ class Reseni(bm.SeminarModelBase):
|
||||||
# self.cislo_body = self.problem.cislo_reseni
|
# self.cislo_body = self.problem.cislo_reseni
|
||||||
# super(Reseni, self).save(*args, **kwargs)
|
# super(Reseni, self).save(*args, **kwargs)
|
||||||
|
|
||||||
class Hodnoceni(bm.SeminarModelBase):
|
class Hodnoceni(SeminarModelBase):
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'seminar_hodnoceni'
|
db_table = 'seminar_hodnoceni'
|
||||||
verbose_name = 'Hodnocení'
|
verbose_name = 'Hodnocení'
|
||||||
|
@ -101,16 +101,16 @@ class Hodnoceni(bm.SeminarModelBase):
|
||||||
body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='body',
|
body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='body',
|
||||||
blank=True, null=True)
|
blank=True, null=True)
|
||||||
|
|
||||||
cislo_body = models.ForeignKey(am.Cislo, verbose_name='číslo pro body',
|
cislo_body = models.ForeignKey(Cislo, verbose_name='číslo pro body',
|
||||||
related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT)
|
related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT)
|
||||||
|
|
||||||
# V ročníku < 26 nastaveno na deadline vygenerovaný pro původní cislo_body
|
# V ročníku < 26 nastaveno na deadline vygenerovaný pro původní cislo_body
|
||||||
deadline_body = models.ForeignKey(am.Deadline, verbose_name='deadline pro body',
|
deadline_body = models.ForeignKey(Deadline, verbose_name='deadline pro body',
|
||||||
related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT)
|
related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT)
|
||||||
|
|
||||||
reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE)
|
reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE)
|
||||||
|
|
||||||
problem = models.ForeignKey(am.Problem, verbose_name='problém',
|
problem = models.ForeignKey(Problem, verbose_name='problém',
|
||||||
related_name='hodnoceni', on_delete=models.PROTECT)
|
related_name='hodnoceni', on_delete=models.PROTECT)
|
||||||
|
|
||||||
feedback = models.TextField('zpětná vazba', blank=True, default='', help_text='Zpětná vazba řešiteli (plain text)')
|
feedback = models.TextField('zpětná vazba', blank=True, default='', help_text='Zpětná vazba řešiteli (plain text)')
|
||||||
|
@ -166,7 +166,7 @@ class Hodnoceni(bm.SeminarModelBase):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def body_neprepocitane_max(self):
|
def body_neprepocitane_max(self):
|
||||||
if not isinstance(self.problem.get_real_instance(), am.Uloha):
|
if not isinstance(self.problem.get_real_instance(), Uloha):
|
||||||
return None
|
return None
|
||||||
return self.problem.uloha.max_body
|
return self.problem.uloha.max_body
|
||||||
|
|
||||||
|
@ -176,12 +176,12 @@ class Hodnoceni(bm.SeminarModelBase):
|
||||||
def generate_filename(self, filename):
|
def generate_filename(self, filename):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
settings.SEMINAR_RESENI_DIR,
|
settings.SEMINAR_RESENI_DIR,
|
||||||
am.aux_generate_filename(self, filename)
|
aux_generate_filename(self, filename)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@reversion.register(ignore_duplicates=True)
|
@reversion.register(ignore_duplicates=True)
|
||||||
class PrilohaReseni(bm.SeminarModelBase):
|
class PrilohaReseni(SeminarModelBase):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'seminar_priloha_reseni'
|
db_table = 'seminar_priloha_reseni'
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<form enctype="multipart/form-data" action="{% url 'seminar_nahraj_reseni' nadproblem_id %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
<form enctype="multipart/form-data" action="{% url 'odevzdavatko_nahraj_reseni' nadproblem_id %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<table class='form'>
|
<table class='form'>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{% for problem in object_list %}
|
{% for problem in object_list %}
|
||||||
<li><a href="{% url 'seminar_nahraj_reseni' problem.id %}">{{ problem }}</a></li>
|
<li><a href="{% url 'odevzdavatko_nahraj_reseni' problem.id %}">{{ problem }}</a></li>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<li>Nelze nic odevzdávat.</li>
|
<li>Nelze nic odevzdávat.</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
Vložit řešení
|
Vložit řešení
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</h1>
|
</h1>
|
||||||
<form enctype="multipart/form-data" action="{% url 'seminar_vloz_reseni' %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
<form enctype="multipart/form-data" action="{% url 'odevzdavatko_vloz_reseni' %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{form.as_p}}
|
{{form.as_p}}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@ from django import template
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
from functools import cache
|
from functools import cache
|
||||||
import seminar.models as m
|
from odevzdavatko.models import Reseni
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
@cache
|
@cache
|
||||||
def barva_reseni(r: m.Reseni):
|
def barva_reseni(r: Reseni):
|
||||||
"""Vrátí nějakou barvu pro daný problém, ve tvaru '#RRGGBB'
|
"""Vrátí nějakou barvu pro daný problém, ve tvaru '#RRGGBB'
|
||||||
|
|
||||||
Efektivně hešujeme do barev."""
|
Efektivně hešujeme do barev."""
|
||||||
|
|
|
@ -2,8 +2,8 @@ from django import template
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
from personalni.utils import normalizuj_jmeno
|
from personalni.utils import normalizuj_jmeno
|
||||||
import seminar.models as m # jen kvůli typové anotaci…
|
from personalni.models import Osoba # jen kvůli typové anotaci…
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def jmeno_jako_prefix(o: m.Osoba):
|
def jmeno_jako_prefix(o: Osoba):
|
||||||
return normalizuj_jmeno(o).replace(' ', '_')
|
return normalizuj_jmeno(o).replace(' ', '_')
|
||||||
|
|
|
@ -5,10 +5,10 @@ from various.views.generic import viewMethodSwitch
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('org/add_solution', org_required(views.VlozReseniView.as_view()), name='seminar_vloz_reseni'),
|
path('org/add_solution', org_required(views.VlozReseniView.as_view()), name='odevzdavatko_vloz_reseni'),
|
||||||
path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniRozcestnikTematekView.as_view()), name='seminar_nahraj_reseni'),
|
path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniRozcestnikTematekView.as_view()), name='odevzdavatko_nahraj_reseni'),
|
||||||
path('resitel/nahraj_reseni/<int:nadproblem_id>/', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
|
path('resitel/nahraj_reseni/<int:nadproblem_id>/', resitel_required(views.NahrajReseniView.as_view()), name='odevzdavatko_nahraj_reseni'),
|
||||||
path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'),
|
path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='odevzdavatko_resitel_odevzdana_reseni'),
|
||||||
|
|
||||||
path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||||
path('org/reseni/rocnik/<int:rocnik>/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
path('org/reseni/rocnik/<int:rocnik>/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||||
|
|
|
@ -17,10 +17,14 @@ from decimal import Decimal
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import seminar.models as m
|
|
||||||
from . import forms as f
|
from . import forms as f
|
||||||
from .forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm
|
from .forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm
|
||||||
|
from .models import Hodnoceni, Reseni
|
||||||
|
|
||||||
|
from personalni.models import Resitel, Osoba, Organizator
|
||||||
|
from tvorba.models import Problem, Deadline, Rocnik
|
||||||
from tvorba.utils import resi_v_rocniku
|
from tvorba.utils import resi_v_rocniku
|
||||||
|
from various.models import Nastaveni
|
||||||
from various.views.pomocne import formularOKView
|
from various.views.pomocne import formularOKView
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -40,20 +44,20 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class TabulkaOdevzdanychReseniView(ListView):
|
class TabulkaOdevzdanychReseniView(ListView):
|
||||||
template_name = 'odevzdavatko/tabulka.html'
|
template_name = 'odevzdavatko/tabulka.html'
|
||||||
model = m.Hodnoceni
|
model = Hodnoceni
|
||||||
|
|
||||||
def inicializuj_osy_tabulky(self):
|
def inicializuj_osy_tabulky(self):
|
||||||
"""Vyrobí prvotní querysety pro sloupce a řádky, tj. seznam všech řešitelů a problémů"""
|
"""Vyrobí prvotní querysety pro sloupce a řádky, tj. seznam všech řešitelů a problémů"""
|
||||||
# FIXME: jméno metody není vypovídající...
|
# FIXME: jméno metody není vypovídající...
|
||||||
# NOTE: Tenhle blok nemůže být přímo ve třídě, protože před vyrobením databáze neexistují ty objekty (?). TODO: Otestovat
|
# NOTE: Tenhle blok nemůže být přímo ve třídě, protože před vyrobením databáze neexistují ty objekty (?). TODO: Otestovat
|
||||||
# TODO: Prefetches, Select related, ...
|
# TODO: Prefetches, Select related, ...
|
||||||
self.resitele = m.Resitel.objects.all()
|
self.resitele = Resitel.objects.all()
|
||||||
self.problemy = m.Problem.objects.all()
|
self.problemy = Problem.objects.all()
|
||||||
self.reseni = m.Reseni.objects.all()
|
self.reseni = Reseni.objects.all()
|
||||||
|
|
||||||
self.aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci
|
self.aktualni_rocnik = Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci
|
||||||
if 'rocnik' in self.kwargs:
|
if 'rocnik' in self.kwargs:
|
||||||
self.aktualni_rocnik = get_object_or_404(m.Rocnik, rocnik=self.kwargs['rocnik'])
|
self.aktualni_rocnik = get_object_or_404(Rocnik, rocnik=self.kwargs['rocnik'])
|
||||||
|
|
||||||
form = FiltrForm(self.request.GET, rocnik=self.aktualni_rocnik)
|
form = FiltrForm(self.request.GET, rocnik=self.aktualni_rocnik)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
@ -86,14 +90,14 @@ class TabulkaOdevzdanychReseniView(ListView):
|
||||||
self.resitele = self.resitele.filter(rok_maturity__gt=self.aktualni_rocnik.prvni_rok)
|
self.resitele = self.resitele.filter(rok_maturity__gt=self.aktualni_rocnik.prvni_rok)
|
||||||
|
|
||||||
if problemy == FiltrForm.PROBLEMY_MOJE:
|
if problemy == FiltrForm.PROBLEMY_MOJE:
|
||||||
org = m.Organizator.objects.get(osoba__user=self.request.user)
|
org = Organizator.objects.get(osoba__user=self.request.user)
|
||||||
self.problemy = self.problemy.filter(
|
self.problemy = self.problemy.filter(
|
||||||
Q(autor=org)|Q(garant=org)|Q(opravovatele=org),
|
Q(autor=org)|Q(garant=org)|Q(opravovatele=org),
|
||||||
Q(stav=m.Problem.STAV_ZADANY)|Q(stav=m.Problem.STAV_VYRESENY),
|
Q(stav=Problem.STAV_ZADANY)|Q(stav=Problem.STAV_VYRESENY),
|
||||||
)
|
)
|
||||||
elif problemy == FiltrForm.PROBLEMY_LETOSNI:
|
elif problemy == FiltrForm.PROBLEMY_LETOSNI:
|
||||||
self.problemy = self.problemy.filter(
|
self.problemy = self.problemy.filter(
|
||||||
Q(stav=m.Problem.STAV_ZADANY)|Q(stav=m.Problem.STAV_VYRESENY),
|
Q(stav=Problem.STAV_ZADANY)|Q(stav=Problem.STAV_VYRESENY),
|
||||||
)
|
)
|
||||||
#self.problemy = list(filter(lambda problem: problem.rocnik() == self.aktualni_rocnik, self.problemy)) # DB HOG? # FIXME: některé problémy nemají ročník....
|
#self.problemy = list(filter(lambda problem: problem.rocnik() == self.aktualni_rocnik, self.problemy)) # DB HOG? # FIXME: některé problémy nemají ročník....
|
||||||
# NOTE: Protože řešení odkazuje přímo na Problém a QuerySet na Hodnocení je nepolymorfní, musíme porovnávat taky s nepolymorfními Problémy.
|
# NOTE: Protože řešení odkazuje přímo na Problém a QuerySet na Hodnocení je nepolymorfní, musíme porovnávat taky s nepolymorfními Problémy.
|
||||||
|
@ -121,8 +125,8 @@ class TabulkaOdevzdanychReseniView(ListView):
|
||||||
ctx = super().get_context_data(*args, **kwargs)
|
ctx = super().get_context_data(*args, **kwargs)
|
||||||
ctx['problemy'] = self.problemy
|
ctx['problemy'] = self.problemy
|
||||||
ctx['resitele'] = self.resitele
|
ctx['resitele'] = self.resitele
|
||||||
tabulka: dict[m.Problem, dict[m.Resitel, list[tuple[m.Reseni, m.Hodnoceni]]]] = dict()
|
tabulka: dict[Problem, dict[Resitel, list[tuple[Reseni, Hodnoceni]]]] = dict()
|
||||||
soucty: dict[m.Problem, dict[m.Resitel, Decimal]] = dict()
|
soucty: dict[Problem, dict[Resitel, Decimal]] = dict()
|
||||||
|
|
||||||
def pridej_reseni(resitel, hodnoceni):
|
def pridej_reseni(resitel, hodnoceni):
|
||||||
problem = hodnoceni.problem
|
problem = hodnoceni.problem
|
||||||
|
@ -143,11 +147,11 @@ class TabulkaOdevzdanychReseniView(ListView):
|
||||||
for resitel in hodnoceni.reseni.resitele.all():
|
for resitel in hodnoceni.reseni.resitele.all():
|
||||||
pridej_reseni(resitel, hodnoceni)
|
pridej_reseni(resitel, hodnoceni)
|
||||||
|
|
||||||
hodnoty: list[list[tuple[Decimal,list[tuple[m.Reseni, m.Hodnoceni]]]]] = [] # Seznam řádků výsledné tabulky podle self.resitele, v každém řádku buňky v pořadí podle self.problemy + jejich součty, v každé buňce seznam řešení k danému řešiteli a problému.
|
hodnoty: list[list[tuple[Decimal,list[tuple[Reseni, Hodnoceni]]]]] = [] # Seznam řádků výsledné tabulky podle self.resitele, v každém řádku buňky v pořadí podle self.problemy + jejich součty, v každé buňce seznam řešení k danému řešiteli a problému.
|
||||||
resitele_do_tabulky: list[m.Resitel] = []
|
resitele_do_tabulky: list[Resitel] = []
|
||||||
for resitel in self.resitele:
|
for resitel in self.resitele:
|
||||||
dostal_body = False
|
dostal_body = False
|
||||||
resiteluv_radek: list[tuple[Decimal,list[tuple[m.Reseni, m.Hodnoceni]]]] = [] # podle pořadí v self.problemy
|
resiteluv_radek: list[tuple[Decimal,list[tuple[Reseni, Hodnoceni]]]] = [] # podle pořadí v self.problemy
|
||||||
for problem in self.problemy:
|
for problem in self.problemy:
|
||||||
if problem in tabulka and resitel in tabulka[problem]:
|
if problem in tabulka and resitel in tabulka[problem]:
|
||||||
resiteluv_radek.append((soucty[problem][resitel], tabulka[problem][resitel]))
|
resiteluv_radek.append((soucty[problem][resitel], tabulka[problem][resitel]))
|
||||||
|
@ -162,7 +166,7 @@ class TabulkaOdevzdanychReseniView(ListView):
|
||||||
# Pro použití hacku na automatické {{form.media}} v template:
|
# Pro použití hacku na automatické {{form.media}} v template:
|
||||||
ctx['form'] = ctx['filtr']
|
ctx['form'] = ctx['filtr']
|
||||||
# Pro maximum v přesměrovátku ročníků
|
# Pro maximum v přesměrovátku ročníků
|
||||||
ctx['aktualni_rocnik'] = m.Nastaveni.get_solo().aktualni_rocnik
|
ctx['aktualni_rocnik'] = Nastaveni.get_solo().aktualni_rocnik
|
||||||
ctx['barvicky'] = self.barvicky
|
ctx['barvicky'] = self.barvicky
|
||||||
if 'rocnik' in self.kwargs:
|
if 'rocnik' in self.kwargs:
|
||||||
ctx['rocnik'] = self.kwargs['rocnik']
|
ctx['rocnik'] = self.kwargs['rocnik']
|
||||||
|
@ -178,7 +182,7 @@ class ReseniProblemuView(MultipleObjectTemplateResponseMixin, MultipleObjectMixi
|
||||||
Asi už bude zastaralý v okamžiku, kdy se tenhle komentář nasadí na produkci :-)
|
Asi už bude zastaralý v okamžiku, kdy se tenhle komentář nasadí na produkci :-)
|
||||||
|
|
||||||
V případě, že takové řešení existuje jen jedno, tak na něj přesměruje."""
|
V případě, že takové řešení existuje jen jedno, tak na něj přesměruje."""
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
template_name = 'odevzdavatko/seznam.html'
|
template_name = 'odevzdavatko/seznam.html'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
@ -190,8 +194,8 @@ class ReseniProblemuView(MultipleObjectTemplateResponseMixin, MultipleObjectMixi
|
||||||
if problem_id is None:
|
if problem_id is None:
|
||||||
raise ValueError("Nemám problém! (To je problém!)")
|
raise ValueError("Nemám problém! (To je problém!)")
|
||||||
|
|
||||||
resitel = m.Resitel.objects.get(id=resitel_id)
|
resitel = Resitel.objects.get(id=resitel_id)
|
||||||
problem = m.Problem.objects.get(id=problem_id)
|
problem = Problem.objects.get(id=problem_id)
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
problem__in=[problem],
|
problem__in=[problem],
|
||||||
resitele__in=[resitel],
|
resitele__in=[resitel],
|
||||||
|
@ -221,13 +225,13 @@ class ReseniProblemuView(MultipleObjectTemplateResponseMixin, MultipleObjectMixi
|
||||||
## XXX: https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#avoid-anything-more-complex
|
## XXX: https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#avoid-anything-more-complex
|
||||||
class DetailReseniView(DetailView):
|
class DetailReseniView(DetailView):
|
||||||
""" Náhled na řešení. Editace je v :py:class:`EditReseniView`. """
|
""" Náhled na řešení. Editace je v :py:class:`EditReseniView`. """
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
template_name = 'odevzdavatko/detail.html'
|
template_name = 'odevzdavatko/detail.html'
|
||||||
|
|
||||||
def aktualni_hodnoceni(self):
|
def aktualni_hodnoceni(self):
|
||||||
self.reseni = get_object_or_404(m.Reseni, id=self.kwargs['pk'])
|
self.reseni = get_object_or_404(Reseni, id=self.kwargs['pk'])
|
||||||
result = [] # Slovníky s klíči problem, body, deadline_body -- initial data pro f.OhodnoceniReseniFormSet
|
result = [] # Slovníky s klíči problem, body, deadline_body -- initial data pro f.OhodnoceniReseniFormSet
|
||||||
for hodn in m.Hodnoceni.objects.filter(reseni=self.reseni):
|
for hodn in Hodnoceni.objects.filter(reseni=self.reseni):
|
||||||
seznam_atributu = [
|
seznam_atributu = [
|
||||||
"problem",
|
"problem",
|
||||||
"body",
|
"body",
|
||||||
|
@ -284,7 +288,7 @@ class EditReseniView(DetailReseniView):
|
||||||
|
|
||||||
|
|
||||||
def hodnoceniReseniView(request, pk, *args, **kwargs):
|
def hodnoceniReseniView(request, pk, *args, **kwargs):
|
||||||
reseni = get_object_or_404(m.Reseni, pk=pk)
|
reseni = get_object_or_404(Reseni, pk=pk)
|
||||||
success_url = reverse('odevzdavatko_detail_reseni', kwargs={'pk': pk})
|
success_url = reverse('odevzdavatko_detail_reseni', kwargs={'pk': pk})
|
||||||
|
|
||||||
# FIXME: Použit initial i tady a nebastlit hodnocení tak nízkoúrovňově
|
# FIXME: Použit initial i tady a nebastlit hodnocení tak nízkoúrovňově
|
||||||
|
@ -300,7 +304,7 @@ def hodnoceniReseniView(request, pk, *args, **kwargs):
|
||||||
poznamka_form.save()
|
poznamka_form.save()
|
||||||
|
|
||||||
# Smažeme všechna dosavadní hodnocení tohoto řešení
|
# Smažeme všechna dosavadní hodnocení tohoto řešení
|
||||||
qs = m.Hodnoceni.objects.filter(reseni=reseni)
|
qs = Hodnoceni.objects.filter(reseni=reseni)
|
||||||
logger.info(f"Will delete {qs.count()} objects: {qs}")
|
logger.info(f"Will delete {qs.count()} objects: {qs}")
|
||||||
qs.delete()
|
qs.delete()
|
||||||
|
|
||||||
|
@ -311,7 +315,7 @@ def hodnoceniReseniView(request, pk, *args, **kwargs):
|
||||||
del(data_for_hodnoceni["body_celkem"])
|
del(data_for_hodnoceni["body_celkem"])
|
||||||
del(data_for_hodnoceni["body_neprepocitane"])
|
del(data_for_hodnoceni["body_neprepocitane"])
|
||||||
del(data_for_hodnoceni["body_neprepocitane_celkem"])
|
del(data_for_hodnoceni["body_neprepocitane_celkem"])
|
||||||
hodnoceni = m.Hodnoceni(
|
hodnoceni = Hodnoceni(
|
||||||
reseni=reseni,
|
reseni=reseni,
|
||||||
**form.cleaned_data,
|
**form.cleaned_data,
|
||||||
)
|
)
|
||||||
|
@ -332,14 +336,14 @@ def hodnoceniReseniView(request, pk, *args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
class PrehledOdevzdanychReseni(ListView):
|
class PrehledOdevzdanychReseni(ListView):
|
||||||
model = m.Hodnoceni
|
model = Hodnoceni
|
||||||
template_name = 'odevzdavatko/prehled_reseni.html'
|
template_name = 'odevzdavatko/prehled_reseni.html'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if not self.request.user.is_authenticated:
|
if not self.request.user.is_authenticated:
|
||||||
raise RuntimeError("Uživatel měl být přihlášený!")
|
raise RuntimeError("Uživatel měl být přihlášený!")
|
||||||
# get_or_none, aby neexistence řešitele (např. u orgů) neházela chybu
|
# get_or_none, aby neexistence řešitele (např. u orgů) neházela chybu
|
||||||
resitel = m.Resitel.objects.filter(osoba__user=self.request.user).first()
|
resitel = Resitel.objects.filter(osoba__user=self.request.user).first()
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
qs = qs.filter(reseni__resitele__in=[resitel])
|
qs = qs.filter(reseni__resitele__in=[resitel])
|
||||||
# Setřídíme podle času doručení řešení, aby se netřídily podle okamžiku vyrobení Hodnocení
|
# Setřídíme podle času doručení řešení, aby se netřídily podle okamžiku vyrobení Hodnocení
|
||||||
|
@ -360,13 +364,13 @@ class PrehledOdevzdanychReseni(ListView):
|
||||||
# Přehled všech řešení kvůli debugování
|
# Přehled všech řešení kvůli debugování
|
||||||
|
|
||||||
class SeznamReseniView(ListView):
|
class SeznamReseniView(ListView):
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
template_name = 'odevzdavatko/seznam.html'
|
template_name = 'odevzdavatko/seznam.html'
|
||||||
|
|
||||||
class SeznamAktualnichReseniView(SeznamReseniView):
|
class SeznamAktualnichReseniView(SeznamReseniView):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
akt_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci, asi...
|
akt_rocnik = Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci, asi...
|
||||||
resitele = resi_v_rocniku(akt_rocnik)
|
resitele = resi_v_rocniku(akt_rocnik)
|
||||||
qs = qs.filter(resitele__in=resitele) # FIXME: Najde řešení i ze starých ročníků, která odevzdal alespoň jeden aktuální řešitel
|
qs = qs.filter(resitele__in=resitele) # FIXME: Najde řešení i ze starých ročníků, která odevzdal alespoň jeden aktuální řešitel
|
||||||
return qs
|
return qs
|
||||||
|
@ -378,7 +382,7 @@ class VlozReseniView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
data = form.cleaned_data
|
data = form.cleaned_data
|
||||||
nove_reseni = m.Reseni.objects.create(
|
nove_reseni = Reseni.objects.create(
|
||||||
cas_doruceni=data['cas_doruceni'],
|
cas_doruceni=data['cas_doruceni'],
|
||||||
forma=data['forma'],
|
forma=data['forma'],
|
||||||
poznamka=data['poznamka'],
|
poznamka=data['poznamka'],
|
||||||
|
@ -405,35 +409,35 @@ class VlozReseniView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
|
|
||||||
class NahrajReseniRozcestnikTematekView(LoginRequiredMixin, ListView):
|
class NahrajReseniRozcestnikTematekView(LoginRequiredMixin, ListView):
|
||||||
model = m.Problem
|
model = Problem
|
||||||
template_name = 'odevzdavatko/nahraj_reseni_nadproblem.html'
|
template_name = 'odevzdavatko/nahraj_reseni_nadproblem.html'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().filter(stav=m.Problem.STAV_ZADANY, nadproblem__isnull=True)
|
return super().get_queryset().filter(stav=Problem.STAV_ZADANY, nadproblem__isnull=True)
|
||||||
|
|
||||||
|
|
||||||
class NahrajReseniView(LoginRequiredMixin, CreateView):
|
class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
template_name = 'odevzdavatko/nahraj_reseni.html'
|
template_name = 'odevzdavatko/nahraj_reseni.html'
|
||||||
form_class = f.NahrajReseniForm
|
form_class = f.NahrajReseniForm
|
||||||
nadproblem: m.Problem
|
nadproblem: Problem
|
||||||
|
|
||||||
def setup(self, request, *args, **kwargs):
|
def setup(self, request, *args, **kwargs):
|
||||||
super().setup(request, *args, **kwargs)
|
super().setup(request, *args, **kwargs)
|
||||||
nadproblem_id = self.kwargs["nadproblem_id"]
|
nadproblem_id = self.kwargs["nadproblem_id"]
|
||||||
self.nadproblem = get_object_or_404(m.Problem, id=nadproblem_id)
|
self.nadproblem = get_object_or_404(Problem, id=nadproblem_id)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
# Zaříznutí nezadaných problémů
|
# Zaříznutí nezadaných problémů
|
||||||
if self.nadproblem.stav != m.Problem.STAV_ZADANY:
|
if self.nadproblem.stav != Problem.STAV_ZADANY:
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
|
||||||
# Zaříznutí starých řešitelů:
|
# Zaříznutí starých řešitelů:
|
||||||
# FIXME: Je to tady dost naprasené, mělo by to asi být jinde…
|
# FIXME: Je to tady dost naprasené, mělo by to asi být jinde…
|
||||||
osoba = m.Osoba.objects.get(user=self.request.user)
|
osoba = Osoba.objects.get(user=self.request.user)
|
||||||
resitel = osoba.resitel
|
resitel = osoba.resitel
|
||||||
if resitel.rok_maturity <= m.Nastaveni.get_solo().aktualni_rocnik.prvni_rok:
|
if resitel.rok_maturity <= Nastaveni.get_solo().aktualni_rocnik.prvni_rok:
|
||||||
return render(request, 'universal.html', {
|
return render(request, 'universal.html', {
|
||||||
'title': 'Nelze odevzdat',
|
'title': 'Nelze odevzdat',
|
||||||
'error': 'Zdá se, že jsi již odmaturoval/a, a tedy nemůžeš odevzdat do našeho semináře řešení.',
|
'error': 'Zdá se, že jsi již odmaturoval/a, a tedy nemůžeš odevzdat do našeho semináře řešení.',
|
||||||
|
@ -445,7 +449,7 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
nadproblem_id = self.nadproblem.id
|
nadproblem_id = self.nadproblem.id
|
||||||
return {
|
return {
|
||||||
"nadproblem_id": nadproblem_id,
|
"nadproblem_id": nadproblem_id,
|
||||||
"problem": [] if self.nadproblem.podproblem.filter(stav=m.Problem.STAV_ZADANY).exists() else nadproblem_id
|
"problem": [] if self.nadproblem.podproblem.filter(stav=Problem.STAV_ZADANY).exists() else nadproblem_id
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +461,7 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
data['prilohy'] = f.ReseniSPrilohamiFormSet()
|
data['prilohy'] = f.ReseniSPrilohamiFormSet()
|
||||||
|
|
||||||
data["nadproblem_id"] = self.nadproblem.id
|
data["nadproblem_id"] = self.nadproblem.id
|
||||||
data["nadproblem"] = get_object_or_404(m.Problem, id=self.nadproblem.id)
|
data["nadproblem"] = get_object_or_404(Problem, id=self.nadproblem.id)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
|
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
|
||||||
|
@ -469,17 +473,17 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
self.object = form.save()
|
self.object = form.save()
|
||||||
self.object.resitele.add(m.Resitel.objects.get(osoba__user = self.request.user))
|
self.object.resitele.add(Resitel.objects.get(osoba__user = self.request.user))
|
||||||
self.object.resitele.add(*form.cleaned_data["resitele"])
|
self.object.resitele.add(*form.cleaned_data["resitele"])
|
||||||
self.object.cas_doruceni = timezone.now()
|
self.object.cas_doruceni = timezone.now()
|
||||||
self.object.forma = m.Reseni.FORMA_UPLOAD
|
self.object.forma = Reseni.FORMA_UPLOAD
|
||||||
self.object.save()
|
self.object.save()
|
||||||
|
|
||||||
prilohy.instance = self.object
|
prilohy.instance = self.object
|
||||||
prilohy.save()
|
prilohy.save()
|
||||||
|
|
||||||
for hodnoceni in self.object.hodnoceni_set.all():
|
for hodnoceni in self.object.hodnoceni_set.all():
|
||||||
hodnoceni.deadline_body = m.Deadline.objects.filter(deadline__gte=self.object.cas_doruceni).first()
|
hodnoceni.deadline_body = Deadline.objects.filter(deadline__gte=self.object.cas_doruceni).first()
|
||||||
hodnoceni.save()
|
hodnoceni.save()
|
||||||
|
|
||||||
# Pošleme mail opravovatelům a garantovi
|
# Pošleme mail opravovatelům a garantovi
|
||||||
|
@ -497,7 +501,7 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
# FIXME: Víc informativní obsah mailů, možná vč. příloh?
|
# FIXME: Víc informativní obsah mailů, možná vč. příloh?
|
||||||
prijemci = map(lambda it: it.osoba.email, prijemci)
|
prijemci = map(lambda it: it.osoba.email, prijemci)
|
||||||
|
|
||||||
resitel = m.Osoba.objects.get(user = self.request.user)
|
resitel = Osoba.objects.get(user = self.request.user)
|
||||||
|
|
||||||
seznam = "problému " + str(problemy[0]) if len(problemy) == 1 else 'následujícím problémům:\n' + ', \n'.join(map(str, problemy))
|
seznam = "problému " + str(problemy[0]) if len(problemy) == 1 else 'následujícím problémům:\n' + ', \n'.join(map(str, problemy))
|
||||||
seznam_do_subjectu = "problému " + str(problemy[0]) + ("" if len(problemy) == 1 else f" (a dalším { len(problemy) - 1 })")
|
seznam_do_subjectu = "problému " + str(problemy[0]) + ("" if len(problemy) == 1 else f" (a dalším { len(problemy) - 1 })")
|
||||||
|
@ -512,5 +516,5 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
return formularOKView(
|
return formularOKView(
|
||||||
self.request,
|
self.request,
|
||||||
text='Řešení úspěšně odevzdáno',
|
text='Řešení úspěšně odevzdáno',
|
||||||
dalsi_odkazy=[("Odevzdat další řešení", reverse("seminar_nahraj_reseni"))],
|
dalsi_odkazy=[("Odevzdat další řešení", reverse("odevzdavatko_nahraj_reseni"))],
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib import admin
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django_reverse_admin import ReverseModelAdmin
|
from django_reverse_admin import ReverseModelAdmin
|
||||||
from django.contrib.messages import WARNING, ERROR, SUCCESS
|
from django.contrib.messages import WARNING, ERROR, SUCCESS
|
||||||
import seminar.models as m
|
import personalni.models as m
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@admin.action(description="Sjednoť telefony")
|
@admin.action(description="Sjednoť telefony")
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib.auth.forms import PasswordResetForm
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from seminar.models import Skola, Resitel, Osoba
|
from personalni.models import Skola, Resitel, Osoba
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
import logging
|
import logging
|
||||||
|
@ -27,7 +27,7 @@ class TelInput(forms.TextInput):
|
||||||
|
|
||||||
class UdajeForm(forms.Form):
|
class UdajeForm(forms.Form):
|
||||||
username = None
|
username = None
|
||||||
err_logger = logging.getLogger('seminar.prihlaska.problem')
|
err_logger = logging.getLogger('personalni.prihlaska.problem')
|
||||||
|
|
||||||
jmeno = forms.CharField(label='Jméno', max_length=256, required=True)
|
jmeno = forms.CharField(label='Jméno', max_length=256, required=True)
|
||||||
prezdivka_resitele = forms.CharField(label='Přezdívka (veřejná)', max_length=256, required=False)
|
prezdivka_resitele = forms.CharField(label='Přezdívka (veřejná)', max_length=256, required=False)
|
||||||
|
@ -147,7 +147,7 @@ class PrihlaskaForm(PasswordResetForm, UdajeForm):
|
||||||
|
|
||||||
|
|
||||||
class ProfileEditForm(UdajeForm):
|
class ProfileEditForm(UdajeForm):
|
||||||
err_logger = logging.getLogger('seminar.edit.problem')
|
err_logger = logging.getLogger('personalni.prihlaska.problem.edit')
|
||||||
username = forms.CharField(
|
username = forms.CharField(
|
||||||
label='Přihlašovací jméno',
|
label='Přihlašovací jméno',
|
||||||
max_length=256,
|
max_length=256,
|
||||||
|
|
|
@ -11,7 +11,7 @@ from django_countries.fields import CountryField
|
||||||
|
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
|
|
||||||
from seminar.models.base import SeminarModelBase
|
from various.models import SeminarModelBase
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
<li>hlasování o přednáškách</li>
|
<li>hlasování o přednáškách</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="{% url 'seminar_seznam_soustredeni' %}">proběhlá soustředění</a>
|
<li><a href="{% url 'soustredeni_seznam' %}">proběhlá soustředění</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li>vytvoření galerie</li>
|
<li>vytvoření galerie</li>
|
||||||
<li>stažení seznamu účastníků</li>
|
<li>stažení seznamu účastníků</li>
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<a href="{% url 'logout' %}">Odhlásit se</a><br>
|
<a href="{% url 'logout' %}">Odhlásit se</a><br>
|
||||||
<a href="{% url 'seminar_resitel_edit' %}">Upravit údaje</a><br>
|
<a href="{% url 'personalni_resitel_edit' %}">Upravit údaje</a><br>
|
||||||
<a href="{% url 'seminar_nahraj_reseni' %}">Nahrát řešení</a><br>
|
<a href="{% url 'odevzdavatko_nahraj_reseni' %}">Nahrát řešení</a><br>
|
||||||
<a href="{% url 'seminar_resitel_odevzdana_reseni' %}">Již odevzdaná řešení</a><br>
|
<a href="{% url 'odevzdavatko_resitel_odevzdana_reseni' %}">Již odevzdaná řešení</a><br>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<hr>
|
<hr>
|
||||||
<p><a href="{% url 'reset_password' %}">Změnit heslo</a></p>
|
<p><a href="{% url 'reset_password' %}">Změnit heslo</a></p>
|
||||||
|
|
||||||
<form action="{% url 'seminar_resitel_edit' %}" method="post">
|
<form action="{% url 'personalni_resitel_edit' %}" method="post">
|
||||||
{% include "personalni/udaje/udaje.html"%}
|
{% include "personalni/udaje/udaje.html"%}
|
||||||
<input type="submit" value="Změnit">
|
<input type="submit" value="Změnit">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<p><b>Tučně</b> popsaná pole jsou povinná.</p>
|
<p><b>Tučně</b> popsaná pole jsou povinná.</p>
|
||||||
|
|
||||||
<form action="{% url 'seminar_prihlaska' %}" method="post">
|
<form action="{% url 'personalni_prihlaska' %}" method="post">
|
||||||
{% include "personalni/udaje/udaje.html" %}
|
{% include "personalni/udaje/udaje.html" %}
|
||||||
<h4>
|
<h4>
|
||||||
GDPR
|
GDPR
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib.auth.models import User, Group
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from personalni.admin import OsobaAdmin, udelej_orgem
|
from personalni.admin import OsobaAdmin, udelej_orgem
|
||||||
# Tohle bude peklo, až jednou ty modely fakt rozstřelíme… Možná vyrobit various.all_models, které půjdou importovat jako m? :-)
|
# Tohle bude peklo, až jednou ty modely fakt rozstřelíme… Možná vyrobit various.all_models, které půjdou importovat jako m? :-)
|
||||||
import seminar.models as m
|
import personalni.models as m
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
|
@ -7,15 +7,15 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'org/rozcestnik/',
|
'org/rozcestnik/',
|
||||||
org_required(views.OrgoRozcestnikView.as_view()),
|
org_required(views.OrgoRozcestnikView.as_view()),
|
||||||
name='seminar_org_rozcestnik'
|
name='personalni_org_rozcestnik'
|
||||||
),
|
),
|
||||||
|
|
||||||
path('prihlaska/', views.prihlaskaView, name='seminar_prihlaska'),
|
path('prihlaska/', views.prihlaskaView, name='personalni_prihlaska'),
|
||||||
|
|
||||||
path(
|
path(
|
||||||
'resitel/osobni-udaje/',
|
'resitel/osobni-udaje/',
|
||||||
login_required(views.resitelEditView),
|
login_required(views.resitelEditView),
|
||||||
name='seminar_resitel_edit'
|
name='personalni_resitel_edit'
|
||||||
),
|
),
|
||||||
|
|
||||||
# Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku
|
# Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import seminar.models as m
|
|
||||||
from various.utils import bez_diakritiky_translate
|
from various.utils import bez_diakritiky_translate
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -7,9 +6,10 @@ from django.contrib.auth.decorators import permission_required, user_passes_test
|
||||||
from django.contrib.auth.models import AnonymousUser
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
import seminar.models as m
|
|
||||||
import soustredeni.models
|
import soustredeni.models
|
||||||
|
|
||||||
|
from odevzdavatko.models import Reseni_Resitele
|
||||||
|
|
||||||
from .models import Osoba, Organizator, Skola, Resitel, Prijemce
|
from .models import Osoba, Organizator, Skola, Resitel, Prijemce
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ def merge_resitele(cilovy, zdrojovy):
|
||||||
# Přepojit všechny vazby ze zdrojového na cílového
|
# Přepojit všechny vazby ze zdrojového na cílového
|
||||||
print('Přepojuji vazby')
|
print('Přepojuji vazby')
|
||||||
# Vazby: Škola (hotovo), Řešení_Řešitelé, Konfery_Účastníci, Soustředění_Účastníci, Osoba (vyřeší se později, nejde přepojit)
|
# Vazby: Škola (hotovo), Řešení_Řešitelé, Konfery_Účastníci, Soustředění_Účastníci, Osoba (vyřeší se později, nejde přepojit)
|
||||||
ct = m.Reseni_Resitele.objects.filter(resitele=zdrojovy).update(resitele=cilovy)
|
ct = Reseni_Resitele.objects.filter(resitele=zdrojovy).update(resitele=cilovy)
|
||||||
print(f' Přepojeno {ct} řešení')
|
print(f' Přepojeno {ct} řešení')
|
||||||
ct = soustredeni.models.Konfery_Ucastnici.objects.filter(resitel=zdrojovy).update(resitel=cilovy)
|
ct = soustredeni.models.Konfery_Ucastnici.objects.filter(resitel=zdrojovy).update(resitel=cilovy)
|
||||||
print(f' Přepojeno {ct} konfer')
|
print(f' Přepojeno {ct} konfer')
|
||||||
|
|
|
@ -16,8 +16,12 @@ from django.db import transaction
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import seminar.models as s
|
|
||||||
import seminar.models as m
|
import personalni.models as m
|
||||||
|
from soustredeni.models import Soustredeni
|
||||||
|
from odevzdavatko.models import Hodnoceni
|
||||||
|
from tvorba.models import Clanek, Uloha, Tema
|
||||||
|
from various.models import Nastaveni
|
||||||
from .forms import PrihlaskaForm, ProfileEditForm, PoMaturiteProfileEditForm
|
from .forms import PrihlaskaForm, ProfileEditForm, PoMaturiteProfileEditForm
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
@ -91,22 +95,22 @@ class OrgoRozcestnikView(TemplateView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['posledni_soustredeni'] = s.Soustredeni.objects.order_by('-datum_konce').first()
|
context['posledni_soustredeni'] = Soustredeni.objects.order_by('-datum_konce').first()
|
||||||
nastaveni = s.Nastaveni.objects.first()
|
nastaveni = Nastaveni.objects.first()
|
||||||
aktualni_rocnik = nastaveni.aktualni_rocnik
|
aktualni_rocnik = nastaveni.aktualni_rocnik
|
||||||
context['posledni_cislo_url'] = nastaveni.aktualni_cislo.verejne_url()
|
context['posledni_cislo_url'] = nastaveni.aktualni_cislo.verejne_url()
|
||||||
# TODO možná chceme odkazovat na právě rozpracované číslo, a ne to poslední vydané
|
# 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
|
# 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)
|
# přes treenody (a dát si přitom pozor na MezicisloNode)
|
||||||
|
|
||||||
neobodovana_reseni = s.Hodnoceni.objects.filter(body__isnull=True)
|
neobodovana_reseni = Hodnoceni.objects.filter(body__isnull=True)
|
||||||
reseni_mimo_cislo = s.Hodnoceni.objects.filter(deadline_body__isnull=True)
|
reseni_mimo_cislo = Hodnoceni.objects.filter(deadline_body__isnull=True)
|
||||||
context['pocet_neobodovanych_reseni'] = neobodovana_reseni.count()
|
context['pocet_neobodovanych_reseni'] = neobodovana_reseni.count()
|
||||||
context['pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.count()
|
context['pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.count()
|
||||||
|
|
||||||
u = self.request.user
|
u = self.request.user
|
||||||
os = s.Osoba.objects.get(user=u)
|
os = m.Osoba.objects.get(user=u)
|
||||||
organizator = s.Organizator.objects.get(osoba=os)
|
organizator = m.Organizator.objects.get(osoba=os)
|
||||||
|
|
||||||
context['muj_pocet_neobodovanych_reseni'] = neobodovana_reseni.filter(Q(problem__garant=organizator) | Q(problem__autor=organizator) | Q(problem__opravovatele__in=[organizator])).distinct().count()
|
context['muj_pocet_neobodovanych_reseni'] = neobodovana_reseni.filter(Q(problem__garant=organizator) | Q(problem__autor=organizator) | Q(problem__opravovatele__in=[organizator])).distinct().count()
|
||||||
context['muj_pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.filter(Q(problem__garant=organizator) | Q(problem__autor=organizator) | Q(problem__opravovatele__in=[organizator])).count()
|
context['muj_pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.filter(Q(problem__garant=organizator) | Q(problem__autor=organizator) | Q(problem__opravovatele__in=[organizator])).count()
|
||||||
|
@ -116,11 +120,11 @@ class OrgoRozcestnikView(TemplateView):
|
||||||
context["pocty_neopravenych_reseni"] = [(it['problem__nazev'], it['cas'].date) for it in pocty_neopravenych_reseni.all()]
|
context["pocty_neopravenych_reseni"] = [(it['problem__nazev'], it['cas'].date) for it in pocty_neopravenych_reseni.all()]
|
||||||
|
|
||||||
#FIXME: přidat stav='STAV_ZADANY'
|
#FIXME: přidat stav='STAV_ZADANY'
|
||||||
temata = s.Tema.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]),
|
temata = Tema.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]),
|
||||||
rocnik=aktualni_rocnik).distinct()
|
rocnik=aktualni_rocnik).distinct()
|
||||||
ulohy = s.Uloha.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]),
|
ulohy = Uloha.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]),
|
||||||
cislo_zadani__rocnik=aktualni_rocnik).distinct()
|
cislo_zadani__rocnik=aktualni_rocnik).distinct()
|
||||||
clanky = s.Clanek.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]),
|
clanky = Clanek.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]),
|
||||||
cislo__rocnik=aktualni_rocnik).distinct()
|
cislo__rocnik=aktualni_rocnik).distinct()
|
||||||
|
|
||||||
context['temata'] = temata
|
context['temata'] = temata
|
||||||
|
@ -134,12 +138,12 @@ class OrgoRozcestnikView(TemplateView):
|
||||||
|
|
||||||
|
|
||||||
class ResitelView(LoginRequiredMixin,generic.DetailView):
|
class ResitelView(LoginRequiredMixin,generic.DetailView):
|
||||||
model = s.Resitel
|
model = m.Resitel
|
||||||
template_name = 'personalni/profil/resitel.html'
|
template_name = 'personalni/profil/resitel.html'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
print(self.request.user)
|
print(self.request.user)
|
||||||
return s.Resitel.objects.get(osoba__user=self.request.user)
|
return m.Resitel.objects.get(osoba__user=self.request.user)
|
||||||
|
|
||||||
### Formulare
|
### Formulare
|
||||||
|
|
||||||
|
@ -157,10 +161,10 @@ def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data):
|
||||||
|
|
||||||
@sensitive_post_parameters('jmeno', 'prijmeni', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'skola')
|
@sensitive_post_parameters('jmeno', 'prijmeni', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'skola')
|
||||||
def resitelEditView(request):
|
def resitelEditView(request):
|
||||||
err_logger = logging.getLogger('seminar.prihlaska.problem')
|
err_logger = logging.getLogger('personalni.prihlaska.problem')
|
||||||
## Načtení objektů Osoba a Resitel patřících k aktuálně přihlášenému uživateli
|
## Načtení objektů Osoba a Resitel patřících k aktuálně přihlášenému uživateli
|
||||||
u = request.user
|
u = request.user
|
||||||
osoba_edit = s.Osoba.objects.get(user=u)
|
osoba_edit = m.Osoba.objects.get(user=u)
|
||||||
if hasattr(osoba_edit,'resitel'):
|
if hasattr(osoba_edit,'resitel'):
|
||||||
resitel_edit = osoba_edit.resitel
|
resitel_edit = osoba_edit.resitel
|
||||||
else:
|
else:
|
||||||
|
@ -195,7 +199,7 @@ def resitelEditView(request):
|
||||||
## Změny v osobě
|
## Změny v osobě
|
||||||
fcd = form.cleaned_data
|
fcd = form.cleaned_data
|
||||||
form_hash = hash(frozenset(fcd.items()))
|
form_hash = hash(frozenset(fcd.items()))
|
||||||
form_logger = logging.getLogger('seminar.prihlaska.form')
|
form_logger = logging.getLogger('personalni.prihlaska.form')
|
||||||
form_logger.info("EDIT:" + str(fcd) + str(form_hash)) # TODO možná logovat jinak
|
form_logger.info("EDIT:" + str(fcd) + str(form_hash)) # TODO možná logovat jinak
|
||||||
osoba_edit.jmeno = fcd['jmeno']
|
osoba_edit.jmeno = fcd['jmeno']
|
||||||
osoba_edit.prijmeni = fcd['prijmeni']
|
osoba_edit.prijmeni = fcd['prijmeni']
|
||||||
|
@ -244,9 +248,9 @@ def resitelEditView(request):
|
||||||
|
|
||||||
@sensitive_post_parameters('jmeno', 'prijmeni', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'skola', 'jak_se_dozvedeli')
|
@sensitive_post_parameters('jmeno', 'prijmeni', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'skola', 'jak_se_dozvedeli')
|
||||||
def prihlaskaView(request):
|
def prihlaskaView(request):
|
||||||
generic_logger = logging.getLogger('seminar.prihlaska')
|
generic_logger = logging.getLogger('personalni.prihlaska')
|
||||||
err_logger = logging.getLogger('seminar.prihlaska.problem')
|
err_logger = logging.getLogger('personalni.prihlaska.problem')
|
||||||
form_logger = logging.getLogger('seminar.prihlaska.form')
|
form_logger = logging.getLogger('personalni.prihlaska.form')
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = PrihlaskaForm(request.POST)
|
form = PrihlaskaForm(request.POST)
|
||||||
# TODO vyresit, co se bude v jakych situacich zobrazovat
|
# TODO vyresit, co se bude v jakych situacich zobrazovat
|
||||||
|
@ -266,7 +270,7 @@ def prihlaskaView(request):
|
||||||
resitel_grp = Group.objects.filter(name__exact='resitel').first()
|
resitel_grp = Group.objects.filter(name__exact='resitel').first()
|
||||||
u.groups.add(resitel_grp)
|
u.groups.add(resitel_grp)
|
||||||
|
|
||||||
o = s.Osoba(
|
o = m.Osoba(
|
||||||
jmeno = fcd['jmeno'],
|
jmeno = fcd['jmeno'],
|
||||||
prijmeni = fcd['prijmeni'],
|
prijmeni = fcd['prijmeni'],
|
||||||
osloveni = fcd['osloveni'],
|
osloveni = fcd['osloveni'],
|
||||||
|
@ -328,7 +332,7 @@ def prihlaskaView(request):
|
||||||
if kolize.count() > 1: # Jednu z nich jsme právě uložili
|
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]}')
|
err_logger.warning(f'Zaregistrovala se osoba s kolizním jménem. ID osob: {[o.id for o in kolize]}')
|
||||||
|
|
||||||
r = s.Resitel(
|
r = m.Resitel(
|
||||||
prezdivka_resitele=fcd['prezdivka_resitele'] if fcd['prezdivka_resitele'] != "" else None,
|
prezdivka_resitele=fcd['prezdivka_resitele'] if fcd['prezdivka_resitele'] != "" else None,
|
||||||
rok_maturity = fcd['rok_maturity'],
|
rok_maturity = fcd['rok_maturity'],
|
||||||
zasilat = fcd['zasilat'],
|
zasilat = fcd['zasilat'],
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.safestring import mark_safe
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
|
|
||||||
from .models import Prednaska, Seznam, STAV_NAVRH
|
from .models import Prednaska, Seznam, STAV_NAVRH
|
||||||
from seminar.models import Soustredeni
|
from soustredeni.models import Soustredeni
|
||||||
|
|
||||||
|
|
||||||
class Seznam_PrednaskaInline(admin.TabularInline):
|
class Seznam_PrednaskaInline(admin.TabularInline):
|
||||||
|
|
|
@ -6,7 +6,8 @@ from django.db.models import Sum
|
||||||
from django.forms import Form
|
from django.forms import Form
|
||||||
|
|
||||||
from prednasky.models import Prednaska, Hlasovani, Seznam, STAV_NAVRH
|
from prednasky.models import Prednaska, Hlasovani, Seznam, STAV_NAVRH
|
||||||
from seminar.models import Soustredeni, Osoba
|
from soustredeni.models import Soustredeni
|
||||||
|
from personalni.models import Osoba
|
||||||
|
|
||||||
def newPrednaska(request):
|
def newPrednaska(request):
|
||||||
# hlasovani se vztahuje k nejnovejsimu soustredeni
|
# hlasovani se vztahuje k nejnovejsimu soustredeni
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
"""
|
"""
|
||||||
Zde bývalo vše. Teď tu zbývají všechny modely a části webu jako archiv,
|
Zde bývalo vše. Teď tu zbývají migrace.
|
||||||
přehled orgů, aktuální (k aktuálnímu číslu) věci, titulka a jak řešit.
|
A kód pro `import seminar.models as m` pro ./manage.py shell.
|
||||||
|
"""
|
||||||
Také je tu generování testovacích (lokálních) dat.
|
|
||||||
"""
|
|
||||||
|
|
|
@ -2,10 +2,11 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
import django_countries.fields
|
import django_countries.fields
|
||||||
import seminar.models
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
from odevzdavatko.models import generate_filename
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(serialize=False, primary_key=True)),
|
('id', models.AutoField(serialize=False, primary_key=True)),
|
||||||
('timestamp', models.DateTimeField(auto_now=True, verbose_name='vytvo\u0159eno')),
|
('timestamp', models.DateTimeField(auto_now=True, verbose_name='vytvo\u0159eno')),
|
||||||
('soubor', models.FileField(upload_to=seminar.models.generate_filename, verbose_name='soubor')),
|
('soubor', models.FileField(upload_to=generate_filename, verbose_name='soubor')),
|
||||||
('poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k p\u0159\xedloze \u0159e\u0161en\xed (plain text), nap\u0159. o p\u016fvodu', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
|
('poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k p\u0159\xedloze \u0159e\u0161en\xed (plain text), nap\u0159. o p\u016fvodu', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
|
|
@ -7,9 +7,12 @@ import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
import django_countries.fields
|
import django_countries.fields
|
||||||
import imagekit.models.fields
|
import imagekit.models.fields
|
||||||
import seminar.models
|
|
||||||
import taggit.managers
|
import taggit.managers
|
||||||
|
|
||||||
|
from soustredeni.models import generate_filename_konfera
|
||||||
|
from odevzdavatko.models import generate_filename
|
||||||
|
from tvorba.models import cislo_pdf_filename, cislo_png_filename
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from treenode.treelib import get_parent
|
from treenode.treelib import get_parent
|
||||||
|
@ -962,7 +965,7 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(primary_key=True, serialize=False)),
|
('id', models.AutoField(primary_key=True, serialize=False)),
|
||||||
('timestamp', models.DateTimeField(auto_now=True, verbose_name='vytvořeno')),
|
('timestamp', models.DateTimeField(auto_now=True, verbose_name='vytvořeno')),
|
||||||
('soubor', models.FileField(upload_to=seminar.models.generate_filename, verbose_name='soubor')),
|
('soubor', models.FileField(upload_to=generate_filename, verbose_name='soubor')),
|
||||||
('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k příloze řešení (plain text), např. o původu', verbose_name='neveřejná poznámka')),
|
('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k příloze řešení (plain text), např. o původu', verbose_name='neveřejná poznámka')),
|
||||||
('reseni', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='prilohy', to='seminar.Reseni', verbose_name='řešení')),
|
('reseni', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='prilohy', to='seminar.Reseni', verbose_name='řešení')),
|
||||||
],
|
],
|
||||||
|
@ -1284,7 +1287,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='pdf',
|
name='pdf',
|
||||||
field=models.FileField(blank=True, help_text='Pdf čísla, které si mohou řešitelé stáhnout', null=True, upload_to=seminar.models.cislo_pdf_filename, verbose_name='pdf'),
|
field=models.FileField(blank=True, help_text='Pdf čísla, které si mohou řešitelé stáhnout', null=True, upload_to=cislo_pdf_filename, verbose_name='pdf'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='problem',
|
model_name='problem',
|
||||||
|
@ -1361,8 +1364,8 @@ class Migration(migrations.Migration):
|
||||||
('abstrakt', models.TextField(blank=True, help_text='Abstrakt konfery tak, jak byl uveden ve sborníku', verbose_name='abstrakt')),
|
('abstrakt', models.TextField(blank=True, help_text='Abstrakt konfery tak, jak byl uveden ve sborníku', verbose_name='abstrakt')),
|
||||||
('org_poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka ke konfeře(plain text)', verbose_name='neveřejná poznámka')),
|
('org_poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka ke konfeře(plain text)', verbose_name='neveřejná poznámka')),
|
||||||
('typ_prezentace', models.CharField(choices=[(b'veletrh', 'Veletrh (postery)'), (b'prezentace', 'Prezentace (přednáška)')], default=b'veletrh', max_length=16, verbose_name='typ prezentace')),
|
('typ_prezentace', models.CharField(choices=[(b'veletrh', 'Veletrh (postery)'), (b'prezentace', 'Prezentace (přednáška)')], default=b'veletrh', max_length=16, verbose_name='typ prezentace')),
|
||||||
('prezentace', models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=seminar.models.generate_filename_konfera, verbose_name='prezentace')),
|
('prezentace', models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=generate_filename_konfera, verbose_name='prezentace')),
|
||||||
('materialy', models.FileField(help_text='Další materiály ke konfeře zabalené do jednoho souboru', upload_to=seminar.models.generate_filename_konfera, verbose_name='materialy')),
|
('materialy', models.FileField(help_text='Další materiály ke konfeře zabalené do jednoho souboru', upload_to=generate_filename_konfera, verbose_name='materialy')),
|
||||||
('organizator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='konfery', to='seminar.Organizator', verbose_name='organizátor')),
|
('organizator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='konfery', to='seminar.Organizator', verbose_name='organizátor')),
|
||||||
('soustredeni', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='konfery', to='seminar.Soustredeni', verbose_name='soustředění')),
|
('soustredeni', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='konfery', to='seminar.Soustredeni', verbose_name='soustředění')),
|
||||||
],
|
],
|
||||||
|
@ -1400,12 +1403,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='konfera',
|
model_name='konfera',
|
||||||
name='materialy',
|
name='materialy',
|
||||||
field=models.FileField(blank=True, help_text='Další materiály ke konfeře zabalené do jednoho souboru', upload_to=seminar.models.generate_filename_konfera, verbose_name='materialy'),
|
field=models.FileField(blank=True, help_text='Další materiály ke konfeře zabalené do jednoho souboru', upload_to=generate_filename_konfera, verbose_name='materialy'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='konfera',
|
model_name='konfera',
|
||||||
name='prezentace',
|
name='prezentace',
|
||||||
field=models.FileField(blank=True, help_text='Prezentace nebo fotka posteru', upload_to=seminar.models.generate_filename_konfera, verbose_name='prezentace'),
|
field=models.FileField(blank=True, help_text='Prezentace nebo fotka posteru', upload_to=generate_filename_konfera, verbose_name='prezentace'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='konfera',
|
model_name='konfera',
|
||||||
|
@ -2648,12 +2651,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='pdf',
|
name='pdf',
|
||||||
field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, upload_to=seminar.models.cislo_pdf_filename, verbose_name='pdf'),
|
field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, upload_to=cislo_pdf_filename, verbose_name='pdf'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='titulka_nahled',
|
name='titulka_nahled',
|
||||||
field=models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to=seminar.models.cislo_png_filename, verbose_name='Obrázek titulní strany'),
|
field=models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to=cislo_png_filename, verbose_name='Obrázek titulní strany'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='treenode',
|
model_name='treenode',
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import migrations
|
||||||
import django_countries.fields
|
|
||||||
import seminar.models
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
CREATE_VIEWS="""
|
CREATE_VIEWS="""
|
||||||
create view seminar_body_za_cislo as
|
create view seminar_body_za_cislo as
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import migrations
|
||||||
import django_countries.fields
|
|
||||||
import seminar.models
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
CREATE_VIEWS="""
|
CREATE_VIEWS="""
|
||||||
drop view seminar_body_k_cislu;
|
drop view seminar_body_k_cislu;
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import migrations
|
||||||
import django_countries.fields
|
|
||||||
import seminar.models
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
CREATE_VIEWS="""
|
CREATE_VIEWS="""
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
import seminar.models
|
from tvorba.models import cislo_pdf_filename
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='pdf',
|
name='pdf',
|
||||||
field=models.FileField(help_text='Pdf \u010d\xedsla, kter\xe9 si mohou \u0159e\u0161itel\xe9 st\xe1hnout', upload_to=seminar.models.cislo_pdf_filename, null=True, verbose_name='pdf'),
|
field=models.FileField(help_text='Pdf \u010d\xedsla, kter\xe9 si mohou \u0159e\u0161itel\xe9 st\xe1hnout', upload_to=cislo_pdf_filename, null=True, verbose_name='pdf'),
|
||||||
preserve_default=True,
|
preserve_default=True,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,7 +2,8 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
import django_countries.fields
|
import django_countries.fields
|
||||||
import seminar.models
|
|
||||||
|
from tvorba.models import cislo_pdf_filename
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -25,7 +26,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='pdf',
|
name='pdf',
|
||||||
field=models.FileField(help_text='Pdf \u010d\xedsla, kter\xe9 si mohou \u0159e\u0161itel\xe9 st\xe1hnout', upload_to=seminar.models.cislo_pdf_filename, null=True, verbose_name='pdf', blank=True),
|
field=models.FileField(help_text='Pdf \u010d\xedsla, kter\xe9 si mohou \u0159e\u0161itel\xe9 st\xe1hnout', upload_to=cislo_pdf_filename, null=True, verbose_name='pdf', blank=True),
|
||||||
preserve_default=True,
|
preserve_default=True,
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
|
|
|
@ -2,7 +2,8 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import seminar.models
|
|
||||||
|
from soustredeni.models import generate_filename_konfera
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -21,8 +22,8 @@ class Migration(migrations.Migration):
|
||||||
('abstrakt', models.TextField(help_text='Abstrakt konfery tak, jak byl uveden ve sborn\xedku', verbose_name='abstrakt', blank=True)),
|
('abstrakt', models.TextField(help_text='Abstrakt konfery tak, jak byl uveden ve sborn\xedku', verbose_name='abstrakt', blank=True)),
|
||||||
('org_poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka ke konfe\u0159e(plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
|
('org_poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka ke konfe\u0159e(plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
|
||||||
('typ_prezentace', models.CharField(default=b'veletrh', max_length=16, verbose_name='typ prezentace', choices=[(b'veletrh', 'Veletrh (postery)'), (b'prezentace', 'Prezentace (p\u0159edn\xe1\u0161ka)')])),
|
('typ_prezentace', models.CharField(default=b'veletrh', max_length=16, verbose_name='typ prezentace', choices=[(b'veletrh', 'Veletrh (postery)'), (b'prezentace', 'Prezentace (p\u0159edn\xe1\u0161ka)')])),
|
||||||
('prezentace', models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=seminar.models.generate_filename_konfera, verbose_name='prezentace')),
|
('prezentace', models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=generate_filename_konfera, verbose_name='prezentace')),
|
||||||
('materialy', models.FileField(help_text='Dal\u0161\xed materi\xe1ly ke konfe\u0159e zabalen\xe9 do jednoho souboru', upload_to=seminar.models.generate_filename_konfera, verbose_name='materialy')),
|
('materialy', models.FileField(help_text='Dal\u0161\xed materi\xe1ly ke konfe\u0159e zabalen\xe9 do jednoho souboru', upload_to=generate_filename_konfera, verbose_name='materialy')),
|
||||||
('organizator', models.ForeignKey(related_name='konfery', on_delete=django.db.models.deletion.SET_NULL, verbose_name='organiz\xe1tor', to='seminar.Organizator', null=True)),
|
('organizator', models.ForeignKey(related_name='konfery', on_delete=django.db.models.deletion.SET_NULL, verbose_name='organiz\xe1tor', to='seminar.Organizator', null=True)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import seminar.models
|
from soustredeni.models import generate_filename_konfera
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -15,12 +15,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='konfera',
|
model_name='konfera',
|
||||||
name='materialy',
|
name='materialy',
|
||||||
field=models.FileField(help_text='Dal\u0161\xed materi\xe1ly ke konfe\u0159e zabalen\xe9 do jednoho souboru', upload_to=seminar.models.generate_filename_konfera, verbose_name='materialy', blank=True),
|
field=models.FileField(help_text='Dal\u0161\xed materi\xe1ly ke konfe\u0159e zabalen\xe9 do jednoho souboru', upload_to=generate_filename_konfera, verbose_name='materialy', blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='konfera',
|
model_name='konfera',
|
||||||
name='prezentace',
|
name='prezentace',
|
||||||
field=models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=seminar.models.generate_filename_konfera, verbose_name='prezentace', blank=True),
|
field=models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=generate_filename_konfera, verbose_name='prezentace', blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='konfera',
|
model_name='konfera',
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Generated by Django 2.2.9 on 2020-04-08 20:21
|
# Generated by Django 2.2.9 on 2020-04-08 20:21
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import seminar.models
|
|
||||||
|
from tvorba.models import cislo_pdf_filename
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -19,6 +20,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='pdf',
|
name='pdf',
|
||||||
field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, upload_to=seminar.models.cislo_pdf_filename, verbose_name='pdf'),
|
field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, upload_to=cislo_pdf_filename, verbose_name='pdf'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Generated by Django 2.2.12 on 2020-05-06 17:51
|
# Generated by Django 2.2.12 on 2020-05-06 17:51
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import seminar.models
|
from tvorba.models import cislo_png_filename
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -14,6 +14,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='titulka_nahled',
|
name='titulka_nahled',
|
||||||
field=models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to=seminar.models.cislo_png_filename, verbose_name='Obrázek titulní strany'),
|
field=models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to=cislo_png_filename, verbose_name='Obrázek titulní strany'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Generated by Django 2.2.24 on 2021-11-29 22:54
|
# Generated by Django 2.2.24 on 2021-11-29 22:54
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import seminar.models.tvorba
|
import various.models
|
||||||
|
from tvorba.models import cislo_pdf_filename
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -14,6 +15,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='cislo',
|
model_name='cislo',
|
||||||
name='pdf',
|
name='pdf',
|
||||||
field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, storage=seminar.models.tvorba.OverwriteStorage(), upload_to=seminar.models.tvorba.cislo_pdf_filename, verbose_name='pdf'),
|
field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, storage=various.models.OverwriteStorage(), upload_to=cislo_pdf_filename, verbose_name='pdf'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import seminar.models as m
|
from tvorba.models import Deadline as mDeadline
|
||||||
|
|
||||||
|
|
||||||
def vytvor_deadliny(apps, schema_editor):
|
def vytvor_deadliny(apps, schema_editor):
|
||||||
|
@ -16,7 +16,7 @@ def vytvor_deadliny(apps, schema_editor):
|
||||||
if cislo.rocnik.rocnik < 26:
|
if cislo.rocnik.rocnik < 26:
|
||||||
Deadline.objects.create(
|
Deadline.objects.create(
|
||||||
cislo=cislo,
|
cislo=cislo,
|
||||||
typ=m.Deadline.TYP_CISLA,
|
typ=mDeadline.TYP_CISLA,
|
||||||
deadline=timezone.make_aware(datetime.datetime.combine(datetime.date(1994 + cislo.rocnik.rocnik, 6, int(cislo.poradi[0])), datetime.time.min)),
|
deadline=timezone.make_aware(datetime.datetime.combine(datetime.date(1994 + cislo.rocnik.rocnik, 6, int(cislo.poradi[0])), datetime.time.min)),
|
||||||
verejna_vysledkovka=cislo.verejna_vysledkovka,
|
verejna_vysledkovka=cislo.verejna_vysledkovka,
|
||||||
)
|
)
|
||||||
|
@ -33,24 +33,24 @@ def vytvor_deadliny(apps, schema_editor):
|
||||||
if cislo.datum_deadline_soustredeni and cislo.datum_deadline_soustredeni == cislo.datum_preddeadline:
|
if cislo.datum_deadline_soustredeni and cislo.datum_deadline_soustredeni == cislo.datum_preddeadline:
|
||||||
vytvor_deadline(
|
vytvor_deadline(
|
||||||
date=cislo.datum_deadline_soustredeni,
|
date=cislo.datum_deadline_soustredeni,
|
||||||
typ=m.Deadline.TYP_PRVNI_A_SOUS
|
typ=mDeadline.TYP_PRVNI_A_SOUS
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if cislo.datum_deadline_soustredeni:
|
if cislo.datum_deadline_soustredeni:
|
||||||
vytvor_deadline(
|
vytvor_deadline(
|
||||||
date=cislo.datum_deadline_soustredeni,
|
date=cislo.datum_deadline_soustredeni,
|
||||||
typ=m.Deadline.TYP_SOUS
|
typ=mDeadline.TYP_SOUS
|
||||||
)
|
)
|
||||||
if cislo.datum_preddeadline:
|
if cislo.datum_preddeadline:
|
||||||
vytvor_deadline(
|
vytvor_deadline(
|
||||||
date=cislo.datum_preddeadline,
|
date=cislo.datum_preddeadline,
|
||||||
typ=m.Deadline.TYP_PRVNI
|
typ=mDeadline.TYP_PRVNI
|
||||||
)
|
)
|
||||||
|
|
||||||
if cislo.datum_deadline:
|
if cislo.datum_deadline:
|
||||||
vytvor_deadline(
|
vytvor_deadline(
|
||||||
date=cislo.datum_deadline,
|
date=cislo.datum_deadline,
|
||||||
typ=m.Deadline.TYP_CISLA
|
typ=mDeadline.TYP_CISLA
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Generated by Django 3.2.15 on 2022-10-09 10:14
|
# Generated by Django 3.2.15 on 2022-10-09 10:14
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
from seminar.models import Deadline
|
from tvorba.models import Deadline
|
||||||
|
|
||||||
|
|
||||||
def vrat_deadliny(apps, schema_editor):
|
def vrat_deadliny(apps, schema_editor):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Generated by Django 3.2.15 on 2022-10-09 11:04
|
# Generated by Django 3.2.15 on 2022-10-09 11:04
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
from seminar.models import Deadline
|
from tvorba.models import Deadline
|
||||||
|
|
||||||
|
|
||||||
def vrat_verejnost(apps, schema_editor):
|
def vrat_verejnost(apps, schema_editor):
|
||||||
|
|
15
seminar/models.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Tento soubor slouží pouze pro shell a podobné. Nikde neimportovat v kódu!
|
||||||
|
|
||||||
|
print("Naimportoval jsi `seminar.models`. Pevně věřím, že to nebylo nikde v kódu. Díky.")
|
||||||
|
|
||||||
|
from galerie.models import *
|
||||||
|
from header_fotky.models import *
|
||||||
|
from korektury.models import *
|
||||||
|
from novinky.models import *
|
||||||
|
from odevzdavatko.models import *
|
||||||
|
from personalni.models import *
|
||||||
|
from prednasky.models import *
|
||||||
|
from soustredeni.models import *
|
||||||
|
from treenode.models import *
|
||||||
|
from tvorba.models import *
|
||||||
|
from various.models import *
|
|
@ -1,21 +0,0 @@
|
||||||
from .tvorba import *
|
|
||||||
from .base import *
|
|
||||||
|
|
||||||
from various.models import Nastaveni
|
|
||||||
from personalni.models import Organizator, Resitel, Skola, Prijemce, Osoba
|
|
||||||
from soustredeni.models import Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Konfera, Konfery_Ucastnici
|
|
||||||
from novinky.models import Novinky
|
|
||||||
from odevzdavatko.models import Reseni, PrilohaReseni, Reseni_Resitele, Hodnoceni
|
|
||||||
from tvorba.models import ZmrazenaVysledkovka, Deadline, Cislo, Rocnik, Pohadka, Tema, Problem, Problemy_Opravovatele, Uloha, Clanek
|
|
||||||
from treenode.models import UlohaVzorakNode, UlohaZadaniNode, CisloNode, TemaVCisleNode, OrgTextNode, Obrazek, RocnikNode, PohadkaNode, TextNode, MezicisloNode, ReseniNode, CastNode, Text, TreeNode
|
|
||||||
|
|
||||||
# Kvůli migr. 0041
|
|
||||||
from soustredeni.models import generate_filename_konfera
|
|
||||||
# migr. 0001
|
|
||||||
from odevzdavatko.models import generate_filename
|
|
||||||
# migr. 0031, 0032, 0081
|
|
||||||
from tvorba.models import cislo_pdf_filename
|
|
||||||
# migr. 0082
|
|
||||||
from tvorba.models import cislo_png_filename
|
|
||||||
# migr 0100 (hack)
|
|
||||||
import tvorba.models as tvorba
|
|
|
@ -1,23 +0,0 @@
|
||||||
from django.urls import reverse
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class SeminarModelBase(models.Model):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
def verejne(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# def get_absolute_url(self):
|
|
||||||
# return "https://" + str(get_current_site(None)) + self.verejne_url()
|
|
||||||
|
|
||||||
def admin_url(self):
|
|
||||||
app_name = self._meta.app_label
|
|
||||||
model_name = self._meta.model_name
|
|
||||||
return reverse('admin:{}_{}_change'.format(app_name, model_name), args=(self.id, ))
|
|
||||||
|
|
||||||
# def verejne_url(self):
|
|
||||||
# return None
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from django.core.files.storage import FileSystemStorage
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class OverwriteStorage(FileSystemStorage):
|
|
||||||
""" Varianta FileSystemStorage, která v případě, že soubor cílového
|
|
||||||
jména již existuje, ho smaže a místo něj uloží soubor nový"""
|
|
||||||
def get_available_name(self,name, max_length=None):
|
|
||||||
if self.exists(name):
|
|
||||||
os.remove(os.path.join(self.location,name))
|
|
||||||
return super().get_available_name(name,max_length)
|
|
|
@ -9,8 +9,8 @@ from django.conf import settings
|
||||||
|
|
||||||
from personalni.models import Resitel, Organizator
|
from personalni.models import Resitel, Organizator
|
||||||
|
|
||||||
from seminar.models.base import SeminarModelBase
|
from various.models import SeminarModelBase
|
||||||
import tvorba.models as am
|
from tvorba.models import Rocnik, Problem, aux_generate_filename
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class Soustredeni(SeminarModelBase):
|
||||||
# Interní ID
|
# Interní ID
|
||||||
id = models.AutoField(primary_key = True)
|
id = models.AutoField(primary_key = True)
|
||||||
|
|
||||||
rocnik = models.ForeignKey(am.Rocnik, verbose_name='ročník', related_name='soustredeni',
|
rocnik = models.ForeignKey(Rocnik, verbose_name='ročník', related_name='soustredeni',
|
||||||
on_delete=models.PROTECT)
|
on_delete=models.PROTECT)
|
||||||
|
|
||||||
datum_zacatku = models.DateField('datum začátku', blank=True, null=True,
|
datum_zacatku = models.DateField('datum začátku', blank=True, null=True,
|
||||||
|
@ -75,7 +75,7 @@ class Soustredeni(SeminarModelBase):
|
||||||
|
|
||||||
def verejne_url(self):
|
def verejne_url(self):
|
||||||
#return reverse('seminar_soustredeni', kwargs={'pk': self.id})
|
#return reverse('seminar_soustredeni', kwargs={'pk': self.id})
|
||||||
return reverse('seminar_seznam_soustredeni')
|
return reverse('soustredeni_seznam')
|
||||||
|
|
||||||
|
|
||||||
@reversion.register(ignore_duplicates=True)
|
@reversion.register(ignore_duplicates=True)
|
||||||
|
@ -143,13 +143,13 @@ class Soustredeni_Organizatori(SeminarModelBase):
|
||||||
def generate_filename_konfera(self, filename):
|
def generate_filename_konfera(self, filename):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
settings.SEMINAR_KONFERY_DIR,
|
settings.SEMINAR_KONFERY_DIR,
|
||||||
am.aux_generate_filename(self, filename)
|
aux_generate_filename(self, filename)
|
||||||
)
|
)
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
||||||
@reversion.register(ignore_duplicates=True)
|
@reversion.register(ignore_duplicates=True)
|
||||||
class Konfera(am.Problem):
|
class Konfera(Problem):
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'seminar_konfera'
|
db_table = 'seminar_konfera'
|
||||||
verbose_name = 'Konfera'
|
verbose_name = 'Konfera'
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<div class="mam-org-only">
|
<div class="mam-org-only">
|
||||||
<a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a><br>
|
<a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a><br>
|
||||||
<a href="../{{soustredeni.pk}}/obalky.pdf">Vygenerovat obálky pro účastníky</a><br>
|
<a href="../{{soustredeni.pk}}/obalky.pdf">Vygenerovat obálky pro účastníky</a><br>
|
||||||
<a href={% url 'seminar_soustredeni_abstrakty' soustredeni.pk %}>Vygenerovat účastníky a vedoucí do abstraktů</a><br>
|
<a href={% url 'soustredeni_abstrakty' soustredeni.pk %}>Vygenerovat účastníky a vedoucí do abstraktů</a><br>
|
||||||
Seznam účastníků -
|
Seznam účastníků -
|
||||||
<a href="../{{soustredeni.pk}}/seznam_ucastniku">HTML tabulka pro tisk</a>,
|
<a href="../{{soustredeni.pk}}/seznam_ucastniku">HTML tabulka pro tisk</a>,
|
||||||
<a href="../{{soustredeni.pk}}/export_ucastniku">CSV</a>,
|
<a href="../{{soustredeni.pk}}/export_ucastniku">CSV</a>,
|
||||||
|
|
|
@ -6,7 +6,7 @@ from typing import Sequence
|
||||||
import lorem
|
import lorem
|
||||||
|
|
||||||
from .models import Soustredeni, Konfera
|
from .models import Soustredeni, Konfera
|
||||||
import seminar.models as am # tvorba
|
from tvorba.models import Rocnik
|
||||||
import personalni.models as pm
|
import personalni.models as pm
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -25,7 +25,7 @@ def gen_soustredeni(
|
||||||
for _ in range(1, 10): # FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?)
|
for _ in range(1, 10): # FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?)
|
||||||
datum_zacatku = datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28))
|
datum_zacatku = datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28))
|
||||||
working_sous = Soustredeni.objects.create(
|
working_sous = Soustredeni.objects.create(
|
||||||
rocnik=am.Rocnik.objects.order_by('?').first(),
|
rocnik=Rocnik.objects.order_by('?').first(),
|
||||||
verejne_db=rnd.choice([True, False]),
|
verejne_db=rnd.choice([True, False]),
|
||||||
misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']),
|
misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']),
|
||||||
typ=rnd.choice(['jarni', 'podzimni', 'vikend']),
|
typ=rnd.choice(['jarni', 'podzimni', 'vikend']),
|
||||||
|
|
|
@ -7,7 +7,7 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'probehlo/',
|
'probehlo/',
|
||||||
views.SoustredeniListView.as_view(),
|
views.SoustredeniListView.as_view(),
|
||||||
name='seminar_seznam_soustredeni'
|
name='soustredeni_seznam'
|
||||||
zelvuska marked this conversation as resolved
ledoian
commented
Review
```
$ git grep probehlo
data/sitetree.json: "url": "soustredeni_probehlo",
personalni/templates/personalni/profil/orgorozcestnik.html: <li><a href="{% url 'soustredeni_probehlo' %}">proběhlá soustředění</a>
```
|
|||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'<int:soustredeni>/',
|
'<int:soustredeni>/',
|
||||||
|
@ -37,12 +37,12 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'obalky.pdf',
|
'obalky.pdf',
|
||||||
org_required(views.soustredeniObalkyView),
|
org_required(views.soustredeniObalkyView),
|
||||||
name='seminar_soustredeni_obalky'
|
name='soustredeni_obalky'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'abstrakty',
|
'abstrakty',
|
||||||
org_required(views.SoustredeniAbstraktyView.as_view()),
|
org_required(views.SoustredeniAbstraktyView.as_view()),
|
||||||
name='seminar_soustredeni_abstrakty'
|
name='soustredeni_abstrakty'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'fotogalerie/',
|
'fotogalerie/',
|
||||||
|
|
|
@ -4,25 +4,27 @@ from django.forms import widgets
|
||||||
|
|
||||||
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
|
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
|
||||||
|
|
||||||
import seminar.models as m
|
from .models import TreeNode, RocnikNode, CisloNode, MezicisloNode, TemaVCisleNode, UlohaZadaniNode, PohadkaNode, UlohaVzorakNode, TextNode, CastNode, OrgTextNode, ReseniNode
|
||||||
|
from .models import Text, Obrazek
|
||||||
|
|
||||||
# Polymorfismus pro stromy
|
# Polymorfismus pro stromy
|
||||||
# TODO: Inlines podle https://django-polymorphic.readthedocs.io/en/stable/admin.html
|
# TODO: Inlines podle https://django-polymorphic.readthedocs.io/en/stable/admin.html
|
||||||
|
|
||||||
@admin.register(m.TreeNode)
|
@admin.register(TreeNode)
|
||||||
class TreeNodeAdmin(PolymorphicParentModelAdmin):
|
class TreeNodeAdmin(PolymorphicParentModelAdmin):
|
||||||
base_model = m.TreeNode
|
base_model = TreeNode
|
||||||
child_models = [
|
child_models = [
|
||||||
m.RocnikNode,
|
RocnikNode,
|
||||||
m.CisloNode,
|
CisloNode,
|
||||||
m.MezicisloNode,
|
MezicisloNode,
|
||||||
m.TemaVCisleNode,
|
TemaVCisleNode,
|
||||||
m.UlohaZadaniNode,
|
UlohaZadaniNode,
|
||||||
m.PohadkaNode,
|
PohadkaNode,
|
||||||
m.UlohaVzorakNode,
|
UlohaVzorakNode,
|
||||||
m.TextNode,
|
TextNode,
|
||||||
m.CastNode,
|
CastNode,
|
||||||
m.OrgTextNode,
|
OrgTextNode,
|
||||||
zelvuska marked this conversation as resolved
ledoian
commented
Já vím, že chybělo už předtím, ale chybí tu Já vím, že chybělo už předtím, ale chybí tu `ReseniNode`. (i později v deklaracích jednotlivých adminů)
|
|||||||
|
ReseniNode,
|
||||||
]
|
]
|
||||||
|
|
||||||
actions = ['aktualizuj_nazvy']
|
actions = ['aktualizuj_nazvy']
|
||||||
|
@ -36,64 +38,68 @@ class TreeNodeAdmin(PolymorphicParentModelAdmin):
|
||||||
self.message_user(request, "Názvy aktualizovány.")
|
self.message_user(request, "Názvy aktualizovány.")
|
||||||
aktualizuj_nazvy.short_description = "Aktualizuj vybraným TreeNodům názvy"
|
aktualizuj_nazvy.short_description = "Aktualizuj vybraným TreeNodům názvy"
|
||||||
|
|
||||||
@admin.register(m.RocnikNode)
|
@admin.register(RocnikNode)
|
||||||
class RocnikNodeAdmin(PolymorphicChildModelAdmin):
|
class RocnikNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.RocnikNode
|
base_model = RocnikNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.CisloNode)
|
@admin.register(CisloNode)
|
||||||
class CisloNodeAdmin(PolymorphicChildModelAdmin):
|
class CisloNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.CisloNode
|
base_model = CisloNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.MezicisloNode)
|
@admin.register(MezicisloNode)
|
||||||
class MezicisloNodeAdmin(PolymorphicChildModelAdmin):
|
class MezicisloNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.MezicisloNode
|
base_model = MezicisloNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.TemaVCisleNode)
|
@admin.register(TemaVCisleNode)
|
||||||
class TemaVCisleNodeAdmin(PolymorphicChildModelAdmin):
|
class TemaVCisleNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.TemaVCisleNode
|
base_model = TemaVCisleNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.UlohaZadaniNode)
|
@admin.register(UlohaZadaniNode)
|
||||||
class UlohaZadaniNodeAdmin(PolymorphicChildModelAdmin):
|
class UlohaZadaniNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.UlohaZadaniNode
|
base_model = UlohaZadaniNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.PohadkaNode)
|
@admin.register(PohadkaNode)
|
||||||
class PohadkaNodeAdmin(PolymorphicChildModelAdmin):
|
class PohadkaNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.PohadkaNode
|
base_model = PohadkaNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.UlohaVzorakNode)
|
@admin.register(UlohaVzorakNode)
|
||||||
class UlohaVzorakNodeAdmin(PolymorphicChildModelAdmin):
|
class UlohaVzorakNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.UlohaVzorakNode
|
base_model = UlohaVzorakNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.TextNode)
|
@admin.register(TextNode)
|
||||||
class TextNodeAdmin(PolymorphicChildModelAdmin):
|
class TextNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.TextNode
|
base_model = TextNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
@admin.register(m.CastNode)
|
@admin.register(CastNode)
|
||||||
class TextNodeAdmin(PolymorphicChildModelAdmin):
|
class TextNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.CastNode
|
base_model = CastNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
fields = ('nadpis',)
|
fields = ('nadpis',)
|
||||||
|
|
||||||
@admin.register(m.OrgTextNode)
|
@admin.register(OrgTextNode)
|
||||||
class TextNodeAdmin(PolymorphicChildModelAdmin):
|
class TextNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
base_model = m.OrgTextNode
|
base_model = OrgTextNode
|
||||||
show_in_index = True
|
show_in_index = True
|
||||||
|
|
||||||
|
@admin.register(ReseniNode)
|
||||||
|
class ReseniNodeAdmin(PolymorphicChildModelAdmin):
|
||||||
|
base_model = ReseniNode
|
||||||
|
show_in_index = True
|
||||||
|
|
||||||
class TextAdminInline(admin.TabularInline):
|
class TextAdminInline(admin.TabularInline):
|
||||||
model = m.Text
|
model = Text
|
||||||
formfield_overrides = {
|
formfield_overrides = {
|
||||||
models.TextField: {'widget': widgets.TextInput}
|
models.TextField: {'widget': widgets.TextInput}
|
||||||
}
|
}
|
||||||
exclude = ['text_zkraceny_set', 'text_zkraceny']
|
exclude = ['text_zkraceny_set', 'text_zkraceny']
|
||||||
|
|
||||||
admin.site.register(m.Text)
|
admin.site.register(Text)
|
||||||
admin.site.register(m.Obrazek)
|
admin.site.register(Obrazek)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
import seminar.models as m
|
from .models import Obrazek
|
||||||
|
|
||||||
# pro přidání políčka do formuláře je potřeba
|
# pro přidání políčka do formuláře je potřeba
|
||||||
# - mít v modelu tu položku, kterou chci upravovat
|
# - mít v modelu tu položku, kterou chci upravovat
|
||||||
|
@ -10,5 +10,5 @@ import seminar.models as m
|
||||||
|
|
||||||
class NahrajObrazekKTreeNoduForm(forms.ModelForm):
|
class NahrajObrazekKTreeNoduForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Obrazek
|
model = Obrazek
|
||||||
fields = ('na_web',)
|
fields = ('na_web',)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from unidecode import unidecode # Používám pro získání ID odkazu (ještě
|
||||||
|
|
||||||
from polymorphic.models import PolymorphicModel
|
from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
from seminar.models import SeminarModelBase
|
from various.models import SeminarModelBase
|
||||||
|
|
||||||
from personalni.models import Organizator
|
from personalni.models import Organizator
|
||||||
from odevzdavatko.models import Reseni
|
from odevzdavatko.models import Reseni
|
||||||
|
@ -347,4 +347,3 @@ class Obrazek(SeminarModelBase):
|
||||||
|
|
||||||
# TODO placement hint - chci ho tady / pred textem / za textem
|
# TODO placement hint - chci ho tady / pred textem / za textem
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_polymorphic.serializers import PolymorphicSerializer
|
from rest_polymorphic.serializers import PolymorphicSerializer
|
||||||
|
|
||||||
import seminar.models as m
|
from odevzdavatko.models import Reseni
|
||||||
|
from tvorba.models import Problem, Uloha
|
||||||
|
|
||||||
|
from .models import RocnikNode, CisloNode, MezicisloNode, TemaVCisleNode, OrgTextNode, PohadkaNode, TextNode, TreeNode, CastNode, UlohaZadaniNode, UlohaVzorakNode, ReseniNode
|
||||||
|
from .models import Text
|
||||||
from treenode import treelib
|
from treenode import treelib
|
||||||
|
|
||||||
DEFAULT_NODE_DEPTH = 2
|
DEFAULT_NODE_DEPTH = 2
|
||||||
|
@ -9,57 +13,57 @@ DEFAULT_NODE_DEPTH = 2
|
||||||
|
|
||||||
class TextSerializer(serializers.ModelSerializer):
|
class TextSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Text
|
model = Text
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class ProblemSerializer(serializers.ModelSerializer):
|
class ProblemSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Problem
|
model = Problem
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class UlohaSerializer(serializers.ModelSerializer):
|
class UlohaSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Uloha
|
model = Uloha
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class ReseniSerializer(serializers.ModelSerializer):
|
class ReseniSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.Reseni
|
model = Reseni
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class RocnikNodeSerializer(serializers.ModelSerializer):
|
class RocnikNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.RocnikNode
|
model = RocnikNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class CisloNodeSerializer(serializers.ModelSerializer):
|
class CisloNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.CisloNode
|
model = CisloNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class MezicisloNodeSerializer(serializers.ModelSerializer):
|
class MezicisloNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.MezicisloNode
|
model = MezicisloNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class TemaVCisleNodeSerializer(serializers.ModelSerializer):
|
class TemaVCisleNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.TemaVCisleNode
|
model = TemaVCisleNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class OrgTextNodeSerializer(serializers.ModelSerializer):
|
class OrgTextNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.OrgTextNode
|
model = OrgTextNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class PohadkaNodeSerializer(serializers.ModelSerializer):
|
class PohadkaNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.PohadkaNode
|
model = PohadkaNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -67,7 +71,7 @@ class TextNodeSerializer(serializers.ModelSerializer):
|
||||||
text = TextSerializer()
|
text = TextSerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.TextNode
|
model = TextNode
|
||||||
fields = ('id','text','polymorphic_ctype')
|
fields = ('id','text','polymorphic_ctype')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -80,7 +84,7 @@ class TextNodeWriteSerializer(serializers.ModelSerializer):
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.TextNode
|
model = TextNode
|
||||||
fields = ('id','text')
|
fields = ('id','text')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -93,26 +97,26 @@ class TextNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
temp_text = validated_data.pop('text')
|
temp_text = validated_data.pop('text')
|
||||||
where = validated_data.pop('where')
|
where = validated_data.pop('where')
|
||||||
refnode_id = validated_data.pop('refnode')
|
refnode_id = validated_data.pop('refnode')
|
||||||
refnode = m.TreeNode.objects.get(pk=refnode_id)
|
refnode = TreeNode.objects.get(pk=refnode_id)
|
||||||
text = m.Text.objects.create(**temp_text)
|
text = Text.objects.create(**temp_text)
|
||||||
if where == 'syn':
|
if where == 'syn':
|
||||||
node = treelib.create_child(refnode,m.TextNode,text=text)
|
node = treelib.create_child(refnode,TextNode,text=text)
|
||||||
elif where == 'za':
|
elif where == 'za':
|
||||||
node = treelib.create_node_after(refnode,m.TextNode,text=text)
|
node = treelib.create_node_after(refnode,TextNode,text=text)
|
||||||
elif where == 'pred':
|
elif where == 'pred':
|
||||||
node = treelib.create_node_before(refnode,m.TextNode,text=text)
|
node = treelib.create_node_before(refnode,TextNode,text=text)
|
||||||
node.where = None
|
node.where = None
|
||||||
node.refnode = None
|
node.refnode = None
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.TextNode
|
model = TextNode
|
||||||
fields = ('text','where','refnode')
|
fields = ('text','where','refnode')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class CastNodeSerializer(serializers.ModelSerializer):
|
class CastNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.CastNode
|
model = CastNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -124,25 +128,25 @@ class CastNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
temp_nadpis = validated_data.pop('nadpis')
|
temp_nadpis = validated_data.pop('nadpis')
|
||||||
where = validated_data.pop('where')
|
where = validated_data.pop('where')
|
||||||
refnode_id = validated_data.pop('refnode')
|
refnode_id = validated_data.pop('refnode')
|
||||||
refnode = m.TreeNode.objects.get(pk=refnode_id)
|
refnode = TreeNode.objects.get(pk=refnode_id)
|
||||||
if where == 'syn':
|
if where == 'syn':
|
||||||
node = treelib.create_child(refnode,m.CastNode,nadpis=temp_nadpis)
|
node = treelib.create_child(refnode,CastNode,nadpis=temp_nadpis)
|
||||||
elif where == 'za':
|
elif where == 'za':
|
||||||
node = treelib.create_node_after(refnode,m.CastNode,nadpis=temp_nadpis)
|
node = treelib.create_node_after(refnode,CastNode,nadpis=temp_nadpis)
|
||||||
elif where == 'pred':
|
elif where == 'pred':
|
||||||
node = treelib.create_node_before(refnode,m.CastNode,nadpis=temp_nadpis)
|
node = treelib.create_node_before(refnode,CastNode,nadpis=temp_nadpis)
|
||||||
node.where = None
|
node.where = None
|
||||||
node.refnode = None
|
node.refnode = None
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.CastNode
|
model = CastNode
|
||||||
fields = ('nadpis','where','refnode')
|
fields = ('nadpis','where','refnode')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class UlohaZadaniNodeSerializer(serializers.ModelSerializer):
|
class UlohaZadaniNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.UlohaZadaniNode
|
model = UlohaZadaniNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -157,7 +161,7 @@ class UlohaZadaniNodeWriteSerializer(serializers.ModelSerializer):
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.TextNode
|
model = TextNode
|
||||||
fields = ('id','uloha')
|
fields = ('id','uloha')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -171,28 +175,28 @@ class UlohaZadaniNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
temp_uloha = validated_data.pop('uloha')
|
temp_uloha = validated_data.pop('uloha')
|
||||||
where = validated_data.pop('where')
|
where = validated_data.pop('where')
|
||||||
refnode_id = validated_data.pop('refnode')
|
refnode_id = validated_data.pop('refnode')
|
||||||
refnode = m.TreeNode.objects.get(pk=refnode_id)
|
refnode = TreeNode.objects.get(pk=refnode_id)
|
||||||
|
|
||||||
# Z cesty ke koreni stromu zjistime, v jakem jsme tematu a v jakem cisle
|
# Z cesty ke koreni stromu zjistime, v jakem jsme tematu a v jakem cisle
|
||||||
cislo = None
|
cislo = None
|
||||||
tema = None
|
tema = None
|
||||||
travelnode = refnode
|
travelnode = refnode
|
||||||
while travelnode is not None:
|
while travelnode is not None:
|
||||||
if isinstance(travelnode, m.TemaVCisleNode):
|
if isinstance(travelnode, TemaVCisleNode):
|
||||||
tema = travelnode.tema
|
tema = travelnode.tema
|
||||||
if isinstance(travelnode, m.CisloNode):
|
if isinstance(travelnode, CisloNode):
|
||||||
cislo = travelnode.cislo
|
cislo = travelnode.cislo
|
||||||
travelnode = treelib.get_parent(travelnode)
|
travelnode = treelib.get_parent(travelnode)
|
||||||
# Vyrobime ulohu
|
# Vyrobime ulohu
|
||||||
uloha = m.Uloha.objects.create(cislo_zadani=cislo, nadproblem = tema, **temp_uloha)
|
uloha = Uloha.objects.create(cislo_zadani=cislo, nadproblem = tema, **temp_uloha)
|
||||||
|
|
||||||
# A vyrobime UlohaZadaniNode
|
# A vyrobime UlohaZadaniNode
|
||||||
if where == 'syn':
|
if where == 'syn':
|
||||||
node = treelib.create_child(refnode,m.UlohaZadaniNode,uloha = uloha)
|
node = treelib.create_child(refnode,UlohaZadaniNode,uloha = uloha)
|
||||||
elif where == 'za':
|
elif where == 'za':
|
||||||
node = treelib.create_node_after(refnode,m.UlohaZadaniNode,uloha = uloha)
|
node = treelib.create_node_after(refnode,UlohaZadaniNode,uloha = uloha)
|
||||||
elif where == 'pred':
|
elif where == 'pred':
|
||||||
node = treelib.create_node_before(refnode,m.UlohaZadaniNode,uloha = uloha)
|
node = treelib.create_node_before(refnode,UlohaZadaniNode,uloha = uloha)
|
||||||
node.where = None
|
node.where = None
|
||||||
node.refnode = None
|
node.refnode = None
|
||||||
node.max_body = None
|
node.max_body = None
|
||||||
|
@ -200,21 +204,21 @@ class UlohaZadaniNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.UlohaZadaniNode
|
model = UlohaZadaniNode
|
||||||
fields = ('uloha','where','refnode')
|
fields = ('uloha','where','refnode')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class UlohaVzorakNodeSerializer(serializers.ModelSerializer):
|
class UlohaVzorakNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.UlohaVzorakNode
|
model = UlohaVzorakNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class UlohaVzorakNodeWriteSerializer(serializers.ModelSerializer):
|
class UlohaVzorakNodeWriteSerializer(serializers.ModelSerializer):
|
||||||
uloha = serializers.PrimaryKeyRelatedField(queryset=m.Uloha.objects.all(), many=False, read_only=False)
|
uloha = serializers.PrimaryKeyRelatedField(queryset=Uloha.objects.all(), many=False, read_only=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.UlohaVzorakNode
|
model = UlohaVzorakNode
|
||||||
fields = ('id','uloha')
|
fields = ('id','uloha')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -226,17 +230,17 @@ class UlohaVzorakNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
uloha_id = validated_data.pop('uloha_id')
|
uloha_id = validated_data.pop('uloha_id')
|
||||||
uloha = m.Uloha.objects.get(pk=uloha_id)
|
uloha = Uloha.objects.get(pk=uloha_id)
|
||||||
where = validated_data.pop('where')
|
where = validated_data.pop('where')
|
||||||
refnode_id = validated_data.pop('refnode')
|
refnode_id = validated_data.pop('refnode')
|
||||||
refnode = m.TreeNode.objects.get(pk=refnode_id)
|
refnode = TreeNode.objects.get(pk=refnode_id)
|
||||||
|
|
||||||
if where == 'syn':
|
if where == 'syn':
|
||||||
node = treelib.create_child(refnode,m.UlohaVzorakNode,uloha = uloha)
|
node = treelib.create_child(refnode,UlohaVzorakNode,uloha = uloha)
|
||||||
elif where == 'za':
|
elif where == 'za':
|
||||||
node = treelib.create_node_after(refnode,m.UlohaVzorakNode,uloha = uloha)
|
node = treelib.create_node_after(refnode,UlohaVzorakNode,uloha = uloha)
|
||||||
elif where == 'pred':
|
elif where == 'pred':
|
||||||
node = treelib.create_node_before(refnode,m.UlohaVzorakNode,uloha = uloha)
|
node = treelib.create_node_before(refnode,UlohaVzorakNode,uloha = uloha)
|
||||||
node.refnode = None
|
node.refnode = None
|
||||||
node.where = None
|
node.where = None
|
||||||
node.uloha_id = None
|
node.uloha_id = None
|
||||||
|
@ -244,7 +248,7 @@ class UlohaVzorakNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.UlohaVzorakNode
|
model = UlohaVzorakNode
|
||||||
fields = ('refnode', 'uloha_id', 'where')
|
fields = ('refnode', 'uloha_id', 'where')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -253,15 +257,15 @@ class UlohaVzorakNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class ReseniNodeSerializer(serializers.ModelSerializer):
|
class ReseniNodeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.ReseniNode
|
model = ReseniNode
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
class ReseniNodeWriteSerializer(serializers.ModelSerializer):
|
class ReseniNodeWriteSerializer(serializers.ModelSerializer):
|
||||||
reseni = serializers.PrimaryKeyRelatedField(queryset=m.Reseni.objects.all(), many=False, read_only=False)
|
reseni = serializers.PrimaryKeyRelatedField(queryset=Reseni.objects.all(), many=False, read_only=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.ReseniNode
|
model = ReseniNode
|
||||||
fields = ('id','reseni')
|
fields = ('id','reseni')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
@ -273,41 +277,41 @@ class ReseniNodeCreateSerializer(serializers.ModelSerializer):
|
||||||
def create(self,validated_data):
|
def create(self,validated_data):
|
||||||
# text_zadani = validated_data.pop('text_zadani')
|
# text_zadani = validated_data.pop('text_zadani')
|
||||||
reseni_id = validated_data.pop('reseni_id')
|
reseni_id = validated_data.pop('reseni_id')
|
||||||
reseni = m.Reseni.objects.get(pk=reseni_id)
|
reseni = Reseni.objects.get(pk=reseni_id)
|
||||||
where = validated_data.pop('where')
|
where = validated_data.pop('where')
|
||||||
refnode_id = validated_data.pop('refnode')
|
refnode_id = validated_data.pop('refnode')
|
||||||
refnode = m.TreeNode.objects.get(pk=refnode_id)
|
refnode = TreeNode.objects.get(pk=refnode_id)
|
||||||
|
|
||||||
# A vyrobime UlohaZadaniNode
|
# A vyrobime UlohaZadaniNode
|
||||||
if where == 'syn':
|
if where == 'syn':
|
||||||
node = treelib.create_child(refnode,m.ReseniNode,reseni = reseni)
|
node = treelib.create_child(refnode,ReseniNode,reseni = reseni)
|
||||||
elif where == 'za':
|
elif where == 'za':
|
||||||
node = treelib.create_node_after(refnode,m.ReseniNode,reseni = reseni)
|
node = treelib.create_node_after(refnode,ReseniNode,reseni = reseni)
|
||||||
elif where == 'pred':
|
elif where == 'pred':
|
||||||
node = treelib.create_node_before(refnode,m.ReseniNode,reseni = reseni)
|
node = treelib.create_node_before(refnode,ReseniNode,reseni = reseni)
|
||||||
node.where = None
|
node.where = None
|
||||||
node.refnode = None
|
node.refnode = None
|
||||||
node.reseni_id = None
|
node.reseni_id = None
|
||||||
return node
|
return node
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = m.ReseniNode
|
model = ReseniNode
|
||||||
fields = ('reseni_id','where','refnode')
|
fields = ('reseni_id','where','refnode')
|
||||||
depth = DEFAULT_NODE_DEPTH
|
depth = DEFAULT_NODE_DEPTH
|
||||||
|
|
||||||
|
|
||||||
class TreeNodeSerializer(PolymorphicSerializer):
|
class TreeNodeSerializer(PolymorphicSerializer):
|
||||||
model_serializer_mapping = {
|
model_serializer_mapping = {
|
||||||
m.RocnikNode: RocnikNodeSerializer,
|
RocnikNode: RocnikNodeSerializer,
|
||||||
m.CisloNode: CisloNodeSerializer,
|
CisloNode: CisloNodeSerializer,
|
||||||
m.MezicisloNode: MezicisloNodeSerializer,
|
MezicisloNode: MezicisloNodeSerializer,
|
||||||
m.TemaVCisleNode: TemaVCisleNodeSerializer,
|
TemaVCisleNode: TemaVCisleNodeSerializer,
|
||||||
m.OrgTextNode: OrgTextNodeSerializer,
|
OrgTextNode: OrgTextNodeSerializer,
|
||||||
m.UlohaZadaniNode: UlohaZadaniNodeSerializer,
|
UlohaZadaniNode: UlohaZadaniNodeSerializer,
|
||||||
m.UlohaVzorakNode: UlohaVzorakNodeSerializer,
|
UlohaVzorakNode: UlohaVzorakNodeSerializer,
|
||||||
m.PohadkaNode: PohadkaNodeSerializer,
|
PohadkaNode: PohadkaNodeSerializer,
|
||||||
m.TextNode: TextNodeSerializer,
|
TextNode: TextNodeSerializer,
|
||||||
m.CastNode: CastNodeSerializer,
|
CastNode: CastNodeSerializer,
|
||||||
m.ReseniNode: ReseniNodeSerializer,
|
ReseniNode: ReseniNodeSerializer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,20 +25,20 @@
|
||||||
<button>Zvyš úroveň nadpisu</button> - nejsou testovací data
|
<button>Zvyš úroveň nadpisu</button> - nejsou testovací data
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% include "seminar/treenode_name.html" %}
|
{% include "treenode/treenode_name.html" %}
|
||||||
{%if obj.children %}
|
{%if obj.children %}
|
||||||
<div class="borderized children">
|
<div class="borderized children">
|
||||||
|
|
||||||
{% with kam="před" kam_slug="syn" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %}
|
{% with kam="před" kam_slug="syn" %} {% include "treenode/treenode_add_stub.html" %} {% endwith %}
|
||||||
{%for ch in obj.children %}
|
{%for ch in obj.children %}
|
||||||
|
|
||||||
{# ----------- Vypisujeme podstrom ----------#}
|
{# ----------- Vypisujeme podstrom ----------#}
|
||||||
{%with obj=ch depth=depth|add:"1" %} {%include "seminar/treenode_recursive.html" %} {%endwith%}
|
{%with obj=ch depth=depth|add:"1" %} {%include "treenode/treenode_recursive.html" %} {%endwith%}
|
||||||
{# ----------- Přidáváme mezi syny / za posledního -------- #}
|
{# ----------- Přidáváme mezi syny / za posledního -------- #}
|
||||||
{% if forloop.last %}
|
{% if forloop.last %}
|
||||||
{% with kam="za" kam_slug="za" obj=ch %} {% include "seminar/treenode_add_stub.html" %} {% endwith %}
|
{% with kam="za" kam_slug="za" obj=ch %} {% include "treenode/treenode_add_stub.html" %} {% endwith %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% with kam="mezi" obj=ch kam_slug="za" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %}
|
{% with kam="mezi" obj=ch kam_slug="za" %} {% include "treenode/treenode_add_stub.html" %} {% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# ----------- Prohazujeme sousedy ----------#}
|
{# ----------- Prohazujeme sousedy ----------#}
|
||||||
<div class="pink">
|
<div class="pink">
|
||||||
|
@ -50,6 +50,6 @@
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{# ----------- Přidáváme prvního syna ----------#}
|
{# ----------- Přidáváme prvního syna ----------#}
|
||||||
{% with kam="jako syna" kam_slug="syn" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %}
|
{% with kam="jako syna" kam_slug="syn" %} {% include "treenode/treenode_add_stub.html" %} {% endwith %}
|
||||||
{%endif%}
|
{%endif%}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django import template
|
from django import template
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import seminar.models as m
|
from .models import RocnikNode, CisloNode, CastNode, TextNode, TemaVCisleNode, UlohaVzorakNode, UlohaZadaniNode, PohadkaNode
|
||||||
ledoian
commented
(Těchto TreeNodů je tu málo, ale nechce se mi teď zjišťovat, které tři chybí…) (Těchto TreeNodů je tu málo, ale nechce se mi teď zjišťovat, které tři chybí…)
|
|||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ def nodeType(value):
|
||||||
if isinstance(value,CastNode): return "Část"
|
if isinstance(value,CastNode): return "Část"
|
||||||
if isinstance(value,TextNode): return "Text"
|
if isinstance(value,TextNode): return "Text"
|
||||||
if isinstance(value,TemaVCisleNode): return "Téma v čísle"
|
if isinstance(value,TemaVCisleNode): return "Téma v čísle"
|
||||||
if isinstance(value,KonferaNode): return "Konfera"
|
# if isinstance(value,KonferaNode): return "Konfera" # FIXME neexistuje
|
||||||
if isinstance(value,ClanekNode): return "Článek"
|
# if isinstance(value,ClanekNode): return "Článek" # FIXME neexistuje
|
||||||
ledoian
commented
Tyhle komentáře způsobí tiché spadnutí. Byl by to Tyhle komentáře způsobí tiché spadnutí. Byl by to `NameError`, nejspíš i při validním volání, teď je to `return None`, díky čemuž se bude chyba špatně lovit. `NameError` je za mě fajn, ale klidně to jde vyřešit nějakým globálním `raise ValueError('tenhle typ TreeNode neexistuje')`.
zelvuska
commented
To je asi otázka spíš na to, proč KonferaNode a ClanekNode přestalo existovat a proč s tím nepřestal existovat i tento kód… To je asi otázka spíš na to, proč KonferaNode a ClanekNode přestalo existovat a proč s tím nepřestal existovat i tento kód…
|
|||||||
if isinstance(value,UlohaVzorakNode): return "Vzorák"
|
if isinstance(value,UlohaVzorakNode): return "Vzorák"
|
||||||
if isinstance(value,UlohaZadaniNode): return "Zadání úlohy"
|
if isinstance(value,UlohaZadaniNode): return "Zadání úlohy"
|
||||||
if isinstance(value,PohadkaNode): return "Pohádka"
|
if isinstance(value,PohadkaNode): return "Pohádka"
|
||||||
|
@ -22,53 +22,57 @@ def nodeType(value):
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isRocnik(value):
|
def isRocnik(value):
|
||||||
return isinstance(value, m.RocnikNode)
|
return isinstance(value, RocnikNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isCislo(value):
|
def isCislo(value):
|
||||||
return isinstance(value, m.CisloNode)
|
return isinstance(value, CisloNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isCast(value):
|
def isCast(value):
|
||||||
return isinstance(value, m.CastNode)
|
return isinstance(value, CastNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isText(value):
|
def isText(value):
|
||||||
return isinstance(value, m.TextNode)
|
return isinstance(value, TextNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isTemaVCisle(value):
|
def isTemaVCisle(value):
|
||||||
return isinstance(value, m.TemaVCisleNode)
|
return isinstance(value, TemaVCisleNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isKonfera(value):
|
def isKonfera(value):
|
||||||
return isinstance(value, m.KonferaNode)
|
# FIXME neexistuje
|
||||||
|
# return isinstance(value, KonferaNode)
|
||||||
ledoian
commented
Prosím aspoň zalogovat, neumřít tiše. Prosím aspoň zalogovat, neumřít tiše.
zelvuska
commented
Stejně jako výše. KonferaNode prostě neexistuje. (Přestala existovat v migraci 0080, které jsi autor…) Stejně jako výše. KonferaNode prostě neexistuje. (Přestala existovat v migraci 0080, které jsi autor…)
|
|||||||
|
return False
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isClanek(value):
|
def isClanek(value):
|
||||||
return isinstance(value, m.ClanekNode)
|
# FIXME neexistuje
|
||||||
|
# return isinstance(value, ClanekNode)
|
||||||
|
return False
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isUlohaVzorak(value):
|
def isUlohaVzorak(value):
|
||||||
return isinstance(value, m.UlohaVzorakNode)
|
return isinstance(value, UlohaVzorakNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isUlohaZadani(value):
|
def isUlohaZadani(value):
|
||||||
return isinstance(value, m.UlohaZadaniNode)
|
return isinstance(value, UlohaZadaniNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isPohadka(value):
|
def isPohadka(value):
|
||||||
return isinstance(value, m.PohadkaNode)
|
return isinstance(value, PohadkaNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isReseni(value):
|
def isReseni(value):
|
||||||
return False
|
return False
|
||||||
# return isinstance(value, m.OtisteneReseniNode)
|
# return isinstance(value, OtisteneReseniNode)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def isOrgText(value):
|
def isOrgText(value):
|
||||||
return False
|
return False
|
||||||
# return isinstance(value, m.OrgTextNode)
|
# return isinstance(value, OrgTextNode)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
import treenode.treelib as tl
|
import treenode.treelib as tl
|
||||||
import seminar.models as m
|
from .models import CastNode
|
||||||
ledoian
commented
V principu myslím, že tady je lepší řešení spíš V principu myslím, že tady je lepší řešení spíš `import treenode.models as tn`, ale až někdo někdy bude pokračovat ve psaní těchto testů, tak si to tam nejspíš dopíše, tak je to teď asi jedno…
zelvuska
commented
Proč si myslíš, že je lepší náhodná zkratka, než importování přímo věcí (když je to lokální věc). A celkově nad tímhle (jak má vypadat importování toho všeho, co předtím bylo Proč si myslíš, že je lepší náhodná zkratka, než importování přímo věcí (když je to lokální věc).
A celkově nad tímhle (jak má vypadat importování toho všeho, co předtím bylo `import seminar.models as m`) trochu dumám.
|
|||||||
|
|
||||||
class SimpleTreeLibTests(TestCase):
|
class SimpleTreeLibTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Vyrobíme pár nějakých Nodů
|
# Vyrobíme pár nějakých Nodů
|
||||||
self.root = m.CastNode(root=None, first_child=None, succ=None, nadpis="Root")
|
self.root = CastNode(root=None, first_child=None, succ=None, nadpis="Root")
|
||||||
self.root.save()
|
self.root.save()
|
||||||
self.some_node = m.CastNode(root=self.root, first_child=None, succ=None, nadpis="Přetržené")
|
self.some_node = CastNode(root=self.root, first_child=None, succ=None, nadpis="Přetržené")
|
||||||
self.other_node = m.CastNode(root=self.root, first_child=None, succ=None, nadpis="Dítě")
|
self.other_node = CastNode(root=self.root, first_child=None, succ=None, nadpis="Dítě")
|
||||||
self.some_orphan = m.CastNode(root=None, first_child=None, succ=None, nadpis="Ošklivé")
|
self.some_orphan = CastNode(root=None, first_child=None, succ=None, nadpis="Ošklivé")
|
||||||
self.other_orphan = m.CastNode(root=None, first_child=None, succ=None, nadpis="Káčátko")
|
self.other_orphan = CastNode(root=None, first_child=None, succ=None, nadpis="Káčátko")
|
||||||
|
|
||||||
# Trochu je pospojujeme
|
# Trochu je pospojujeme
|
||||||
self.root.first_child = self.some_node
|
self.root.first_child = self.some_node
|
||||||
|
|
|
@ -238,7 +238,7 @@ class TreeLibError(RuntimeError):
|
||||||
|
|
||||||
# Editace stromu:
|
# Editace stromu:
|
||||||
def create_node_after(predecessor, type, **kwargs):
|
def create_node_after(predecessor, type, **kwargs):
|
||||||
from seminar.models import TreeNode
|
from .models import TreeNode
|
||||||
if predecessor is None:
|
if predecessor is None:
|
||||||
raise TreeLibError("Nelze vyrábět sirotky! (predecessor=None)")
|
raise TreeLibError("Nelze vyrábět sirotky! (predecessor=None)")
|
||||||
if not issubclass(type, TreeNode):
|
if not issubclass(type, TreeNode):
|
||||||
|
@ -255,7 +255,7 @@ def create_node_after(predecessor, type, **kwargs):
|
||||||
|
|
||||||
# Vyrábí prvního syna, ostatní nalepí za (existují-li)
|
# Vyrábí prvního syna, ostatní nalepí za (existují-li)
|
||||||
def create_child(parent, type, **kwargs):
|
def create_child(parent, type, **kwargs):
|
||||||
from seminar.models import TreeNode
|
from .models import TreeNode
|
||||||
if parent is None:
|
if parent is None:
|
||||||
raise TreeLibError("Nelze vyrábět sirotky! (parent=None)")
|
raise TreeLibError("Nelze vyrábět sirotky! (parent=None)")
|
||||||
if not issubclass(type, TreeNode):
|
if not issubclass(type, TreeNode):
|
||||||
|
@ -293,7 +293,7 @@ def insert_last_child(parent, node):
|
||||||
last.save()
|
last.save()
|
||||||
|
|
||||||
def create_node_before(successor, type, **kwargs):
|
def create_node_before(successor, type, **kwargs):
|
||||||
from seminar.models import TreeNode
|
from .models import TreeNode
|
||||||
if successor is None:
|
if successor is None:
|
||||||
raise TreeLibError("Nelze vyrábět sirotky! (successor=None)")
|
raise TreeLibError("Nelze vyrábět sirotky! (successor=None)")
|
||||||
if not issubclass(type, TreeNode):
|
if not issubclass(type, TreeNode):
|
||||||
|
|
|
@ -2,16 +2,16 @@ from django.urls import path, re_path
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
#path('treenode/<int:pk>/', views.TreeNodeView.as_view(), name='seminar_treenode'),
|
#path('treenode/<int:pk>/', views.TreeNodeView.as_view(), name='treenode'),
|
||||||
#path('treenode/<int:pk>/json/', views.TreeNodeJSONView.as_view(), name='seminar_treenode_json'),
|
#path('treenode/<int:pk>/json/', views.TreeNodeJSONView.as_view(), name='treenode_json'),
|
||||||
#path('treenode/text/<int:pk>/', views.TextWebView.as_view(), name='seminar_textnode_web'),
|
#path('treenode/text/<int:pk>/', views.TextWebView.as_view(), name='treenode_textnode_web'),
|
||||||
#path('treenode/editor/pridat/<str:co>/<int:pk>/<str:kam>/', views.TreeNodePridatView.as_view(), name='treenode_pridat'),
|
#path('treenode/editor/pridat/<str:co>/<int:pk>/<str:kam>/', views.TreeNodePridatView.as_view(), name='treenode_pridat'),
|
||||||
#path('treenode/editor/smazat/<int:pk>/', views.TreeNodeSmazatView.as_view(), name='treenode_smazat'),
|
#path('treenode/editor/smazat/<int:pk>/', views.TreeNodeSmazatView.as_view(), name='treenode_smazat'),
|
||||||
#path('treenode/editor/odvesitpryc/<int:pk>/', views.TreeNodeOdvesitPrycView.as_view(), name='treenode_odvesitpryc'),
|
#path('treenode/editor/odvesitpryc/<int:pk>/', views.TreeNodeOdvesitPrycView.as_view(), name='treenode_odvesitpryc'),
|
||||||
#path('treenode/editor/podvesit/<int:pk>/<str:kam>/', views.TreeNodePodvesitView.as_view(), name='treenode_podvesit'),
|
#path('treenode/editor/podvesit/<int:pk>/<str:kam>/', views.TreeNodePodvesitView.as_view(), name='treenode_podvesit'),
|
||||||
#path('treenode/editor/prohodit/<int:pk>/', views.TreeNodeProhoditView.as_view(), name='treenode_prohodit'),
|
#path('treenode/editor/prohodit/<int:pk>/', views.TreeNodeProhoditView.as_view(), name='treenode_prohodit'),
|
||||||
#path('treenode/sirotcinec/', views.SirotcinecView.as_view(), name='seminar_treenode_sirotcinec'),
|
#path('treenode/sirotcinec/', views.SirotcinecView.as_view(), name='treenode_sirotcinec'),
|
||||||
#path('problem/(?P<pk>\d+)/(?P<prispevek>\d+)/', views.PrispevekView.as_view(), name='seminar_problem_prispevek'),
|
#path('problem/(?P<pk>\d+)/(?P<prispevek>\d+)/', views.PrispevekView.as_view(), name='treenode_problem_prispevek'),
|
||||||
|
|
||||||
re_path(r'^temp/vue/.*$',views.VueTestView.as_view(),name='vue_test_view'),
|
re_path(r'^temp/vue/.*$',views.VueTestView.as_view(),name='vue_test_view'),
|
||||||
path('temp/image_upload/', views.NahrajObrazekKTreeNoduView.as_view()),
|
path('temp/image_upload/', views.NahrajObrazekKTreeNoduView.as_view()),
|
||||||
|
|
|
@ -6,8 +6,8 @@ from django.views.generic.edit import CreateView
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
|
||||||
import seminar.models as s
|
from .models import TemaVCisleNode, RocnikNode, CisloNode, UlohaVzorakNode, UlohaZadaniNode, TreeNode, CastNode, TextNode, ReseniNode, PohadkaNode, OrgTextNode
|
||||||
ledoian
commented
(Tu chybí (Tu chybí `MeziCisloNode`, to je vcelku podezřelé…)
zelvuska
commented
Asi nejsem schopen opravit (aniž bych se snažil pochopit treenode). Asi nejsem schopen opravit (aniž bych se snažil pochopit treenode).
|
|||||||
import seminar.models as m
|
from .models import Text, Obrazek
|
||||||
from treenode import treelib
|
from treenode import treelib
|
||||||
import treenode.forms as f
|
import treenode.forms as f
|
||||||
import treenode.templatetags as tnltt
|
import treenode.templatetags as tnltt
|
||||||
|
@ -29,7 +29,7 @@ class TNLData(object):
|
||||||
|
|
||||||
if parent:
|
if parent:
|
||||||
self.tema_in_path = parent.tema_in_path
|
self.tema_in_path = parent.tema_in_path
|
||||||
if isinstance(anode, m.TemaVCisleNode):
|
if isinstance(anode, TemaVCisleNode):
|
||||||
self.tema_in_path = True
|
self.tema_in_path = True
|
||||||
|
|
||||||
def add_edit_options(self):
|
def add_edit_options(self):
|
||||||
|
@ -51,11 +51,11 @@ class TNLData(object):
|
||||||
(All of them have method verejne.)"""
|
(All of them have method verejne.)"""
|
||||||
parent = anode # chceme začít už od konkrétního node včetně
|
parent = anode # chceme začít už od konkrétního node včetně
|
||||||
while True:
|
while True:
|
||||||
rocnik = isinstance(parent, s.RocnikNode)
|
rocnik = isinstance(parent, RocnikNode)
|
||||||
cislo = isinstance(parent, s.CisloNode)
|
cislo = isinstance(parent, CisloNode)
|
||||||
uloha = (isinstance(parent, s.UlohaVzorakNode) or
|
uloha = (isinstance(parent, UlohaVzorakNode) or
|
||||||
isinstance(parent, s.UlohaZadaniNode))
|
isinstance(parent, UlohaZadaniNode))
|
||||||
tema = isinstance(parent, s.TemaVCisleNode)
|
tema = isinstance(parent, TemaVCisleNode)
|
||||||
|
|
||||||
if (rocnik or cislo or uloha or tema) or parent==None:
|
if (rocnik or cislo or uloha or tema) or parent==None:
|
||||||
break
|
break
|
||||||
|
@ -158,7 +158,7 @@ class TNLData(object):
|
||||||
|
|
||||||
|
|
||||||
class TreeNodeView(generic.DetailView):
|
class TreeNodeView(generic.DetailView):
|
||||||
model = s.TreeNode
|
model = TreeNode
|
||||||
template_name = 'treenode/treenode.html'
|
template_name = 'treenode/treenode.html'
|
||||||
|
|
||||||
def get_context_data(self,**kwargs):
|
def get_context_data(self,**kwargs):
|
||||||
|
@ -168,7 +168,7 @@ class TreeNodeView(generic.DetailView):
|
||||||
|
|
||||||
|
|
||||||
class TreeNodeJSONView(generic.DetailView):
|
class TreeNodeJSONView(generic.DetailView):
|
||||||
model = s.TreeNode
|
model = TreeNode
|
||||||
|
|
||||||
def get(self,request,*args, **kwargs):
|
def get(self,request,*args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
|
@ -178,21 +178,21 @@ class TreeNodeJSONView(generic.DetailView):
|
||||||
|
|
||||||
class TreeNodePridatView(generic.View):
|
class TreeNodePridatView(generic.View):
|
||||||
type_from_str = {
|
type_from_str = {
|
||||||
'rocnikNode': m.RocnikNode,
|
'rocnikNode': RocnikNode,
|
||||||
'cisloNode': m.CisloNode,
|
'cisloNode': CisloNode,
|
||||||
'castNode': m.CastNode,
|
'castNode': CastNode,
|
||||||
'textNode': m.TextNode,
|
'textNode': TextNode,
|
||||||
'temaVCisleNode': m.TemaVCisleNode,
|
'temaVCisleNode': TemaVCisleNode,
|
||||||
'reseniNode': m.ReseniNode,
|
'reseniNode': ReseniNode,
|
||||||
'ulohaZadaniNode': m.UlohaZadaniNode,
|
'ulohaZadaniNode': UlohaZadaniNode,
|
||||||
'ulohaVzorakNode': m.UlohaVzorakNode,
|
'ulohaVzorakNode': UlohaVzorakNode,
|
||||||
'pohadkaNode': m.PohadkaNode,
|
'pohadkaNode': PohadkaNode,
|
||||||
'orgText': m.OrgTextNode,
|
'orgText': OrgTextNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
######## FIXME: ROZEPSANE, NEFUNGUJE, DOPSAT !!!!!! ###########
|
######## FIXME: ROZEPSANE, NEFUNGUJE, DOPSAT !!!!!! ###########
|
||||||
node = s.TreeNode.objects.get(pk=self.kwargs['pk'])
|
node = TreeNode.objects.get(pk=self.kwargs['pk'])
|
||||||
kam = self.kwargs['kam']
|
kam = self.kwargs['kam']
|
||||||
co = self.kwargs['co']
|
co = self.kwargs['co']
|
||||||
typ = self.type_from_str[co]
|
typ = self.type_from_str[co]
|
||||||
|
@ -202,19 +202,19 @@ class TreeNodePridatView(generic.View):
|
||||||
if kam not in ('pred','syn','za'):
|
if kam not in ('pred','syn','za'):
|
||||||
raise ValidationError('Přidat lze pouze před nebo za node nebo jako syna')
|
raise ValidationError('Přidat lze pouze před nebo za node nebo jako syna')
|
||||||
|
|
||||||
if co == m.TextNode:
|
if co == TextNode:
|
||||||
new_obj = m.Text()
|
new_obj = Text()
|
||||||
new_obj.save()
|
new_obj.save()
|
||||||
elif co == m.CastNode:
|
elif co == CastNode:
|
||||||
new_obj = m.CastNode()
|
new_obj = CastNode()
|
||||||
new_obj.nadpis = request.POST.get('pridat-castNode-{}-{}'.format(node.id,kam))
|
new_obj.nadpis = request.POST.get('pridat-castNode-{}-{}'.format(node.id,kam))
|
||||||
new_obj.save()
|
new_obj.save()
|
||||||
elif co == m.ReseniNode:
|
elif co == ReseniNode:
|
||||||
new_obj = m
|
new_obj = m
|
||||||
pass
|
pass
|
||||||
elif co == m.UlohaZadaniNode:
|
elif co == UlohaZadaniNode:
|
||||||
pass
|
pass
|
||||||
elif co == m.UlohaReseniNode:
|
elif co == UlohaReseniNode:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
new_obj = None
|
new_obj = None
|
||||||
|
@ -225,15 +225,15 @@ class TreeNodePridatView(generic.View):
|
||||||
|
|
||||||
|
|
||||||
if kam == 'syn':
|
if kam == 'syn':
|
||||||
if typ == m.TextNode:
|
if typ == TextNode:
|
||||||
text_obj = m.Text()
|
text_obj = Text()
|
||||||
text_obj.save()
|
text_obj.save()
|
||||||
node = treelib.create_child(node, typ, text=text_obj)
|
node = treelib.create_child(node, typ, text=text_obj)
|
||||||
else:
|
else:
|
||||||
node = treelib.create_child(node, typ)
|
node = treelib.create_child(node, typ)
|
||||||
if kam == 'za':
|
if kam == 'za':
|
||||||
if typ == m.TextNode:
|
if typ == TextNode:
|
||||||
text_obj = m.Text()
|
text_obj = Text()
|
||||||
text_obj.save()
|
text_obj.save()
|
||||||
node = treelib.create_node_after(node, typ, text=text_obj)
|
node = treelib.create_node_after(node, typ, text=text_obj)
|
||||||
else:
|
else:
|
||||||
|
@ -244,7 +244,7 @@ class TreeNodePridatView(generic.View):
|
||||||
|
|
||||||
class TreeNodeSmazatView(generic.base.View):
|
class TreeNodeSmazatView(generic.base.View):
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
node = s.TreeNode.objects.get(pk=self.kwargs['pk'])
|
node = TreeNode.objects.get(pk=self.kwargs['pk'])
|
||||||
if node.first_child:
|
if node.first_child:
|
||||||
raise NotImplementedError('Mazání TreeNode se syny není zatím podporováno!')
|
raise NotImplementedError('Mazání TreeNode se syny není zatím podporováno!')
|
||||||
treelib.disconnect_node(node)
|
treelib.disconnect_node(node)
|
||||||
|
@ -254,7 +254,7 @@ class TreeNodeSmazatView(generic.base.View):
|
||||||
|
|
||||||
class TreeNodeOdvesitPrycView(generic.base.View):
|
class TreeNodeOdvesitPrycView(generic.base.View):
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
node = s.TreeNode.objects.get(pk=self.kwargs['pk'])
|
node = TreeNode.objects.get(pk=self.kwargs['pk'])
|
||||||
treelib.disconnect_node(node)
|
treelib.disconnect_node(node)
|
||||||
node.root = None
|
node.root = None
|
||||||
node.save()
|
node.save()
|
||||||
|
@ -263,7 +263,7 @@ class TreeNodeOdvesitPrycView(generic.base.View):
|
||||||
|
|
||||||
class TreeNodePodvesitView(generic.base.View):
|
class TreeNodePodvesitView(generic.base.View):
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
node = s.TreeNode.objects.get(pk=self.kwargs['pk'])
|
node = TreeNode.objects.get(pk=self.kwargs['pk'])
|
||||||
kam = self.kwargs['kam']
|
kam = self.kwargs['kam']
|
||||||
if kam == 'pred':
|
if kam == 'pred':
|
||||||
treelib.lower_node(node)
|
treelib.lower_node(node)
|
||||||
|
@ -274,21 +274,21 @@ class TreeNodePodvesitView(generic.base.View):
|
||||||
|
|
||||||
class TreeNodeProhoditView(generic.base.View):
|
class TreeNodeProhoditView(generic.base.View):
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
node = s.TreeNode.objects.get(pk=self.kwargs['pk'])
|
node = TreeNode.objects.get(pk=self.kwargs['pk'])
|
||||||
treelib.swap_succ(node)
|
treelib.swap_succ(node)
|
||||||
return redirect(request.headers.get('referer'))
|
return redirect(request.headers.get('referer'))
|
||||||
#FIXME ve formulari predat puvodni url a vratit redirect na ni
|
#FIXME ve formulari predat puvodni url a vratit redirect na ni
|
||||||
|
|
||||||
class SirotcinecView(generic.ListView):
|
class SirotcinecView(generic.ListView):
|
||||||
model = s.TreeNode
|
model = TreeNode
|
||||||
template_name = 'treenode/orphanage.html'
|
template_name = 'treenode/orphanage.html'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return s.TreeNode.objects.not_instance_of(s.RocnikNode).filter(root=None,prev=None,succ=None,father_of_first=None)
|
return TreeNode.objects.not_instance_of(RocnikNode).filter(root=None,prev=None,succ=None,father_of_first=None)
|
||||||
|
|
||||||
# FIXME pouzit Django REST Framework
|
# FIXME pouzit Django REST Framework
|
||||||
class TextWebView(generic.DetailView):
|
class TextWebView(generic.DetailView):
|
||||||
model = s.Text
|
model = Text
|
||||||
|
|
||||||
def get(self,request,*args, **kwargs):
|
def get(self,request,*args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
|
@ -300,7 +300,7 @@ class VueTestView(generic.TemplateView):
|
||||||
|
|
||||||
|
|
||||||
class NahrajObrazekKTreeNoduView(LoginRequiredMixin, CreateView):
|
class NahrajObrazekKTreeNoduView(LoginRequiredMixin, CreateView):
|
||||||
model = s.Obrazek
|
model = Obrazek
|
||||||
form_class = f.NahrajObrazekKTreeNoduForm
|
form_class = f.NahrajObrazekKTreeNoduForm
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
|
@ -316,7 +316,7 @@ class NahrajObrazekKTreeNoduView(LoginRequiredMixin, CreateView):
|
||||||
print(form)
|
print(form)
|
||||||
self.object = form.save(commit=False)
|
self.object = form.save(commit=False)
|
||||||
print(self.object.na_web)
|
print(self.object.na_web)
|
||||||
self.object.text = m.Text.objects.get(pk=int(self.request.headers['Textid']))
|
self.object.text = Text.objects.get(pk=int(self.request.headers['Textid']))
|
||||||
self.object.save()
|
self.object.save()
|
||||||
|
|
||||||
return JsonResponse({"url":self.object.na_web.url})
|
return JsonResponse({"url":self.object.na_web.url})
|
||||||
|
|
|
@ -3,7 +3,12 @@ from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from rest_framework.permissions import BasePermission, AllowAny
|
from rest_framework.permissions import BasePermission, AllowAny
|
||||||
from seminar import models as m
|
|
||||||
|
from odevzdavatko.models import Reseni
|
||||||
|
from tvorba.models import Problem, Uloha
|
||||||
|
|
||||||
|
from .models import TextNode, CastNode, UlohaVzorakNode, UlohaZadaniNode, ReseniNode
|
||||||
|
from .models import Text
|
||||||
import treenode.serializers as views
|
import treenode.serializers as views
|
||||||
|
|
||||||
from treenode.permissions import AllowWrite
|
from treenode.permissions import AllowWrite
|
||||||
|
@ -66,17 +71,17 @@ class ReadWriteSerializerMixin(object):
|
||||||
return self.create_serializer_class
|
return self.create_serializer_class
|
||||||
|
|
||||||
class TextViewSet(PermissionMixin, viewsets.ModelViewSet):
|
class TextViewSet(PermissionMixin, viewsets.ModelViewSet):
|
||||||
queryset = m.Text.objects.all()
|
queryset = Text.objects.all()
|
||||||
serializer_class = views.TextSerializer
|
serializer_class = views.TextSerializer
|
||||||
|
|
||||||
class TextNodeViewSet(PermissionMixin, ReadWriteSerializerMixin,viewsets.ModelViewSet):
|
class TextNodeViewSet(PermissionMixin, ReadWriteSerializerMixin,viewsets.ModelViewSet):
|
||||||
queryset = m.TextNode.objects.all()
|
queryset = TextNode.objects.all()
|
||||||
read_serializer_class = views.TextNodeSerializer
|
read_serializer_class = views.TextNodeSerializer
|
||||||
write_serializer_class = views.TextNodeWriteSerializer
|
write_serializer_class = views.TextNodeWriteSerializer
|
||||||
create_serializer_class = views.TextNodeCreateSerializer
|
create_serializer_class = views.TextNodeCreateSerializer
|
||||||
|
|
||||||
class CastNodeViewSet(PermissionMixin, ReadWriteSerializerMixin,viewsets.ModelViewSet):
|
class CastNodeViewSet(PermissionMixin, ReadWriteSerializerMixin,viewsets.ModelViewSet):
|
||||||
queryset = m.CastNode.objects.all()
|
queryset = CastNode.objects.all()
|
||||||
read_serializer_class = views.CastNodeSerializer
|
read_serializer_class = views.CastNodeSerializer
|
||||||
write_serializer_class = views.CastNodeSerializer
|
write_serializer_class = views.CastNodeSerializer
|
||||||
create_serializer_class = views.CastNodeCreateSerializer
|
create_serializer_class = views.CastNodeCreateSerializer
|
||||||
|
@ -95,7 +100,7 @@ class UlohaVzorakNodeViewSet(PermissionMixin, ReadWriteSerializerMixin, viewsets
|
||||||
create_serializer_class = views.UlohaVzorakNodeCreateSerializer
|
create_serializer_class = views.UlohaVzorakNodeCreateSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = m.UlohaVzorakNode.objects.all()
|
queryset = UlohaVzorakNode.objects.all()
|
||||||
nazev = self.request.query_params.get('nazev',None)
|
nazev = self.request.query_params.get('nazev',None)
|
||||||
if nazev is not None:
|
if nazev is not None:
|
||||||
queryset = queryset.filter(nazev__contains=nazev)
|
queryset = queryset.filter(nazev__contains=nazev)
|
||||||
|
@ -114,7 +119,7 @@ class ReseniViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = views.ReseniSerializer
|
serializer_class = views.ReseniSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = m.Reseni.objects.all()
|
queryset = Reseni.objects.all()
|
||||||
#FIXME upravit nazvy dle skutecnych polozek reseni
|
#FIXME upravit nazvy dle skutecnych polozek reseni
|
||||||
nazev = self.request.query_params.get('nazev',None)
|
nazev = self.request.query_params.get('nazev',None)
|
||||||
if nazev is not None:
|
if nazev is not None:
|
||||||
|
@ -128,7 +133,7 @@ class UlohaViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = views.UlohaSerializer
|
serializer_class = views.UlohaSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = m.Uloha.objects.all()
|
queryset = Uloha.objects.all()
|
||||||
nazev = self.request.query_params.get('nazev',None)
|
nazev = self.request.query_params.get('nazev',None)
|
||||||
if nazev is not None:
|
if nazev is not None:
|
||||||
queryset = queryset.filter(nazev__contains=nazev)
|
queryset = queryset.filter(nazev__contains=nazev)
|
||||||
|
@ -138,13 +143,13 @@ class UlohaViewSet(viewsets.ModelViewSet):
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
class UlohaZadaniNodeViewSet(ReadWriteSerializerMixin, viewsets.ModelViewSet):
|
class UlohaZadaniNodeViewSet(ReadWriteSerializerMixin, viewsets.ModelViewSet):
|
||||||
queryset = m.UlohaZadaniNode.objects.all()
|
queryset = UlohaZadaniNode.objects.all()
|
||||||
read_serializer_class = views.UlohaZadaniNodeSerializer
|
read_serializer_class = views.UlohaZadaniNodeSerializer
|
||||||
write_serializer_class = views.UlohaZadaniNodeWriteSerializer
|
write_serializer_class = views.UlohaZadaniNodeWriteSerializer
|
||||||
create_serializer_class = views.UlohaZadaniNodeCreateSerializer
|
create_serializer_class = views.UlohaZadaniNodeCreateSerializer
|
||||||
|
|
||||||
class ReseniNodeViewSet(ReadWriteSerializerMixin, viewsets.ModelViewSet):
|
class ReseniNodeViewSet(ReadWriteSerializerMixin, viewsets.ModelViewSet):
|
||||||
queryset = m.ReseniNode.objects.all()
|
queryset = ReseniNode.objects.all()
|
||||||
read_serializer_class = views.ReseniNodeSerializer
|
read_serializer_class = views.ReseniNodeSerializer
|
||||||
write_serializer_class = views.ReseniNodeWriteSerializer
|
write_serializer_class = views.ReseniNodeWriteSerializer
|
||||||
create_serializer_class = views.ReseniNodeCreateSerializer
|
create_serializer_class = views.ReseniNodeCreateSerializer
|
||||||
|
@ -155,7 +160,7 @@ class ProblemViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = views.ProblemSerializer
|
serializer_class = views.ProblemSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = m.Problem.objects.all()
|
queryset = Problem.objects.all()
|
||||||
ucel = self.request.query_params.get('ucel',None)
|
ucel = self.request.query_params.get('ucel',None)
|
||||||
rocnik = self.request.query_params.get('rocnik',None)
|
rocnik = self.request.query_params.get('rocnik',None)
|
||||||
tema = self.request.query_params.get('tema',None)
|
tema = self.request.query_params.get('tema',None)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import datetime
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
import seminar.models.tvorba
|
import various.models
|
||||||
import tvorba.models
|
import tvorba.models
|
||||||
import taggit.managers
|
import taggit.managers
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class Migration(migrations.Migration):
|
||||||
('datum_vydani', models.DateField(blank=True, help_text='Datum vydání finální verze', null=True, verbose_name='datum vydání')),
|
('datum_vydani', models.DateField(blank=True, help_text='Datum vydání finální verze', null=True, verbose_name='datum vydání')),
|
||||||
('verejne_db', models.BooleanField(db_column='verejne', default=False, verbose_name='číslo zveřejněno')),
|
('verejne_db', models.BooleanField(db_column='verejne', default=False, verbose_name='číslo zveřejněno')),
|
||||||
('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k číslu (plain text)', verbose_name='neveřejná poznámka')),
|
('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k číslu (plain text)', verbose_name='neveřejná poznámka')),
|
||||||
('pdf', models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, storage=seminar.models.tvorba.OverwriteStorage(), upload_to=tvorba.models.cislo_pdf_filename, verbose_name='pdf')),
|
('pdf', models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, storage=various.models.OverwriteStorage(), upload_to=tvorba.models.cislo_pdf_filename, verbose_name='pdf')),
|
||||||
('titulka_nahled', models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to=tvorba.models.cislo_png_filename, verbose_name='Obrázek titulní strany')),
|
('titulka_nahled', models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to=tvorba.models.cislo_png_filename, verbose_name='Obrázek titulní strany')),
|
||||||
('rocnik', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='cisla', to='tvorba.rocnik', verbose_name='ročník')),
|
('rocnik', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='cisla', to='tvorba.rocnik', verbose_name='ročník')),
|
||||||
],
|
],
|
||||||
|
|
|
@ -31,8 +31,7 @@ from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
|
|
||||||
from seminar.models.base import SeminarModelBase
|
from various.models import SeminarModelBase, OverwriteStorage
|
||||||
from seminar.models.tvorba import OverwriteStorage
|
|
||||||
from personalni.models import Prijemce, Organizator
|
from personalni.models import Prijemce, Organizator
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -96,7 +95,7 @@ class Rocnik(SeminarModelBase):
|
||||||
return self.prvni_rok + 1
|
return self.prvni_rok + 1
|
||||||
|
|
||||||
def verejne_url(self):
|
def verejne_url(self):
|
||||||
return reverse('seminar_rocnik', kwargs={'rocnik': self.rocnik})
|
return reverse('tvorba_rocnik', kwargs={'rocnik': self.rocnik})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cached_rocnik(cls, r_id):
|
def cached_rocnik(cls, r_id):
|
||||||
|
@ -171,7 +170,7 @@ class Cislo(SeminarModelBase):
|
||||||
verejne.boolean = True
|
verejne.boolean = True
|
||||||
|
|
||||||
def verejne_url(self):
|
def verejne_url(self):
|
||||||
return reverse('seminar_cislo', kwargs={'rocnik': self.rocnik.rocnik, 'cislo': self.poradi})
|
return reverse('tvorba_cislo', kwargs={'rocnik': self.rocnik.rocnik, 'cislo': self.poradi})
|
||||||
|
|
||||||
def absolute_url(self):
|
def absolute_url(self):
|
||||||
return "https://" + str(get_current_site(None)) + self.verejne_url()
|
return "https://" + str(get_current_site(None)) + self.verejne_url()
|
||||||
|
@ -508,7 +507,7 @@ class Problem(SeminarModelBase,PolymorphicModel):
|
||||||
# verejne.boolean = True
|
# verejne.boolean = True
|
||||||
|
|
||||||
def verejne_url(self):
|
def verejne_url(self):
|
||||||
return reverse('seminar_problem', kwargs={'pk': self.id})
|
return reverse('tvorba_problem', kwargs={'pk': self.id})
|
||||||
|
|
||||||
def admin_url(self):
|
def admin_url(self):
|
||||||
return reverse('admin:tvorba_problem_change', args=(self.id, ))
|
return reverse('admin:tvorba_problem_change', args=(self.id, ))
|
||||||
|
|
|
@ -35,12 +35,12 @@
|
||||||
<div class="mam-org-only">
|
<div class="mam-org-only">
|
||||||
<h2> Orgovské odkazy </h2>
|
<h2> Orgovské odkazy </h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="obalky.pdf">Obálky (PDF)</a></li>
|
<li><a href="{% url "tvorba_cislo_obalky" rocnik=cislo.rocnik.rocnik cislo=cislo.poradi %}">Obálky (PDF)</a></li>
|
||||||
<li><a href="tituly.tex" download>Tituly (TeX, 2. deadline předchozího čísla a 1.deadline tohoto)</a></li>
|
<li><a href="{% url "tvorba_cislo_titul" rocnik=cislo.rocnik.rocnik cislo=cislo.poradi %}" download>Tituly (TeX, 2. deadline předchozího čísla a 1.deadline tohoto)</a></li>
|
||||||
<li><a href="vysledkovka.tex" download>Výsledkovka (TeX, 2. deadline předchozího čísla a 1.deadline tohoto)</a></li>
|
<li><a href="{% url "tvorba_cislo_vysledkovka" rocnik=cislo.rocnik.rocnik cislo=cislo.poradi %}" download>Výsledkovka (TeX, 2. deadline předchozího čísla a 1.deadline tohoto)</a></li>
|
||||||
<li><a href="odmeny/{{prevcislo.rocnik.rocnik}}.{{prevcislo.poradi}}/">Odměny</a></li>
|
<li>{% if prevcislo %}<a href="{% url "tvorba_archiv_odmeny" trocnik=cislo.rocnik.rocnik tcislo=cislo.poradi frocnik=prevcislo.rocnik.rocnik fcislo=prevcislo.poradi %}">Odměny</a>{% else %}Pro toto číslo neumíme spočítat odměny.{% endif %}{# FIXME (Jediné číslo, kde toto neumíme je to úplně první.) #}</li>
|
||||||
<li><a href="{% url "seminar_rocnik_titul" rocnik=cislo.rocnik.rocnik %}" download="posledni_tituly.tex">Tituly do závěrečného čísla (TeX, 2. deadline předchozího čísla a oba tohoto)</a></li>
|
<li><a href="{% url "tvorba_rocnik_titul" rocnik=cislo.rocnik.rocnik %}" download="posledni_tituly.tex">Tituly do závěrečného čísla (TeX, 2. deadline předchozího čísla a oba tohoto)</a></li>
|
||||||
<li><a href="{% url "seminar_rocnik_posledni_vysledkovka" rocnik=cislo.rocnik.rocnik %}" download>Výsledkovka závěrečného čísla ročníku (TeX, 2. deadline předchozího čísla a oba tohoto)</a></li>
|
<li><a href="{% url "tvorba_rocnik_posledni_vysledkovka" rocnik=cislo.rocnik.rocnik %}" download>Výsledkovka závěrečného čísla ročníku (TeX, 2. deadline předchozího čísla a oba tohoto)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "seminar/archiv/problem.html" %}
|
{% extends "tvorba/archiv/problem.html" %}
|
||||||
|
|
||||||
{% block problem %}
|
{% block problem %}
|
||||||
{% if problem.cislo_zadani %}
|
{% if problem.cislo_zadani %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "seminar/archiv/problem.html" %}
|
{% extends "tvorba/archiv/problem.html" %}
|
||||||
|
|
||||||
{% block problem %}
|
{% block problem %}
|
||||||
<h1>
|
<h1>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "seminar/archiv/problem.html" %}
|
{% extends "tvorba/archiv/problem.html" %}
|
||||||
|
|
||||||
{% block problem %}
|
{% block problem %}
|
||||||
<h1>
|
<h1>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "seminar/archiv/problem.html" %}
|
{% extends "tvorba/archiv/problem.html" %}
|
||||||
|
|
||||||
{% block problem %}
|
{% block problem %}
|
||||||
<h1>
|
<h1>
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
<p><a href='vysledkovka.tex' download>Výsledkovka ročníku (LaTeX, včetně neveřejných)</a></p>
|
<p><a href='vysledkovka.tex' download>Výsledkovka ročníku (LaTeX, včetně neveřejných)</a></p>
|
||||||
<p><a href="tituly.tex" download>Tituly (TeX, včetně neveřejných, všechny, nevhodné do mamtexu)</a></p>
|
<p><a href="tituly.tex" download>Tituly (TeX, včetně neveřejných, všechny, nevhodné do mamtexu)</a></p>
|
||||||
{# FIXME: Sice to sem asi nepatří sémanticky, ale bylo to nejjednodušší… #}
|
{# FIXME: Sice to sem asi nepatří sémanticky, ale bylo to nejjednodušší… #}
|
||||||
<p><a href='{% url 'seminar_rocnik_resitele_csv' rocnik=rocnik.rocnik %}' download>CSV export řešitelů</a></p>
|
<p><a href='{% url 'tvorba_rocnik_resitele_csv' rocnik=rocnik.rocnik %}' download>CSV export řešitelů</a></p>
|
||||||
<h2>Výsledková listina včetně neveřejných bodů</h2>
|
<h2>Výsledková listina včetně neveřejných bodů</h2>
|
||||||
{% include "vysledkovky/vysledkovka_rocnik.html" with vysledkovka=vysledkovka_neverejna %}
|
{% include "vysledkovky/vysledkovka_rocnik.html" with vysledkovka=vysledkovka_neverejna %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends 'seminar/clanky/resitelske_clanky.html' %}
|
{% extends 'tvorba/clanky/resitelske_clanky.html' %}
|
||||||
|
|
||||||
{% block nadpis1a %}
|
{% block nadpis1a %}
|
||||||
Organizátorské články
|
Organizátorské články
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Staré výsledkové listiny najdete
|
Staré výsledkové listiny najdete
|
||||||
v <a href="{% url 'seminar_archiv_rocniky' %}">archivu</a>.
|
v <a href="{% url 'tvorba_archiv_rocniky' %}">archivu</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% if user.je_org and vysledkovka_s_neverejnymi %}
|
{% if user.je_org and vysledkovka_s_neverejnymi %}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
from django import template
|
from django import template
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
import seminar.models as m
|
from tvorba.models import Deadline
|
||||||
|
|
||||||
@register.filter(name='deadline_kratseji')
|
@register.filter(name='deadline_kratseji')
|
||||||
def deadline_kratsi_text(deadline: m.Deadline):
|
def deadline_kratsi_text(deadline: Deadline):
|
||||||
if deadline is None:
|
if deadline is None:
|
||||||
return 'NONE'
|
return 'NONE'
|
||||||
strings = {
|
strings = {
|
||||||
m.Deadline.TYP_PRVNI: f"{deadline.cislo} ⭯",
|
Deadline.TYP_PRVNI: f"{deadline.cislo} ⭯",
|
||||||
m.Deadline.TYP_SOUS: f"{deadline.cislo} Ⓢ",
|
Deadline.TYP_SOUS: f"{deadline.cislo} Ⓢ",
|
||||||
m.Deadline.TYP_PRVNI_A_SOUS: f"{deadline.cislo} ⭯Ⓢ",
|
Deadline.TYP_PRVNI_A_SOUS: f"{deadline.cislo} ⭯Ⓢ",
|
||||||
m.Deadline.TYP_CISLA: f"{deadline.cislo} ✓",
|
Deadline.TYP_CISLA: f"{deadline.cislo} ✓",
|
||||||
}
|
}
|
||||||
return strings[deadline.typ]
|
return strings[deadline.typ]
|
||||||
|
|
||||||
@register.filter(name='deadline_html')
|
@register.filter(name='deadline_html')
|
||||||
def deadline_html(deadline: m.Deadline):
|
def deadline_html(deadline: Deadline):
|
||||||
if deadline is None:
|
if deadline is None:
|
||||||
return 'Neznámý deadline'
|
return 'Neznámý deadline'
|
||||||
text = deadline_kratsi_text(deadline)
|
text = deadline_kratsi_text(deadline)
|
||||||
classes = {
|
classes = {
|
||||||
m.Deadline.TYP_PRVNI: 'preddeadline',
|
Deadline.TYP_PRVNI: 'preddeadline',
|
||||||
m.Deadline.TYP_SOUS: 'sous_deadline',
|
Deadline.TYP_SOUS: 'sous_deadline',
|
||||||
m.Deadline.TYP_PRVNI_A_SOUS: 'sous_deadline',
|
Deadline.TYP_PRVNI_A_SOUS: 'sous_deadline',
|
||||||
m.Deadline.TYP_CISLA: 'final_deadline',
|
Deadline.TYP_CISLA: 'final_deadline',
|
||||||
}
|
}
|
||||||
return mark_safe(f'<span class="{classes[deadline.typ]}" title="{deadline}">{text}</span>')
|
return mark_safe(f'<span class="{classes[deadline.typ]}" title="{deadline}">{text}</span>')
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,12 @@ import lorem
|
||||||
import django.contrib.auth
|
import django.contrib.auth
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from seminar.models import Rocnik, Cislo, Deadline, Problem, Tema, Uloha, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, UlohaZadaniNode
|
from .models import Rocnik, Cislo, Deadline, Problem, Tema, Uloha, Clanek
|
||||||
import seminar.models as m
|
|
||||||
|
from odevzdavatko.models import Reseni, Hodnoceni
|
||||||
|
# TODO zbavit se treenodů do treenode.testutils (ty pak klidně volat odtud)
|
||||||
|
from treenode.models import TextNode, UlohaZadaniNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, CastNode, MezicisloNode, ReseniNode
|
||||||
|
from treenode.models import Text
|
||||||
|
|
||||||
from treenode.treelib import all_children, insert_last_child, all_children_of_type, create_node_after
|
from treenode.treelib import all_children, insert_last_child, all_children_of_type, create_node_after
|
||||||
|
|
||||||
|
@ -195,7 +199,7 @@ def add_first_child(node, child):
|
||||||
|
|
||||||
def get_text():
|
def get_text():
|
||||||
odstavec = lorem.paragraph()
|
odstavec = lorem.paragraph()
|
||||||
return Text.objects.create(na_web = odstavec, do_cisla = odstavec)
|
return Text.objects.create(na_web = odstavec, do_cisla = odstavec)
|
||||||
|
|
||||||
def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod):
|
def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod):
|
||||||
tema = Tema.objects.create(
|
tema = Tema.objects.create(
|
||||||
|
@ -219,31 +223,31 @@ def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod):
|
||||||
insert_last_child(cislo_node, tema_cislo_node)
|
insert_last_child(cislo_node, tema_cislo_node)
|
||||||
|
|
||||||
# Přidávání obsahu do čísla
|
# Přidávání obsahu do čísla
|
||||||
cast_node = m.CastNode.objects.create(nadpis = "Příspěvek k číslu {}".format(cislo.kod), root=cislo_node.root)
|
cast_node = CastNode.objects.create(nadpis = "Příspěvek k číslu {}".format(cislo.kod), root=cislo_node.root)
|
||||||
add_first_child(tema_cislo_node, cast_node)
|
add_first_child(tema_cislo_node, cast_node)
|
||||||
|
|
||||||
text_node = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
text_node = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
||||||
add_first_child(cast_node, text_node)
|
add_first_child(cast_node, text_node)
|
||||||
|
|
||||||
cast_node2 = m.CastNode.objects.create(nadpis = "První podproblém", root=cislo_node.root)
|
cast_node2 = CastNode.objects.create(nadpis = "První podproblém", root=cislo_node.root)
|
||||||
add_first_child(text_node, cast_node2)
|
add_first_child(text_node, cast_node2)
|
||||||
|
|
||||||
text_node2 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
text_node2 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
||||||
add_first_child(cast_node2, text_node2)
|
add_first_child(cast_node2, text_node2)
|
||||||
|
|
||||||
cast_node3 = m.CastNode.objects.create(nadpis = "Druhý podproblém", root=cislo_node.root)
|
cast_node3 = CastNode.objects.create(nadpis = "Druhý podproblém", root=cislo_node.root)
|
||||||
add_first_child(text_node2, cast_node3)
|
add_first_child(text_node2, cast_node3)
|
||||||
|
|
||||||
text_node3 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
text_node3 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
||||||
add_first_child(cast_node3, text_node3)
|
add_first_child(cast_node3, text_node3)
|
||||||
|
|
||||||
cast_node4 = m.CastNode.objects.create(nadpis = "Třetí podproblém", root=cislo_node.root)
|
cast_node4 = CastNode.objects.create(nadpis = "Třetí podproblém", root=cislo_node.root)
|
||||||
add_first_child(text_node3, cast_node4)
|
add_first_child(text_node3, cast_node4)
|
||||||
|
|
||||||
text_node4 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
text_node4 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
|
||||||
add_first_child(cast_node3, text_node4)
|
add_first_child(cast_node3, text_node4)
|
||||||
|
|
||||||
cast_node3a = m.CastNode.objects.create(nadpis = "Podproblém paralelní s "
|
cast_node3a = CastNode.objects.create(nadpis = "Podproblém paralelní s "
|
||||||
"druhým podproblémem", root=cislo_node.root)
|
"druhým podproblémem", root=cislo_node.root)
|
||||||
cast_node3.succ = cast_node3a
|
cast_node3.succ = cast_node3a
|
||||||
cast_node3.save()
|
cast_node3.save()
|
||||||
|
@ -253,10 +257,10 @@ def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod):
|
||||||
|
|
||||||
# Občas přidáme mezičíslo
|
# Občas přidáme mezičíslo
|
||||||
if rnd.randint(1, 3) == 1:
|
if rnd.randint(1, 3) == 1:
|
||||||
create_node_after(cislo_node, m.MezicisloNode, root=cislo_node.root)
|
create_node_after(cislo_node, MezicisloNode, root=cislo_node.root)
|
||||||
mezicislo_node = cislo_node.succ
|
mezicislo_node = cislo_node.succ
|
||||||
|
|
||||||
cast_node_mezicislo = m.CastNode.objects.create(
|
cast_node_mezicislo = CastNode.objects.create(
|
||||||
nadpis = "Příspěvek k mezičíslu".format(cislo.kod), root=cislo_node.root)
|
nadpis = "Příspěvek k mezičíslu".format(cislo.kod), root=cislo_node.root)
|
||||||
add_first_child(mezicislo_node, cast_node_mezicislo)
|
add_first_child(mezicislo_node, cast_node_mezicislo)
|
||||||
|
|
||||||
|
@ -419,7 +423,7 @@ def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori,
|
||||||
# Najdeme správný TemaVCisleNode pro vložení vzoráku
|
# Najdeme správný TemaVCisleNode pro vložení vzoráku
|
||||||
res_tema_node = None;
|
res_tema_node = None;
|
||||||
for node in all_children(cislo_se_vzorakem.cislonode):
|
for node in all_children(cislo_se_vzorakem.cislonode):
|
||||||
if isinstance(node, TemaVCisleNode):
|
if isinstance(node, TemaVCisleNode):
|
||||||
if node.tema == tema:
|
if node.tema == tema:
|
||||||
res_tema_node = node
|
res_tema_node = node
|
||||||
if res_tema_node is None:
|
if res_tema_node is None:
|
||||||
|
@ -438,7 +442,7 @@ def otec_syn(otec, syn):
|
||||||
|
|
||||||
def gen_clanek(rnd, organizatori, resitele):
|
def gen_clanek(rnd, organizatori, resitele):
|
||||||
logger.info("Generuji článek do čísla 22.2")
|
logger.info("Generuji článek do čísla 22.2")
|
||||||
clanek = m.Clanek.objects.create(
|
clanek = Clanek.objects.create(
|
||||||
nazev="Článek o Lorem ipsum",
|
nazev="Článek o Lorem ipsum",
|
||||||
nadproblem=None,
|
nadproblem=None,
|
||||||
stav='vyreseny',
|
stav='vyreseny',
|
||||||
|
@ -448,16 +452,16 @@ def gen_clanek(rnd, organizatori, resitele):
|
||||||
)
|
)
|
||||||
clanek.save()
|
clanek.save()
|
||||||
|
|
||||||
reseni = m.Reseni.objects.create(
|
reseni = Reseni.objects.create(
|
||||||
zverejneno=True,
|
zverejneno=True,
|
||||||
)
|
)
|
||||||
reseni.resitele.add(rnd.choice(resitele))
|
reseni.resitele.add(rnd.choice(resitele))
|
||||||
reseni.save()
|
reseni.save()
|
||||||
|
|
||||||
cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2)
|
cislo = Cislo.objects.get(rocnik__rocnik=22, poradi=2)
|
||||||
cislonode = cislo.cislonode
|
cislonode = cislo.cislonode
|
||||||
|
|
||||||
hodnoceni = m.Hodnoceni.objects.create(
|
hodnoceni = Hodnoceni.objects.create(
|
||||||
body=15.0,
|
body=15.0,
|
||||||
cislo_body=cislo,
|
cislo_body=cislo,
|
||||||
reseni=reseni,
|
reseni=reseni,
|
||||||
|
@ -465,7 +469,7 @@ def gen_clanek(rnd, organizatori, resitele):
|
||||||
)
|
)
|
||||||
hodnoceni.save()
|
hodnoceni.save()
|
||||||
|
|
||||||
reseninode = m.ReseniNode.objects.create(
|
reseninode = ReseniNode.objects.create(
|
||||||
reseni=reseni
|
reseni=reseni
|
||||||
)
|
)
|
||||||
reseninode.save()
|
reseninode.save()
|
||||||
|
@ -481,26 +485,26 @@ def gen_clanek(rnd, organizatori, resitele):
|
||||||
# FIXME: Ten, kdo vymyslel TreeLib (mj. týž, kdo psal tenhle kód),
|
# FIXME: Ten, kdo vymyslel TreeLib (mj. týž, kdo psal tenhle kód),
|
||||||
# nevyrobil vhodnou funkci, takže to postavíme pozpátku pomocí create_child
|
# nevyrobil vhodnou funkci, takže to postavíme pozpátku pomocí create_child
|
||||||
# (které vyrábí _prvního_ syna)
|
# (které vyrábí _prvního_ syna)
|
||||||
create_child(reseninode, m.CastNode, nadpis="Lorem ipsum")
|
create_child(reseninode, CastNode, nadpis="Lorem ipsum")
|
||||||
# Taky ten člověk nevyrobil vracení nových věcí...
|
# Taky ten člověk nevyrobil vracení nových věcí...
|
||||||
castnode = reseninode.first_child
|
castnode = reseninode.first_child
|
||||||
|
|
||||||
# Úvodní odstaveček
|
# Úvodní odstaveček
|
||||||
obsah = "Tohle je zamyšlení o textu lorem ipsum. Začneme a skončíme ukázkou."
|
obsah = "Tohle je zamyšlení o textu lorem ipsum. Začneme a skončíme ukázkou."
|
||||||
text = m.Text.objects.create(
|
text = Text.objects.create(
|
||||||
na_web=obsah,
|
na_web=obsah,
|
||||||
do_cisla=obsah,
|
do_cisla=obsah,
|
||||||
)
|
)
|
||||||
text.save()
|
text.save()
|
||||||
create_child(reseninode, m.TextNode, text=text)
|
create_child(reseninode, TextNode, text=text)
|
||||||
|
|
||||||
# Několik odstavců lorem ipsum
|
# Několik odstavců lorem ipsum
|
||||||
for _ in range(rnd.randint(3, 7)):
|
for _ in range(rnd.randint(3, 7)):
|
||||||
lipsum = lorem.paragraph()
|
lipsum = lorem.paragraph()
|
||||||
text = m.Text.objects.create(
|
text = Text.objects.create(
|
||||||
na_web=lipsum,
|
na_web=lipsum,
|
||||||
do_cisla=lipsum,
|
do_cisla=lipsum,
|
||||||
)
|
)
|
||||||
text.save()
|
text.save()
|
||||||
create_child(castnode, m.TextNode, text=text)
|
create_child(castnode, TextNode, text=text)
|
||||||
logger.info(f"Článek vygenerován (reseni={reseni.id}, treenode={reseninode.id})")
|
logger.info(f"Článek vygenerován (reseni={reseni.id}, treenode={reseninode.id})")
|
||||||
|
|
|
@ -7,19 +7,19 @@ urlpatterns = [
|
||||||
# path('<int:rocnik>/t<int:tematko>/', views.TematkoView),
|
# path('<int:rocnik>/t<int:tematko>/', views.TematkoView),
|
||||||
|
|
||||||
# Archiv
|
# Archiv
|
||||||
path('archiv/rocniky/', views.ArchivView.as_view(), name="seminar_archiv_rocniky"),
|
path('archiv/rocniky/', views.ArchivView.as_view(), name="tvorba_archiv_rocniky"),
|
||||||
path('archiv/temata/', views.ArchivTemataView.as_view(), name="seminar_archiv_temata"),
|
path('archiv/temata/', views.ArchivTemataView.as_view(), name="tvorba_archiv_temata"),
|
||||||
|
|
||||||
path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='seminar_rocnik'),
|
path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='tvorba_rocnik'),
|
||||||
path('cislo/<int:rocnik>.<str:cislo>/', views.CisloView.as_view(), name='seminar_cislo'),
|
path('cislo/<int:rocnik>.<str:cislo>/', views.CisloView.as_view(), name='tvorba_cislo'),
|
||||||
path('problem/<int:pk>/', views.problemView, name='seminar_problem'),
|
path('problem/<int:pk>/', views.problemView, name='tvorba_problem'),
|
||||||
|
|
||||||
# Zadani
|
# Zadani
|
||||||
# path('aktualni/zadani/', views.AktualniZadaniView.as_view(), name='seminar_aktualni_zadani'), # Dočasně ad-hoc jednoduchá věc.
|
# path('aktualni/zadani/', views.AktualniZadaniView.as_view(), name='tvorba_aktualni_zadani'), # Dočasně ad-hoc jednoduchá věc.
|
||||||
path('aktualni/zadani/', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
|
path('aktualni/zadani/', views.AktualniZadaniView, name='tvorba_aktualni_zadani'),
|
||||||
#path('aktualni/temata/', views.ZadaniTemataView, name='seminar_temata'),
|
#path('aktualni/temata/', views.ZadaniTemataView, name='tvorba_temata'),
|
||||||
path('aktualni/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_aktualni_vysledky'),
|
path('aktualni/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='tvorba_aktualni_vysledky'),
|
||||||
path('aktualni/rocnik/', views.AktualniRocnikRedirectView.as_view(), name='seminar_aktualni_rocnik'),
|
path('aktualni/rocnik/', views.AktualniRocnikRedirectView.as_view(), name='tvorba_aktualni_rocnik'),
|
||||||
|
|
||||||
# Clanky
|
# Clanky
|
||||||
path('archiv/clanky/', views.ClankyResitelView.as_view(), name='clanky_resitel'),
|
path('archiv/clanky/', views.ClankyResitelView.as_view(), name='clanky_resitel'),
|
||||||
|
@ -29,42 +29,42 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'rocnik/<int:rocnik>/vysledkovka.tex',
|
'rocnik/<int:rocnik>/vysledkovka.tex',
|
||||||
org_required(views.RocnikVysledkovkaView.as_view()),
|
org_required(views.RocnikVysledkovkaView.as_view()),
|
||||||
name='seminar_rocnik_vysledkovka'
|
name='tvorba_rocnik_vysledkovka'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'rocnik/<int:rocnik>/resitele.csv',
|
'rocnik/<int:rocnik>/resitele.csv',
|
||||||
org_required(views.resiteleRocnikuCsvExportView),
|
org_required(views.resiteleRocnikuCsvExportView),
|
||||||
name='seminar_rocnik_resitele_csv'
|
name='tvorba_rocnik_resitele_csv'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'rocnik/<int:rocnik>/tituly.tex',
|
'rocnik/<int:rocnik>/tituly.tex',
|
||||||
org_required(views.TitulyViewRocnik),
|
org_required(views.TitulyViewRocnik),
|
||||||
name='seminar_rocnik_titul'
|
name='tvorba_rocnik_titul'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'rocnik/<int:rocnik>/posledni_vysledkovka.tex',
|
'rocnik/<int:rocnik>/posledni_vysledkovka.tex',
|
||||||
org_required(views.PosledniCisloVysledkovkaView.as_view()),
|
org_required(views.PosledniCisloVysledkovkaView.as_view()),
|
||||||
name='seminar_rocnik_posledni_vysledkovka'
|
name='tvorba_rocnik_posledni_vysledkovka'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'cislo/<int:rocnik>.<str:cislo>/vysledkovka.tex',
|
'cislo/<int:rocnik>.<str:cislo>/vysledkovka.tex',
|
||||||
org_required(views.CisloVysledkovkaView.as_view()),
|
org_required(views.CisloVysledkovkaView.as_view()),
|
||||||
name='seminar_cislo_vysledkovka'
|
name='tvorba_cislo_vysledkovka'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'cislo/<int:rocnik>.<str:cislo>/obalky.pdf',
|
'cislo/<int:rocnik>.<str:cislo>/obalky.pdf',
|
||||||
org_required(views.cisloObalkyView),
|
org_required(views.cisloObalkyView),
|
||||||
name='seminar_cislo_obalky'
|
name='tvorba_cislo_obalky'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'cislo/<int:rocnik>.<str:cislo>/tituly.tex',
|
'cislo/<int:rocnik>.<str:cislo>/tituly.tex',
|
||||||
org_required(views.TitulyView),
|
org_required(views.TitulyView),
|
||||||
name='seminar_cislo_titul'
|
name='tvorba_cislo_titul'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'cislo/<int:trocnik>.<str:tcislo>/odmeny/<int:frocnik>.<str:fcislo>/',
|
'cislo/<int:trocnik>.<str:tcislo>/odmeny/<int:frocnik>.<str:fcislo>/',
|
||||||
org_required(views.OdmenyView.as_view()),
|
org_required(views.OdmenyView.as_view()),
|
||||||
name="seminar_archiv_odmeny"),
|
name="tvorba_archiv_odmeny"),
|
||||||
|
|
||||||
# Dočasné & neodladěné:
|
# Dočasné & neodladěné:
|
||||||
path(
|
path(
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
import personalni.models
|
import personalni.models
|
||||||
|
|
||||||
import seminar.models as m
|
import tvorba.models as m
|
||||||
|
|
||||||
|
|
||||||
def resi_v_rocniku(rocnik, cislo=None):
|
def resi_v_rocniku(rocnik, cislo=None):
|
||||||
|
|
|
@ -14,12 +14,11 @@ from django.db.models import Q, Sum, Count
|
||||||
from django.views.generic.base import RedirectView
|
from django.views.generic.base import RedirectView
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
|
||||||
import seminar.models as s
|
from personalni.models import Resitel
|
||||||
import seminar.models as m
|
from soustredeni.models import Konfera
|
||||||
from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, \
|
from tvorba.models import Problem, Cislo, Rocnik, Tema, Clanek, Deadline, Uloha
|
||||||
Resitel, Novinky, Tema, Clanek, \
|
from treenode.models import TemaVCisleNode, PohadkaNode
|
||||||
Deadline # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci
|
from various.models import Nastaveni
|
||||||
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
|
|
||||||
from treenode import treelib
|
from treenode import treelib
|
||||||
import treenode.templatetags as tnltt
|
import treenode.templatetags as tnltt
|
||||||
import treenode.serializers as vr
|
import treenode.serializers as vr
|
||||||
|
@ -58,7 +57,7 @@ def get_problemy_k_tematu(tema):
|
||||||
|
|
||||||
# FIXME: Pozor, níž je ještě jeden ProblemView!
|
# FIXME: Pozor, níž je ještě jeden ProblemView!
|
||||||
#class ProblemView(generic.DetailView):
|
#class ProblemView(generic.DetailView):
|
||||||
# model = s.Problem
|
# model = Problem
|
||||||
# # Zkopírujeme template_name od TreeNodeView, protože jsme prakticky jen trošku upravený TreeNodeView
|
# # Zkopírujeme template_name od TreeNodeView, protože jsme prakticky jen trošku upravený TreeNodeView
|
||||||
# template_name = TreeNodeView.template_name
|
# template_name = TreeNodeView.template_name
|
||||||
#
|
#
|
||||||
|
@ -70,17 +69,17 @@ def get_problemy_k_tematu(tema):
|
||||||
# if False:
|
# if False:
|
||||||
# # Hezčí formátování zbytku :-P
|
# # Hezčí formátování zbytku :-P
|
||||||
# pass
|
# pass
|
||||||
# elif isinstance(self.object, s.Clanek) or isinstance(self.object, s.Konfera):
|
# elif isinstance(self.object, Clanek) or isinstance(self.object, Konfera):
|
||||||
# # Tyhle Problémy mají ŘešeníNode
|
# # Tyhle Problémy mají ŘešeníNode
|
||||||
# context['tnldata'] = TNLData.from_treenode(self.object.reseninode,user)
|
# context['tnldata'] = TNLData.from_treenode(self.object.reseninode,user)
|
||||||
# elif isinstance(self.object, s.Uloha):
|
# elif isinstance(self.object, 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
|
# # 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_zadani = TNLData.from_treenode(self.object.ulohazadaninode,user)
|
||||||
# tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode,user)
|
# tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode,user)
|
||||||
# context['tnldata'] = TNLData.from_tnldata_list([tnl_zadani, tnl_vzorak])
|
# context['tnldata'] = TNLData.from_tnldata_list([tnl_zadani, tnl_vzorak])
|
||||||
# elif isinstance(self.object, s.Tema):
|
# elif isinstance(self.object, Tema):
|
||||||
# rocniknode = self.object.rocnik.rocniknode
|
# rocniknode = self.object.rocnik.rocniknode
|
||||||
# context['tnldata'] = TNLData.filter_treenode(rocniknode, lambda x: isinstance(x, s.TemaVCisleNode))
|
# context['tnldata'] = TNLData.filter_treenode(rocniknode, lambda x: isinstance(x, TemaVCisleNode))
|
||||||
# else:
|
# else:
|
||||||
# raise ValueError("Obecný problém nejde zobrazit.")
|
# raise ValueError("Obecný problém nejde zobrazit.")
|
||||||
# return context
|
# return context
|
||||||
|
@ -115,7 +114,7 @@ def ZadaniTemataView(request):
|
||||||
nastaveni = get_object_or_404(Nastaveni)
|
nastaveni = get_object_or_404(Nastaveni)
|
||||||
verejne = nastaveni.aktualni_cislo.verejne()
|
verejne = nastaveni.aktualni_cislo.verejne()
|
||||||
akt_rocnik = nastaveni.aktualni_cislo.rocnik
|
akt_rocnik = nastaveni.aktualni_cislo.rocnik
|
||||||
temata = s.Tema.objects.filter(rocnik=akt_rocnik, stav='zadany')
|
temata = Tema.objects.filter(rocnik=akt_rocnik, stav='zadany')
|
||||||
return render(request, 'tvorba/tematka/rozcestnik.html',
|
return render(request, 'tvorba/tematka/rozcestnik.html',
|
||||||
{
|
{
|
||||||
'tematka': temata,
|
'tematka': temata,
|
||||||
|
@ -140,14 +139,14 @@ def ZadaniTemataView(request):
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def TematkoView(request, rocnik, tematko):
|
#def TematkoView(request, rocnik, tematko):
|
||||||
# nastaveni = s.Nastaveni.objects.first()
|
# nastaveni = Nastaveni.objects.first()
|
||||||
# rocnik_object = s.Rocnik.objects.filter(rocnik=rocnik)
|
# rocnik_object = Rocnik.objects.filter(rocnik=rocnik)
|
||||||
# tematko_object = s.Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko)
|
# tematko_object = Tema.objects.filter(rocnik=rocnik_object[0], kod=tematko)
|
||||||
# seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode)
|
# seznam = vytahniZLesaSeznam(tematko_object[0], nastaveni.aktualni_rocnik().rocniknode)
|
||||||
# for node, depth in seznam:
|
# for node, depth in seznam:
|
||||||
# if node.isinstance(node, s.KonferaNode):
|
# if node.isinstance(node, KonferaNode): # FIXME neexistuje
|
||||||
# raise Exception("Not implemented yet")
|
# raise Exception("Not implemented yet")
|
||||||
# if node.isinstance(node, s.PohadkaNode): # Mohu ignorovat, má pod sebou
|
# if node.isinstance(node, PohadkaNode): # Mohu ignorovat, má pod sebou
|
||||||
# pass
|
# pass
|
||||||
#
|
#
|
||||||
# return render(request, 'tvorba/tematka/toaletak.html', {})
|
# return render(request, 'tvorba/tematka/toaletak.html', {})
|
||||||
|
@ -155,8 +154,8 @@ def ZadaniTemataView(request):
|
||||||
#
|
#
|
||||||
#def TemataRozcestnikView(request):
|
#def TemataRozcestnikView(request):
|
||||||
# print("=============================================")
|
# print("=============================================")
|
||||||
# nastaveni = s.Nastaveni.objects.first()
|
# nastaveni = Nastaveni.objects.first()
|
||||||
# tematka_objects = s.Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik())
|
# tematka_objects = Tema.objects.filter(rocnik=nastaveni.aktualni_rocnik())
|
||||||
# tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
|
# tematka = [] #List tematka obsahuje pro kazde tematko object a list vsech TemaVCisleNodu - implementované pomocí slovníku
|
||||||
# for tematko_object in tematka_objects:
|
# for tematko_object in tematka_objects:
|
||||||
# print("AKTUALNI TEMATKO")
|
# print("AKTUALNI TEMATKO")
|
||||||
|
@ -278,7 +277,7 @@ def resiteleRocnikuCsvExportView(request, rocnik):
|
||||||
assert request.method in ('GET', 'HEAD')
|
assert request.method in ('GET', 'HEAD')
|
||||||
return dataResiteluCsvResponse(
|
return dataResiteluCsvResponse(
|
||||||
utils.resi_v_rocniku(
|
utils.resi_v_rocniku(
|
||||||
get_object_or_404(m.Rocnik, rocnik=rocnik)
|
get_object_or_404(Rocnik, rocnik=rocnik)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -291,10 +290,10 @@ def resiteleRocnikuCsvExportView(request, rocnik):
|
||||||
# def get_template_names(self, **kwargs):
|
# 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.
|
# # 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 = {
|
# spravne_templaty = {
|
||||||
# s.Uloha: "uloha",
|
# Uloha: "uloha",
|
||||||
# s.Tema: "tema",
|
# Tema: "tema",
|
||||||
# s.Konfera: "konfera",
|
# Konfera: "konfera",
|
||||||
# s.Clanek: "clanek",
|
# Clanek: "clanek",
|
||||||
# }
|
# }
|
||||||
# context = super().get_context_data(**kwargs)
|
# context = super().get_context_data(**kwargs)
|
||||||
# return ['tvorba/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
|
# return ['tvorba/archiv/problem_' + spravne_templaty[context['object'].__class__] + '.html']
|
||||||
|
@ -340,10 +339,10 @@ class CisloView(generic.DetailView):
|
||||||
deadliny_s_vysledkovkami = []
|
deadliny_s_vysledkovkami = []
|
||||||
|
|
||||||
nadpisy = {
|
nadpisy = {
|
||||||
m.Deadline.TYP_CISLA: "Výsledkovka",
|
Deadline.TYP_CISLA: "Výsledkovka",
|
||||||
m.Deadline.TYP_PRVNI: "Výsledkovka do prvního deadlinu",
|
Deadline.TYP_PRVNI: "Výsledkovka do prvního deadlinu",
|
||||||
m.Deadline.TYP_PRVNI_A_SOUS: "Výsledkovka do prvního deadlinu a deadlinu pro účast na soustředění",
|
Deadline.TYP_PRVNI_A_SOUS: "Výsledkovka do prvního deadlinu a deadlinu pro účast na soustředění",
|
||||||
m.Deadline.TYP_SOUS: "Výsledkovka do deadlinu pro účast na soustředění",
|
Deadline.TYP_SOUS: "Výsledkovka do deadlinu pro účast na soustředění",
|
||||||
}
|
}
|
||||||
|
|
||||||
for deadline in deadliny:
|
for deadline in deadliny:
|
||||||
|
@ -577,8 +576,8 @@ class ClankyResitelView(generic.ListView):
|
||||||
|
|
||||||
class AktualniRocnikRedirectView(RedirectView):
|
class AktualniRocnikRedirectView(RedirectView):
|
||||||
permanent=False
|
permanent=False
|
||||||
pattern_name = 'seminar_rocnik'
|
pattern_name = 'tvorba_rocnik'
|
||||||
|
|
||||||
def get_redirect_url(self, *args, **kwargs):
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik.rocnik
|
aktualni_rocnik = Nastaveni.get_solo().aktualni_rocnik.rocnik
|
||||||
return super().get_redirect_url(rocnik=aktualni_rocnik, *args, **kwargs)
|
return super().get_redirect_url(rocnik=aktualni_rocnik, *args, **kwargs)
|
||||||
|
|
|
@ -5,13 +5,13 @@ from django.db import transaction
|
||||||
from django.forms import Form, CharField, IntegerField
|
from django.forms import Form, CharField, IntegerField
|
||||||
from django.views.generic import FormView
|
from django.views.generic import FormView
|
||||||
|
|
||||||
import seminar.models as m
|
from tvorba.models import Cislo, Problem, Uloha, Tema
|
||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
|
||||||
def problemView(request, pk):
|
def problemView(request, pk):
|
||||||
# Pokud problém neexistuje, hodíme obyčejnou 404
|
# Pokud problém neexistuje, hodíme obyčejnou 404
|
||||||
# Taktéž v případě, že takový problém nemá být vidět
|
# Taktéž v případě, že takový problém nemá být vidět
|
||||||
problem = get_object_or_404(m.Problem, id=pk, stav__in=[m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY])
|
problem = get_object_or_404(Problem, id=pk, stav__in=[Problem.STAV_ZADANY, Problem.STAV_VYRESENY])
|
||||||
# Problém existuje, neumíme ho zobrazit, renderujeme nějakou haluz
|
# Problém existuje, neumíme ho zobrazit, renderujeme nějakou haluz
|
||||||
template = 'universal.html'
|
template = 'universal.html'
|
||||||
ctx = {
|
ctx = {
|
||||||
|
@ -32,7 +32,7 @@ class HromadnePridaniForm(Form):
|
||||||
|
|
||||||
def clean_tema(self):
|
def clean_tema(self):
|
||||||
""" Kontrola, že `tema` je název právě jednoho tématu """
|
""" Kontrola, že `tema` je název právě jednoho tématu """
|
||||||
if m.Tema.objects.filter(
|
if Tema.objects.filter(
|
||||||
nazev__exact=self.cleaned_data['tema'],
|
nazev__exact=self.cleaned_data['tema'],
|
||||||
nadproblem=None).count() != 1:
|
nadproblem=None).count() != 1:
|
||||||
raise ValidationError("Špatný nebo nepřesně zadaný název témátka")
|
raise ValidationError("Špatný nebo nepřesně zadaný název témátka")
|
||||||
|
@ -67,20 +67,20 @@ class HromadnePridaniView(FormView):
|
||||||
dil = cd["dil"]
|
dil = cd["dil"]
|
||||||
body = list(map(int, cd["body"].split(",")))
|
body = list(map(int, cd["body"].split(",")))
|
||||||
|
|
||||||
t = m.Problem.objects.get(nazev__exact=tema, nadproblem=None)
|
t = Problem.objects.get(nazev__exact=tema, nadproblem=None)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
pfx = f"{t.nazev}, díl {dil}, "
|
pfx = f"{t.nazev}, díl {dil}, "
|
||||||
|
|
||||||
for k, b in enumerate(body, 1):
|
for k, b in enumerate(body, 1):
|
||||||
u = m.Uloha.objects.create(
|
u = Uloha.objects.create(
|
||||||
nadproblem=t,
|
nadproblem=t,
|
||||||
nazev=pfx + f"{'úloha' if b > 0 else 'problém'} {k}",
|
nazev=pfx + f"{'úloha' if b > 0 else 'problém'} {k}",
|
||||||
autor=t.autor,
|
autor=t.autor,
|
||||||
garant=t.garant,
|
garant=t.garant,
|
||||||
max_body=b,
|
max_body=b,
|
||||||
cislo_zadani=m.Cislo.get(t.rocnik.rocnik, dil),
|
cislo_zadani=Cislo.get(t.rocnik.rocnik, dil),
|
||||||
kod=k,
|
kod=k,
|
||||||
stav=m.Problem.STAV_ZADANY,
|
stav=Problem.STAV_ZADANY,
|
||||||
)
|
)
|
||||||
u.opravovatele.set(t.opravovatele.all())
|
u.opravovatele.set(t.opravovatele.all())
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
Ješte nejsi zaregistrován?
|
Ješte nejsi zaregistrován?
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<form action="{% url 'seminar_prihlaska' %}">
|
<form action="{% url 'personalni_prihlaska' %}">
|
||||||
<input type="submit" value="Registrovat" />
|
<input type="submit" value="Registrovat" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -55,5 +55,4 @@ class PasswordResetCompleteView(auth_views.PasswordResetCompleteView):
|
||||||
|
|
||||||
|
|
||||||
class PasswordChangeView(auth_views.PasswordChangeView):
|
class PasswordChangeView(auth_views.PasswordChangeView):
|
||||||
# template_name = 'seminar/password_change.html'
|
|
||||||
success_url = reverse_lazy('titulni_strana')
|
success_url = reverse_lazy('titulni_strana')
|
||||||
|
|
|
@ -12,8 +12,8 @@ class StripSensitiveFormDataFilter(Filter):
|
||||||
if hasattr(record, 'request') and record.request.path in [
|
if hasattr(record, 'request') and record.request.path in [
|
||||||
reverse('login'),
|
reverse('login'),
|
||||||
reverse('logout'),
|
reverse('logout'),
|
||||||
reverse('seminar_prihlaska'),
|
reverse('personalni_prihlaska'),
|
||||||
reverse('seminar_resitel_edit'),
|
reverse('personalni_resitel_edit'),
|
||||||
reverse('reset_password'),
|
reverse('reset_password'),
|
||||||
reverse('reset_password_done'),
|
reverse('reset_password_done'),
|
||||||
# FIXME
|
# FIXME
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from seminar.models import Cislo
|
from tvorba.models import Cislo
|
||||||
|
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
import seminar.models as m
|
from tvorba.models import Deadline
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Všem deadlinům se zveřejněnou výsledkovkou vygeneruj výsledkovku"
|
help = "Všem deadlinům se zveřejněnou výsledkovkou vygeneruj výsledkovku"
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
for deadline in m.Deadline.objects.filter(verejna_vysledkovka=True):
|
for deadline in Deadline.objects.filter(verejna_vysledkovka=True):
|
||||||
deadline.vygeneruj_vysledkovku()
|
deadline.vygeneruj_vysledkovku()
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@ from django.core.management.base import BaseCommand
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni
|
from odevzdavatko.models import Reseni
|
||||||
|
from personalni.models import Skola, Resitel
|
||||||
|
from tvorba.models import Rocnik, Cislo, Problem
|
||||||
from various.testutils import create_test_data
|
from various.testutils import create_test_data
|
||||||
import django.contrib.auth
|
import django.contrib.auth
|
||||||
User = django.contrib.auth.get_user_model()
|
User = django.contrib.auth.get_user_model()
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
import os
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.core.files.storage import FileSystemStorage
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
from solo.models import SingletonModel
|
from solo.models import SingletonModel
|
||||||
|
|
||||||
from tvorba.models import Cislo
|
|
||||||
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
@reversion.register(ignore_duplicates=True)
|
@reversion.register(ignore_duplicates=True)
|
||||||
class Nastaveni(SingletonModel):
|
class Nastaveni(SingletonModel):
|
||||||
|
@ -14,10 +15,10 @@ class Nastaveni(SingletonModel):
|
||||||
db_table = 'seminar_nastaveni'
|
db_table = 'seminar_nastaveni'
|
||||||
verbose_name = 'Nastavení semináře'
|
verbose_name = 'Nastavení semináře'
|
||||||
|
|
||||||
# aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name='aktuální ročník',
|
# aktualni_rocnik = models.ForeignKey("tvorba.Rocnik", verbose_name='aktuální ročník',
|
||||||
# null=False, on_delete=models.PROTECT)
|
# null=False, on_delete=models.PROTECT)
|
||||||
|
|
||||||
aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo',
|
aktualni_cislo = models.ForeignKey("tvorba.Cislo", verbose_name='Aktuální číslo',
|
||||||
null=True, blank=False, on_delete=models.PROTECT,
|
null=True, blank=False, on_delete=models.PROTECT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,3 +38,28 @@ class Nastaveni(SingletonModel):
|
||||||
|
|
||||||
def verejne(self):
|
def verejne(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class OverwriteStorage(FileSystemStorage):
|
||||||
|
""" Varianta FileSystemStorage, která v případě, že soubor cílového
|
||||||
|
jména již existuje, ho smaže a místo něj uloží soubor nový"""
|
||||||
|
def get_available_name(self,name, max_length=None):
|
||||||
|
if self.exists(name):
|
||||||
|
os.remove(os.path.join(self.location,name))
|
||||||
|
return super().get_available_name(name,max_length)
|
||||||
|
|
||||||
|
|
||||||
|
class SeminarModelBase(models.Model):
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
def verejne(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# def get_absolute_url(self):
|
||||||
|
# return "https://" + str(get_current_site(None)) + self.verejne_url()
|
||||||
|
|
||||||
|
def admin_url(self):
|
||||||
|
app_name = self._meta.app_label
|
||||||
|
model_name = self._meta.model_name
|
||||||
|
return reverse('admin:{}_{}_change'.format(app_name, model_name), args=(self.id, ))
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
Na této stránce velmi intenzivně pracujeme.
|
Na této stránce velmi intenzivně pracujeme.
|
||||||
Za dočasnou nedostupnost se omlouváme.
|
Za dočasnou nedostupnost se omlouváme.
|
||||||
Zkuste přejít na <a href="/">titulní stránku</a>
|
Zkuste přejít na <a href="/">titulní stránku</a>
|
||||||
nebo se podívat na <a href="{% url 'seminar_aktualni_zadani' %}">aktuální zadání</a>.
|
nebo se podívat na <a href="{% url 'tvorba_aktualni_zadani' %}">aktuální zadání</a>.
|
||||||
</p>
|
</p>
|
||||||
<img src="{% static '404.png' %}">
|
<img src="{% static '404.png' %}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -7,7 +7,9 @@ from django.contrib.flatpages.models import FlatPage
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
from seminar.models import Rocnik, Cislo, Nastaveni, Osoba, Organizator
|
from personalni.models import Osoba, Organizator
|
||||||
|
from tvorba.models import Rocnik, Cislo
|
||||||
|
from various.models import Nastaveni
|
||||||
|
|
||||||
from korektury.testutils import create_test_pdf
|
from korektury.testutils import create_test_pdf
|
||||||
from novinky.testutils import gen_novinky
|
from novinky.testutils import gen_novinky
|
||||||
|
|
|
@ -14,8 +14,10 @@ from django.views import generic
|
||||||
import novinky.views
|
import novinky.views
|
||||||
import treenode.treelib as t
|
import treenode.treelib as t
|
||||||
import tvorba.views
|
import tvorba.views
|
||||||
from personalni.models import Resitel
|
|
||||||
from seminar import models as m
|
from treenode.models import CisloNode
|
||||||
|
from personalni.models import Resitel, Osoba
|
||||||
|
from tvorba.models import Clanek, Deadline
|
||||||
|
|
||||||
from ..models import Nastaveni
|
from ..models import Nastaveni
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ class TitulniStranaView(generic.ListView):
|
||||||
context = super(TitulniStranaView, self).get_context_data(**kwargs)
|
context = super(TitulniStranaView, self).get_context_data(**kwargs)
|
||||||
nastaveni = get_object_or_404(Nastaveni)
|
nastaveni = get_object_or_404(Nastaveni)
|
||||||
|
|
||||||
deadline = m.Deadline.objects.filter(
|
deadline = Deadline.objects.filter(
|
||||||
deadline__gte=timezone.now()).order_by("deadline").first()
|
deadline__gte=timezone.now()).order_by("deadline").first()
|
||||||
context['nejblizsi_deadline'] = deadline
|
context['nejblizsi_deadline'] = deadline
|
||||||
|
|
||||||
|
@ -93,31 +95,31 @@ def seznam_problemu():
|
||||||
|
|
||||||
# Duplicita jmen
|
# Duplicita jmen
|
||||||
jmena = {}
|
jmena = {}
|
||||||
for r in m.Resitel.objects.all():
|
for r in Resitel.objects.all():
|
||||||
j = r.osoba.plne_jmeno()
|
j = r.osoba.plne_jmeno()
|
||||||
if j not in jmena:
|
if j not in jmena:
|
||||||
jmena[j] = []
|
jmena[j] = []
|
||||||
jmena[j].append(r)
|
jmena[j].append(r)
|
||||||
for j in jmena:
|
for j in jmena:
|
||||||
if len(jmena[j]) > 1:
|
if len(jmena[j]) > 1:
|
||||||
prb(m.Resitel, 'Duplicitní jméno "%s"' % (j,), jmena[j])
|
prb(Resitel, 'Duplicitní jméno "%s"' % (j,), jmena[j])
|
||||||
|
|
||||||
# Data maturity a narození
|
# Data maturity a narození
|
||||||
for r in m.Resitel.objects.all():
|
for r in Resitel.objects.all():
|
||||||
if not r.rok_maturity:
|
if not r.rok_maturity:
|
||||||
prb(m.Resitel, 'Neznámý rok maturity', [r])
|
prb(Resitel, 'Neznámý rok maturity', [r])
|
||||||
if r.rok_maturity and (r.rok_maturity < 1990 or r.rok_maturity > datetime.date.today().year + 10):
|
if r.rok_maturity and (r.rok_maturity < 1990 or r.rok_maturity > datetime.date.today().year + 10):
|
||||||
prb(m.Resitel, 'Podezřelé datum maturity', [r])
|
prb(Resitel, 'Podezřelé datum maturity', [r])
|
||||||
if r.osoba.datum_narozeni and (
|
if r.osoba.datum_narozeni and (
|
||||||
r.osoba.datum_narozeni.year < 1970 or r.osoba.datum_narozeni.year > datetime.date.today().year - 12):
|
r.osoba.datum_narozeni.year < 1970 or r.osoba.datum_narozeni.year > datetime.date.today().year - 12):
|
||||||
prb(m.Resitel, 'Podezřelé datum narození', [r])
|
prb(Resitel, 'Podezřelé datum narození', [r])
|
||||||
# if not r.email:
|
# if not r.email:
|
||||||
# prb(Resitel, u'Neznámý email', [r])
|
# prb(Resitel, u'Neznámý email', [r])
|
||||||
|
|
||||||
## Kontroly konzistence databáze a TreeNodů
|
## Kontroly konzistence databáze a TreeNodů
|
||||||
|
|
||||||
# Články
|
# Články
|
||||||
for clanek in m.Clanek.objects.all():
|
for clanek in Clanek.objects.all():
|
||||||
# získáme řešení svázané se článkem a z něj node ve stromě
|
# získáme řešení svázané se článkem a z něj node ve stromě
|
||||||
reseni = clanek.reseni_set
|
reseni = clanek.reseni_set
|
||||||
if (reseni.count() != 1):
|
if (reseni.count() != 1):
|
||||||
|
@ -127,7 +129,7 @@ def seznam_problemu():
|
||||||
# content type je věc pomáhající rozeznávat různé typy objektů v django-polymorphic
|
# content type je věc pomáhající rozeznávat různé typy objektů v django-polymorphic
|
||||||
# protože isinstance vrátí vždy jen TreeNode
|
# protože isinstance vrátí vždy jen TreeNode
|
||||||
# https://django-polymorphic.readthedocs.io/en/stable/migrating.html
|
# https://django-polymorphic.readthedocs.io/en/stable/migrating.html
|
||||||
cislonode_ct = ContentType.objects.get_for_model(m.CisloNode)
|
cislonode_ct = ContentType.objects.get_for_model(CisloNode)
|
||||||
node = clanek_node
|
node = clanek_node
|
||||||
while node is not None:
|
while node is not None:
|
||||||
node_ct = node.polymorphic_ctype
|
node_ct = node.polymorphic_ctype
|
||||||
|
@ -136,7 +138,7 @@ def seznam_problemu():
|
||||||
# .cislonode je opačná vazba k treenode_ptr, abychom z TreeNode dostali
|
# .cislonode je opačná vazba k treenode_ptr, abychom z TreeNode dostali
|
||||||
# CisloNode
|
# CisloNode
|
||||||
if clanek.cislo != node.cislonode.cislo:
|
if clanek.cislo != node.cislonode.cislo:
|
||||||
prb(m.Clanek, "Číslo otištění uložené u článku nesedí s "
|
prb(Clanek, "Číslo otištění uložené u článku nesedí s "
|
||||||
"číslem otištění podle struktury treenodů.", [clanek])
|
"číslem otištění podle struktury treenodů.", [clanek])
|
||||||
break
|
break
|
||||||
node = t.get_parent(node)
|
node = t.get_parent(node)
|
||||||
|
@ -146,8 +148,8 @@ def seznam_problemu():
|
||||||
def StavDatabazeView(request):
|
def StavDatabazeView(request):
|
||||||
# nastaveni = Nastaveni.objects.get()
|
# nastaveni = Nastaveni.objects.get()
|
||||||
problemy = seznam_problemu()
|
problemy = seznam_problemu()
|
||||||
muzi = Resitel.objects.filter(osoba__osloveni=m.Osoba.OSLOVENI_MUZSKE)
|
muzi = Resitel.objects.filter(osoba__osloveni=Osoba.OSLOVENI_MUZSKE)
|
||||||
zeny = Resitel.objects.filter(osoba__osloveni=m.Osoba.OSLOVENI_ZENSKE)
|
zeny = Resitel.objects.filter(osoba__osloveni=Osoba.OSLOVENI_ZENSKE)
|
||||||
return render(request, 'various/stav_databaze.html', {
|
return render(request, 'various/stav_databaze.html', {
|
||||||
# 'nastaveni': nastaveni,
|
# 'nastaveni': nastaveni,
|
||||||
'problemy': problemy,
|
'problemy': problemy,
|
||||||
|
|
|
@ -17,7 +17,7 @@ def formularOKView(request, text='', dalsi_odkazy: Sequence[tuple[str, str]] = (
|
||||||
odkazy = list(dalsi_odkazy) + [
|
odkazy = list(dalsi_odkazy) + [
|
||||||
# (Text, odkaz)
|
# (Text, odkaz)
|
||||||
('Vrátit se na titulní stránku', reverse('titulni_strana')),
|
('Vrátit se na titulní stránku', reverse('titulni_strana')),
|
||||||
('Zobrazit aktuální zadání', reverse('seminar_aktualni_zadani')),
|
('Zobrazit aktuální zadání', reverse('tvorba_aktualni_zadani')),
|
||||||
]
|
]
|
||||||
context = {
|
context = {
|
||||||
'odkazy': odkazy,
|
'odkazy': odkazy,
|
||||||
|
|
|
@ -17,9 +17,9 @@ module.exports = {
|
||||||
filenameHashing: false,
|
filenameHashing: false,
|
||||||
productionSourceMap: true,
|
productionSourceMap: true,
|
||||||
publicPath: process.env.NODE_ENV === 'production'
|
publicPath: process.env.NODE_ENV === 'production'
|
||||||
? '/static/seminar/vue/'
|
? '/static/treenode/vue/'
|
||||||
: 'http://localhost:8080/',
|
: 'http://localhost:8080/',
|
||||||
outputDir: '../seminar/static/seminar/vue/',
|
outputDir: '../treenode/static/treenode/vue/',
|
||||||
|
|
||||||
chainWebpack: config => {
|
chainWebpack: config => {
|
||||||
|
|
||||||
|
|