From cd6ae46570312f649d12656332d4df45ea9dc14c Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 23 Feb 2021 22:13:14 +0100 Subject: [PATCH 01/16] =?UTF-8?q?Filtrov=C3=A1n=C3=AD:=20frontend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/forms.py | 74 +++++++++++++++++++ .../seminar/odevzdavatko/tabulka.html | 8 ++ seminar/views/odevzdavatko.py | 5 ++ 3 files changed, 87 insertions(+) diff --git a/seminar/forms.py b/seminar/forms.py index c64095c6..39714fae 100644 --- a/seminar/forms.py +++ b/seminar/forms.py @@ -316,3 +316,77 @@ class JednoHodnoceniForm(forms.ModelForm): OhodnoceniReseniFormSet = formset_factory(JednoHodnoceniForm, extra = 0, ) + +# FIXME: Ideálně by mělo být součástí třídy níž, ale neumím to udělat +DATE_FORMAT = '%Y-%m-%d' + +class OdevzdavatkoTabulkaFiltrForm(forms.Form): + """Form pro filtrování přehledové odevzdávátkové tabulky + + Inspirováno https://kam.mff.cuni.cz/mffzoom/""" + + # Věci definované níž se importují i ve views pro odevzdávátko (Inspirováno https://docs.djangoproject.com/en/3.1/ref/models/fields/#field-choices) + + RESITELE_RELEVANTNI = 'relevantni' + RESITELE_LETOSNI = 'letosni' + RESITELE_CHOICES = [ + (RESITELE_RELEVANTNI, 'Relevantní řešitelé'), # I.e. nezobrazovat prázdné řádky tabulky + (RESITELE_LETOSNI, 'Všichni letošní'), + # Možná: všechny vč. historických? + ] + + PROBLEMY_MOJE = 'moje' + PROBLEMY_LETOSNI = 'letosni' + PROBLEMY_CHOICES = [ + (PROBLEMY_MOJE, 'Moje problémy'), # Letošní problémy, které mají v sobě nebo v nadproblémech přiřazeného daného orga + (PROBLEMY_LETOSNI, 'Všechny letošní'), + # TODO: *hlavní problémy, možná všechny... + # XXX: Chtělo by to i "aktuálně zadané... + ] + + # TODO: Typy problémů (problémy, úlohy, ostatní, všechny)? Jen některá řešení (obodovaná/neobodovaná, víc řešitelů, ...)? + + + def gen_terminy(): + import datetime + from time import strftime + + aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik + aktualni_cislo = m.Nastaveni.get_solo().aktualni_cislo + + result = [] + + for cislo in m.Cislo.objects.filter( + rocnik=aktualni_rocnik, + poradi__lte=aktualni_cislo.poradi, + ).reverse(): # Standardně se řadí od nejnovějšího čísla + # Předem je mi líto kohokoliv, kdo tyhle řádky bude číst... + if cislo.datum_vydani is not None and cislo.datum_vydani <= datetime.date.today(): + result.append(( + strftime(DATE_FORMAT, cislo.datum_vydani.timetuple()), + f"Vydání {cislo.poradi}. čísla")) + if cislo.datum_preddeadline is not None and cislo.datum_preddeadline <= datetime.date.today(): + result.append(( + strftime(DATE_FORMAT, cislo.datum_preddeadline.timetuple()), + f"Předdeadline {cislo.poradi}. čísla")) + if cislo.datum_deadline_soustredeni is not None and cislo.datum_deadline_soustredeni <= datetime.date.today(): + result.append(( + strftime(DATE_FORMAT, cislo.datum_deadline_soustredeni.timetuple()), + f"Sous. deadline {cislo.poradi}. čísla")) + if cislo.datum_deadline is not None and cislo.datum_deadline <= datetime.date.today(): + result.append(( + strftime(DATE_FORMAT, cislo.datum_deadline.timetuple()), + f"Finální deadline {cislo.poradi}. čísla")) + result.append(( + strftime(DATE_FORMAT, datetime.date.today().timetuple()), f"Dnes")) + + return result + + # NOTE: Initial definuji pro jednotlivé fieldy, aby to bylo tady a nebylo potřeba to řešit ve views... + resitele = forms.ChoiceField(choices=RESITELE_CHOICES, initial=RESITELE_RELEVANTNI) + problemy = forms.ChoiceField(choices=PROBLEMY_CHOICES, initial=PROBLEMY_MOJE) + + # choices jako parametr Select widgetu neumí brát callable, jen iterable, takže si pro jednoduchost můžu rovnou uložit výsledek sem... + terminy = gen_terminy() + reseni_od = forms.DateField(input_formats=[DATE_FORMAT], widget=forms.Select(choices=terminy), initial=terminy[-2]) + reseni_do = forms.DateField(input_formats=[DATE_FORMAT], widget=forms.Select(choices=terminy), initial=terminy[-1]) diff --git a/seminar/templates/seminar/odevzdavatko/tabulka.html b/seminar/templates/seminar/odevzdavatko/tabulka.html index ff396ce4..26a6f922 100644 --- a/seminar/templates/seminar/odevzdavatko/tabulka.html +++ b/seminar/templates/seminar/odevzdavatko/tabulka.html @@ -4,6 +4,14 @@ {% block content %} +
+{{ filtr.resitele }} +{{ filtr.problemy }} +Od: {{ filtr.reseni_od }} +Do: {{ filtr.reseni_do }} + +
+ {# Prázdná buňka v levém horním rohu #} diff --git a/seminar/views/odevzdavatko.py b/seminar/views/odevzdavatko.py index e81f119f..214893af 100644 --- a/seminar/views/odevzdavatko.py +++ b/seminar/views/odevzdavatko.py @@ -100,6 +100,11 @@ class TabulkaOdevzdanychReseniView(ListView): hodnoty.append(resiteluv_radek) ctx['radky'] = list(zip(self.resitele, hodnoty)) + from seminar.forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm + ctx['filtr'] = FiltrForm() + # Pro použití hacku na automatické {{form.media}} v template: + ctx['form'] = ctx['filtr'] + return ctx # Velmi silně inspirováno zdrojáky, FIXME: Nedá se to udělat smysluplněji? From 629c95e62cc6418f37fcb3bd715153ad5b8353a1 Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 2 Mar 2021 22:20:08 +0100 Subject: [PATCH 02/16] =?UTF-8?q?=C5=A0patn=C3=A9=20importy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/views/views_all.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index 7c1d2370..032e9380 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -29,7 +29,7 @@ from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm import seminar.forms as f import seminar.templatetags.treenodes as tnltt import seminar.views.views_rest as vr -from seminar.views.vysledkovka import vysledkovka_rocniku, vysledkovka_cisla +from seminar.views.vysledkovka import vysledkovka_rocniku, vysledkovka_cisla, body_resitelu from datetime import timedelta, date, datetime, MAXYEAR from django.utils import timezone @@ -185,7 +185,7 @@ class TNLData(object): return [cls.from_treenode(treenode)] else: found = [] - for tn in all_children(treenode): + for tn in treelib.all_children(treenode): result = cls.filter_treenode(tn, predicate) # Result by v tuhle chvíli měl být seznam TNLDat odpovídající treenodům, jež matchnuly predikát. for tnl in result: From a2bd452520ac5dd8d2778c7d2bb9ce2d4daf7699 Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 2 Mar 2021 22:34:42 +0100 Subject: [PATCH 03/16] =?UTF-8?q?url=20v=C3=BDsledkovky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/sitetree.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/sitetree.json b/data/sitetree.json index 3445dd59..1f58d744 100644 --- a/data/sitetree.json +++ b/data/sitetree.json @@ -337,8 +337,8 @@ "sort_order": 33, "title": "Výsledková listina", "tree": 1, - "url": "zadani/vysledkova-listina/", - "urlaspattern": false + "url": "seminar_aktualni_vysledky", + "urlaspattern": true }, "model": "sitetree.treeitem", "pk": 16 From e3b8ff716e2678417fb162ea3d1bc239a21c31f5 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 2 Mar 2021 22:46:43 +0100 Subject: [PATCH 04/16] =?UTF-8?q?Odevzd=C3=A1vac=C3=AD=20tabulka=20v0.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/views/odevzdavatko.py | 53 ++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/seminar/views/odevzdavatko.py b/seminar/views/odevzdavatko.py index 214893af..d1cedb1b 100644 --- a/seminar/views/odevzdavatko.py +++ b/seminar/views/odevzdavatko.py @@ -12,6 +12,7 @@ import logging import seminar.models as m import seminar.forms as f +from seminar.forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm from seminar.utils import aktivniResitele, resi_v_rocniku logger = logging.getLogger(__name__) @@ -41,28 +42,55 @@ class TabulkaOdevzdanychReseniView(ListView): def inicializuj_osy_tabulky(self): """Vyrobí prvotní querysety pro sloupce a řádky, tj. seznam všech řešitelů a problémů""" + # 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 # TODO: Prefetches, Select related, ... self.resitele = m.Resitel.objects.all() self.problemy = m.Problem.objects.all() + self.reseni = m.Reseni.objects.all() + + form = FiltrForm(self.request.GET) + if form.is_valid(): + fcd = form.cleaned_data + resitele = fcd["resitele"] + problemy = fcd["problemy"] + reseni_od = fcd["reseni_od"] + reseni_do = fcd["reseni_do"] + else: + resitele = FiltrForm.get_initial_for_field(FormFiltr.resitele, "resitele") + problemy = FiltrForm.get_initial_for_field(FormFiltr.problemy, "problemy") + resitele_od = FiltrForm.get_initial_for_field(FormFiltr.resitele_od, "resitele_od") + resitele_do = FiltrForm.get_initial_for_field(FormFiltr.resitele_do, "resitele_do") + - def get_queryset(self): - self.inicializuj_osy_tabulky() - self.akt_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci, asi... - self.resitele = resi_v_rocniku(self.akt_rocnik) + # Filtrujeme! + aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci + if resitele == FiltrForm.RESITELE_RELEVANTNI: + logger.warning("Někdo chtěl v tabulce jen relevantní řešitele a měl smůlu :-(") + resitele = FiltrForm.RESITELE_LETOSNI # Fall-through + elif resitele == FiltrForm.RESITELE_LETOSNI: + self.resitele = resi_v_rocniku(aktualni_rocnik) + + if problemy == FiltrForm.PROBLEMY_MOJE: + org = m.Organizator.objects.get(osoba__user=self.request.user) + from django.db.models import Q + self.problemy = self.problemy.filter(Q(autor=org)|Q(garant=org)|Q(opravovatele=org), stav=m.Problem.STAV_ZADANY) + elif problemy == FiltrForm.PROBLEMY_LETOSNI: + self.problemy = self.problemy.filter(stav=m.Problem.STAV_ZADANY) + #self.problemy = list(filter(lambda problem: problem.rocnik() == 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. - self.problemy = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY).non_polymorphic() + self.problemy = self.problemy.non_polymorphic() + + self.reseni = self.reseni.filter(cas_doruceni__date__gte=reseni_od, cas_doruceni__date__lte=reseni_do) + def get_queryset(self): + self.inicializuj_osy_tabulky() qs = super().get_queryset() - qs = qs.filter(problem__in=self.problemy).select_related('reseni', 'problem').prefetch_related('reseni__resitele__osoba') + qs = qs.filter(problem__in=self.problemy, reseni__in=self.reseni, reseni__resitele__in=self.resitele).select_related('reseni', 'problem').prefetch_related('reseni__resitele__osoba') return qs def get_context_data(self, *args, **kwargs): - # FIXME: Tenhle blok nemůže být přímo ve třídě, protože před vyrobením databáze neexistuje Nastavení. - self.akt_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci, asi... - self.resitele = resi_v_rocniku(self.akt_rocnik) - # 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. - self.problemy = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY).non_polymorphic() + # self.resitele, self.reseni a self.problemy jsou již nastavené ctx = super().get_context_data(*args, **kwargs) ctx['problemy'] = self.problemy @@ -100,8 +128,7 @@ class TabulkaOdevzdanychReseniView(ListView): hodnoty.append(resiteluv_radek) ctx['radky'] = list(zip(self.resitele, hodnoty)) - from seminar.forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm - ctx['filtr'] = FiltrForm() + ctx['filtr'] = FiltrForm(initial=self.request.GET) # Pro použití hacku na automatické {{form.media}} v template: ctx['form'] = ctx['filtr'] From f4fadcd775b9980a0f009828744c5a5b274d32dd Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 2 Mar 2021 22:50:31 +0100 Subject: [PATCH 05/16] =?UTF-8?q?odstran=C4=9Bn=20n=C3=A1hodn=C3=BD=20do?= =?UTF-8?q?=C4=8Dasn=C3=BD=20soubor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/.~lock.profile_vysledkovka.txt# | 1 - 1 file changed, 1 deletion(-) delete mode 100644 seminar/.~lock.profile_vysledkovka.txt# diff --git a/seminar/.~lock.profile_vysledkovka.txt# b/seminar/.~lock.profile_vysledkovka.txt# deleted file mode 100644 index cf1b89b4..00000000 --- a/seminar/.~lock.profile_vysledkovka.txt# +++ /dev/null @@ -1 +0,0 @@ -,anet,erebus,25.03.2020 22:21,file:///home/anet/.config/libreoffice/4; \ No newline at end of file From b5ae76a5a4b86e306d87079863d0930227974ddd Mon Sep 17 00:00:00 2001 From: "Tomas \"Jethro\" Pokorny" Date: Tue, 2 Mar 2021 23:03:40 +0100 Subject: [PATCH 06/16] Pridany contenttypes. --- data/contenttypes.json | 530 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 530 insertions(+) create mode 100644 data/contenttypes.json diff --git a/data/contenttypes.json b/data/contenttypes.json new file mode 100644 index 00000000..954fd4b8 --- /dev/null +++ b/data/contenttypes.json @@ -0,0 +1,530 @@ +[ + { + "fields": { + "app_label": "seminar", + "model": "treenode" + }, + "model": "contenttypes.contenttype", + "pk": 1 + }, + { + "fields": { + "app_label": "seminar", + "model": "problem" + }, + "model": "contenttypes.contenttype", + "pk": 2 + }, + { + "fields": { + "app_label": "seminar", + "model": "rocniknode" + }, + "model": "contenttypes.contenttype", + "pk": 3 + }, + { + "fields": { + "app_label": "seminar", + "model": "cislonode" + }, + "model": "contenttypes.contenttype", + "pk": 4 + }, + { + "fields": { + "app_label": "seminar", + "model": "mezicislonode" + }, + "model": "contenttypes.contenttype", + "pk": 5 + }, + { + "fields": { + "app_label": "seminar", + "model": "temavcislenode" + }, + "model": "contenttypes.contenttype", + "pk": 6 + }, + { + "fields": { + "app_label": "seminar", + "model": "orgtextnode" + }, + "model": "contenttypes.contenttype", + "pk": 7 + }, + { + "fields": { + "app_label": "seminar", + "model": "ulohazadaninode" + }, + "model": "contenttypes.contenttype", + "pk": 8 + }, + { + "fields": { + "app_label": "seminar", + "model": "ulohavzoraknode" + }, + "model": "contenttypes.contenttype", + "pk": 9 + }, + { + "fields": { + "app_label": "seminar", + "model": "pohadkanode" + }, + "model": "contenttypes.contenttype", + "pk": 10 + }, + { + "fields": { + "app_label": "seminar", + "model": "textnode" + }, + "model": "contenttypes.contenttype", + "pk": 11 + }, + { + "fields": { + "app_label": "seminar", + "model": "castnode" + }, + "model": "contenttypes.contenttype", + "pk": 12 + }, + { + "fields": { + "app_label": "seminar", + "model": "reseninode" + }, + "model": "contenttypes.contenttype", + "pk": 13 + }, + { + "fields": { + "app_label": "seminar", + "model": "tema" + }, + "model": "contenttypes.contenttype", + "pk": 14 + }, + { + "fields": { + "app_label": "seminar", + "model": "clanek" + }, + "model": "contenttypes.contenttype", + "pk": 15 + }, + { + "fields": { + "app_label": "seminar", + "model": "uloha" + }, + "model": "contenttypes.contenttype", + "pk": 16 + }, + { + "fields": { + "app_label": "auth", + "model": "user" + }, + "model": "contenttypes.contenttype", + "pk": 17 + }, + { + "fields": { + "app_label": "contenttypes", + "model": "contenttype" + }, + "model": "contenttypes.contenttype", + "pk": 18 + }, + { + "fields": { + "app_label": "sessions", + "model": "session" + }, + "model": "contenttypes.contenttype", + "pk": 19 + }, + { + "fields": { + "app_label": "sites", + "model": "site" + }, + "model": "contenttypes.contenttype", + "pk": 20 + }, + { + "fields": { + "app_label": "auth", + "model": "permission" + }, + "model": "contenttypes.contenttype", + "pk": 21 + }, + { + "fields": { + "app_label": "auth", + "model": "group" + }, + "model": "contenttypes.contenttype", + "pk": 22 + }, + { + "fields": { + "app_label": "reversion", + "model": "revision" + }, + "model": "contenttypes.contenttype", + "pk": 23 + }, + { + "fields": { + "app_label": "reversion", + "model": "version" + }, + "model": "contenttypes.contenttype", + "pk": 24 + }, + { + "fields": { + "app_label": "taggit", + "model": "tag" + }, + "model": "contenttypes.contenttype", + "pk": 25 + }, + { + "fields": { + "app_label": "taggit", + "model": "taggeditem" + }, + "model": "contenttypes.contenttype", + "pk": 26 + }, + { + "fields": { + "app_label": "fluent_comments", + "model": "fluentcomment" + }, + "model": "contenttypes.contenttype", + "pk": 27 + }, + { + "fields": { + "app_label": "threadedcomments", + "model": "threadedcomment" + }, + "model": "contenttypes.contenttype", + "pk": 28 + }, + { + "fields": { + "app_label": "django_comments", + "model": "comment" + }, + "model": "contenttypes.contenttype", + "pk": 29 + }, + { + "fields": { + "app_label": "django_comments", + "model": "commentflag" + }, + "model": "contenttypes.contenttype", + "pk": 30 + }, + { + "fields": { + "app_label": "flatpages", + "model": "flatpage" + }, + "model": "contenttypes.contenttype", + "pk": 31 + }, + { + "fields": { + "app_label": "sitetree", + "model": "tree" + }, + "model": "contenttypes.contenttype", + "pk": 32 + }, + { + "fields": { + "app_label": "sitetree", + "model": "treeitem" + }, + "model": "contenttypes.contenttype", + "pk": 33 + }, + { + "fields": { + "app_label": "seminar", + "model": "cislo" + }, + "model": "contenttypes.contenttype", + "pk": 34 + }, + { + "fields": { + "app_label": "seminar", + "model": "resitel" + }, + "model": "contenttypes.contenttype", + "pk": 35 + }, + { + "fields": { + "app_label": "seminar", + "model": "rocnik" + }, + "model": "contenttypes.contenttype", + "pk": 36 + }, + { + "fields": { + "app_label": "seminar", + "model": "skola" + }, + "model": "contenttypes.contenttype", + "pk": 37 + }, + { + "fields": { + "app_label": "seminar", + "model": "soustredeni" + }, + "model": "contenttypes.contenttype", + "pk": 38 + }, + { + "fields": { + "app_label": "seminar", + "model": "reseni" + }, + "model": "contenttypes.contenttype", + "pk": 39 + }, + { + "fields": { + "app_label": "seminar", + "model": "prilohareseni" + }, + "model": "contenttypes.contenttype", + "pk": 40 + }, + { + "fields": { + "app_label": "seminar", + "model": "nastaveni" + }, + "model": "contenttypes.contenttype", + "pk": 41 + }, + { + "fields": { + "app_label": "seminar", + "model": "soustredeni_ucastnici" + }, + "model": "contenttypes.contenttype", + "pk": 42 + }, + { + "fields": { + "app_label": "seminar", + "model": "novinky" + }, + "model": "contenttypes.contenttype", + "pk": 43 + }, + { + "fields": { + "app_label": "seminar", + "model": "organizator" + }, + "model": "contenttypes.contenttype", + "pk": 44 + }, + { + "fields": { + "app_label": "seminar", + "model": "soustredeni_organizatori" + }, + "model": "contenttypes.contenttype", + "pk": 45 + }, + { + "fields": { + "app_label": "seminar", + "model": "konfera" + }, + "model": "contenttypes.contenttype", + "pk": 46 + }, + { + "fields": { + "app_label": "seminar", + "model": "osoba" + }, + "model": "contenttypes.contenttype", + "pk": 47 + }, + { + "fields": { + "app_label": "seminar", + "model": "prijemce" + }, + "model": "contenttypes.contenttype", + "pk": 48 + }, + { + "fields": { + "app_label": "seminar", + "model": "text" + }, + "model": "contenttypes.contenttype", + "pk": 49 + }, + { + "fields": { + "app_label": "seminar", + "model": "pohadka" + }, + "model": "contenttypes.contenttype", + "pk": 50 + }, + { + "fields": { + "app_label": "seminar", + "model": "reseni_resitele" + }, + "model": "contenttypes.contenttype", + "pk": 51 + }, + { + "fields": { + "app_label": "seminar", + "model": "obrazek" + }, + "model": "contenttypes.contenttype", + "pk": 52 + }, + { + "fields": { + "app_label": "seminar", + "model": "hodnoceni" + }, + "model": "contenttypes.contenttype", + "pk": 53 + }, + { + "fields": { + "app_label": "seminar", + "model": "konfery_ucastnici" + }, + "model": "contenttypes.contenttype", + "pk": 54 + }, + { + "fields": { + "app_label": "galerie", + "model": "galerie" + }, + "model": "contenttypes.contenttype", + "pk": 55 + }, + { + "fields": { + "app_label": "galerie", + "model": "obrazek" + }, + "model": "contenttypes.contenttype", + "pk": 56 + }, + { + "fields": { + "app_label": "korektury", + "model": "korekturovanepdf" + }, + "model": "contenttypes.contenttype", + "pk": 57 + }, + { + "fields": { + "app_label": "korektury", + "model": "oprava" + }, + "model": "contenttypes.contenttype", + "pk": 58 + }, + { + "fields": { + "app_label": "korektury", + "model": "komentar" + }, + "model": "contenttypes.contenttype", + "pk": 59 + }, + { + "fields": { + "app_label": "prednasky", + "model": "hlasovani" + }, + "model": "contenttypes.contenttype", + "pk": 60 + }, + { + "fields": { + "app_label": "prednasky", + "model": "prednaska" + }, + "model": "contenttypes.contenttype", + "pk": 61 + }, + { + "fields": { + "app_label": "prednasky", + "model": "seznam" + }, + "model": "contenttypes.contenttype", + "pk": 62 + }, + { + "fields": { + "app_label": "header_fotky", + "model": "fotkaheader" + }, + "model": "contenttypes.contenttype", + "pk": 63 + }, + { + "fields": { + "app_label": "header_fotky", + "model": "fotkaurlvazba" + }, + "model": "contenttypes.contenttype", + "pk": 64 + }, + { + "fields": { + "app_label": "admin", + "model": "logentry" + }, + "model": "contenttypes.contenttype", + "pk": 65 + }, + { + "fields": { + "app_label": "authtoken", + "model": "token" + }, + "model": "contenttypes.contenttype", + "pk": 66 + } +] \ No newline at end of file From dcfda3ff4e08f8705709d7ac4af6402e7a21d4ad Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 2 Mar 2021 23:15:15 +0100 Subject: [PATCH 07/16] =?UTF-8?q?Odevzd=C3=A1v=C3=A1tko:=20ve=20t=C5=99?= =?UTF-8?q?=C3=ADd=C4=9B=20nem=C3=A1=20b=C3=BDt=20k=C3=B3d,=20jinak=20to?= =?UTF-8?q?=20rozb=C3=ADj=C3=AD=20testdata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/forms.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/seminar/forms.py b/seminar/forms.py index 39714fae..800b8e35 100644 --- a/seminar/forms.py +++ b/seminar/forms.py @@ -382,11 +382,15 @@ class OdevzdavatkoTabulkaFiltrForm(forms.Form): return result + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # choices jako parametr Select widgetu neumí brát callable, jen iterable, takže si pro jednoduchost můžu rovnou uložit výsledek sem... + # A "sem" znamená do libovolné metody, protože jinak se jedná o kód, který django spustí při inicializaci a protože potřebujeme databázi, tak by spadnul při vyrábění testdat... + self.terminy = self.gen_terminy() + # NOTE: Initial definuji pro jednotlivé fieldy, aby to bylo tady a nebylo potřeba to řešit ve views... resitele = forms.ChoiceField(choices=RESITELE_CHOICES, initial=RESITELE_RELEVANTNI) problemy = forms.ChoiceField(choices=PROBLEMY_CHOICES, initial=PROBLEMY_MOJE) - # choices jako parametr Select widgetu neumí brát callable, jen iterable, takže si pro jednoduchost můžu rovnou uložit výsledek sem... - terminy = gen_terminy() reseni_od = forms.DateField(input_formats=[DATE_FORMAT], widget=forms.Select(choices=terminy), initial=terminy[-2]) reseni_do = forms.DateField(input_formats=[DATE_FORMAT], widget=forms.Select(choices=terminy), initial=terminy[-1]) From 281b6551f8851cd195ee48908cc50b43a6b59dcc Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 2 Mar 2021 23:26:18 +0100 Subject: [PATCH 08/16] Opravena neverejna aktualni vysledkovka --- seminar/templates/seminar/zadani/AktualniVysledkovka.html | 2 ++ seminar/views/views_all.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/seminar/templates/seminar/zadani/AktualniVysledkovka.html b/seminar/templates/seminar/zadani/AktualniVysledkovka.html index ed89c87c..5874c983 100644 --- a/seminar/templates/seminar/zadani/AktualniVysledkovka.html +++ b/seminar/templates/seminar/zadani/AktualniVysledkovka.html @@ -24,7 +24,9 @@

Výsledky včetně neveřejných

{% with vysledkovka_s_neverejnymi as radky_vysledkovky %} + {% with cisla_s_neverejnymi as cisla %} {% include "seminar/vysledkovka_rocnik.html" %} + {% endwith %} {% endwith %}
{% endif %} diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index 032e9380..04600d6a 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -503,6 +503,7 @@ def ZadaniAktualniVysledkovkaView(request): pass # vysledkovka s neverejnyma vysledkama vysledkovka_s_neverejnymi = vysledkovka_rocniku(nastaveni.aktualni_rocnik, jen_verejne=False) + cisla_s_neverejnymi = cisla_rocniku(nastaveni.aktualni_rocnik, jen_verejne=False) return render( request, 'seminar/zadani/AktualniVysledkovka.html', @@ -511,6 +512,7 @@ def ZadaniAktualniVysledkovkaView(request): 'radky_vysledkovky': vysledkovka, 'cisla': cisla, 'vysledkovka_s_neverejnymi': vysledkovka_s_neverejnymi, + 'cisla_s_neverejnymi': cisla_s_neverejnymi, } ) From 6dcd87684aa28d82d901f0e1dd4f0655cafa89bf Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 2 Mar 2021 23:35:40 +0100 Subject: [PATCH 09/16] Sesortena neverejna aktualni vysledkovka --- seminar/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seminar/utils.py b/seminar/utils.py index a02c317c..e28f3cbc 100644 --- a/seminar/utils.py +++ b/seminar/utils.py @@ -232,7 +232,7 @@ def cisla_rocniku(rocnik, jen_verejne=True): if jen_verejne: return rocnik.verejna_cisla() else: - return rocnik.cisla.all() + return rocnik.cisla.all().order_by('poradi') def hlavni_problem(problem): """ Pro daný problém vrátí jeho nejvyšší nadproblém.""" From a6cf928471d0a4439fa9ea5668ba1e040d619d4b Mon Sep 17 00:00:00 2001 From: "Tomas \"Jethro\" Pokorny" Date: Tue, 2 Mar 2021 23:45:58 +0100 Subject: [PATCH 10/16] Zakomentovana (pravdepodobne) nepouzivana funkce verejne --- seminar/models.py | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/seminar/models.py b/seminar/models.py index b85711e5..f2c418e6 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -864,31 +864,31 @@ class Problem(SeminarModelBase,PolymorphicModel): return str(self.kod) return '' - def verejne(self): - # aktuálně podle stavu problému - # FIXME pro některé problémy možná chceme override - # FIXME vrací veřejnost čistě problému, nezávisle na čísle, ve kterém je. - # Je to tak správně? Podle aktuální představy ano. - stav_verejny = False - if self.stav == 'zadany' or self.stav == 'vyreseny': - stav_verejny = True - print("stav_verejny: {}".format(stav_verejny)) - - cislo_verejne = False - cislonode = self.cislo_node() - if cislonode is None: - # problém nemá vlastní node, veřejnost posuzujeme jen podle stavu - print("empty node") - return stav_verejny - else: - cislo_zadani = cislonode.cislo - if (cislo_zadani and cislo_zadani.verejne()): - print("cislo: {}".format(cislo_zadani)) - cislo_verejne = True - print("stav_verejny: {}".format(stav_verejny)) - print("cislo_verejne: {}".format(cislo_verejne)) - return (stav_verejny and cislo_verejne) - verejne.boolean = True +# def verejne(self): +# # aktuálně podle stavu problému +# # FIXME pro některé problémy možná chceme override +# # FIXME vrací veřejnost čistě problému, nezávisle na čísle, ve kterém je. +# # Je to tak správně? Podle aktuální představy ano. +# stav_verejny = False +# if self.stav == 'zadany' or self.stav == 'vyreseny': +# stav_verejny = True +# print("stav_verejny: {}".format(stav_verejny)) +# +# cislo_verejne = False +# cislonode = self.cislo_node() +# if cislonode is None: +# # problém nemá vlastní node, veřejnost posuzujeme jen podle stavu +# print("empty node") +# return stav_verejny +# else: +# cislo_zadani = cislonode.cislo +# if (cislo_zadani and cislo_zadani.verejne()): +# print("cislo: {}".format(cislo_zadani)) +# cislo_verejne = True +# print("stav_verejny: {}".format(stav_verejny)) +# print("cislo_verejne: {}".format(cislo_verejne)) +# return (stav_verejny and cislo_verejne) +# verejne.boolean = True def verejne_url(self): return reverse('seminar_problem', kwargs={'pk': self.id}) From 8b37035bf3b1ab98550d5031ace0e288f8631fb1 Mon Sep 17 00:00:00 2001 From: "Tomas \"Jethro\" Pokorny" Date: Tue, 2 Mar 2021 23:46:30 +0100 Subject: [PATCH 11/16] Admin | Nedovolit zverejnit cislo, kdyz nejou zverejnene problemy. --- seminar/admin.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/seminar/admin.py b/seminar/admin.py index 4da32e96..849ca696 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin from django.contrib.auth.models import Group from django.db import models -from django.forms import widgets +from django.forms import widgets, ModelForm +from django.core.exceptions import ValidationError from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter from reversion.admin import VersionAdmin @@ -12,11 +13,43 @@ from solo.admin import SingletonModelAdmin # Todo: reversion import seminar.models as m +import seminar.treelib as tl admin.site.register(m.Skola) admin.site.register(m.Prijemce) admin.site.register(m.Rocnik) -admin.site.register(m.Cislo) + +class CisloForm(ModelForm): + class Meta: + model = m.Cislo + fields = '__all__' + + def clean(self): + print("Cleaning...") + print(self.cleaned_data) + if self.cleaned_data.get('verejne_db') == False: + return self.cleaned_data + cn = m.CisloNode.objects.get(cislo=self.instance) + for ch in tl.all_children(cn): + if isinstance(ch, m.TemaVCisleNode): + if ch.tema.stav not in \ + (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY): + raise ValidationError('Téma %(tema)s není zadané ani vyřešené', params={'tema':ch.tema}) + + if isinstance(ch, m.UlohaZadaniNode) or isinstance(ch, m.UlohaVzorakNode): + if ch.uloha.stav not in \ + (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY): + raise ValidationError('Úloha %(uloha)s není zadaná ani vyřešená', params={'uloha':ch.uloha}) + if isinstance(ch, m.ReseniNode): + for problem in ch.reseni.problem_set: + if problem not in \ + (m.Problem.STAV_ZADANY, m.Problem.STAV_VYRESENY): + raise ValidationError('Problém %s není zadaný ani vyřešený', code=problem) + return self.cleaned_data + +@admin.register(m.Cislo) +class CisloAdmin(admin.ModelAdmin): + form = CisloForm @admin.register(m.Osoba) class OsobaAdmin(admin.ModelAdmin): From 1c8cf08f32f6fdf644176c0908722452847922db Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 3 Mar 2021 00:46:09 +0100 Subject: [PATCH 12/16] =?UTF-8?q?Revert=20"Odevzd=C3=A1v=C3=A1tko:=20ve=20?= =?UTF-8?q?t=C5=99=C3=ADd=C4=9B=20nem=C3=A1=20b=C3=BDt=20k=C3=B3d,=20jinak?= =?UTF-8?q?=20to=20rozb=C3=ADj=C3=AD=20testdata"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pořád je to rozbitý, budu si s tím hrát separátně This reverts commit dcfda3ff4e08f8705709d7ac4af6402e7a21d4ad. --- seminar/forms.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/seminar/forms.py b/seminar/forms.py index 800b8e35..39714fae 100644 --- a/seminar/forms.py +++ b/seminar/forms.py @@ -382,15 +382,11 @@ class OdevzdavatkoTabulkaFiltrForm(forms.Form): return result - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - # choices jako parametr Select widgetu neumí brát callable, jen iterable, takže si pro jednoduchost můžu rovnou uložit výsledek sem... - # A "sem" znamená do libovolné metody, protože jinak se jedná o kód, který django spustí při inicializaci a protože potřebujeme databázi, tak by spadnul při vyrábění testdat... - self.terminy = self.gen_terminy() - # NOTE: Initial definuji pro jednotlivé fieldy, aby to bylo tady a nebylo potřeba to řešit ve views... resitele = forms.ChoiceField(choices=RESITELE_CHOICES, initial=RESITELE_RELEVANTNI) problemy = forms.ChoiceField(choices=PROBLEMY_CHOICES, initial=PROBLEMY_MOJE) + # choices jako parametr Select widgetu neumí brát callable, jen iterable, takže si pro jednoduchost můžu rovnou uložit výsledek sem... + terminy = gen_terminy() reseni_od = forms.DateField(input_formats=[DATE_FORMAT], widget=forms.Select(choices=terminy), initial=terminy[-2]) reseni_do = forms.DateField(input_formats=[DATE_FORMAT], widget=forms.Select(choices=terminy), initial=terminy[-1]) From 2a156e3774db8a8a9d8b743368a69d09fe508f3d Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 3 Mar 2021 00:46:56 +0100 Subject: [PATCH 13/16] Revert "Pridany contenttypes." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U každého jsou jiné a nejdou aplikovat, viz Kanec:#1099 This reverts commit b5ae76a5a4b86e306d87079863d0930227974ddd. --- data/contenttypes.json | 530 ----------------------------------------- 1 file changed, 530 deletions(-) delete mode 100644 data/contenttypes.json diff --git a/data/contenttypes.json b/data/contenttypes.json deleted file mode 100644 index 954fd4b8..00000000 --- a/data/contenttypes.json +++ /dev/null @@ -1,530 +0,0 @@ -[ - { - "fields": { - "app_label": "seminar", - "model": "treenode" - }, - "model": "contenttypes.contenttype", - "pk": 1 - }, - { - "fields": { - "app_label": "seminar", - "model": "problem" - }, - "model": "contenttypes.contenttype", - "pk": 2 - }, - { - "fields": { - "app_label": "seminar", - "model": "rocniknode" - }, - "model": "contenttypes.contenttype", - "pk": 3 - }, - { - "fields": { - "app_label": "seminar", - "model": "cislonode" - }, - "model": "contenttypes.contenttype", - "pk": 4 - }, - { - "fields": { - "app_label": "seminar", - "model": "mezicislonode" - }, - "model": "contenttypes.contenttype", - "pk": 5 - }, - { - "fields": { - "app_label": "seminar", - "model": "temavcislenode" - }, - "model": "contenttypes.contenttype", - "pk": 6 - }, - { - "fields": { - "app_label": "seminar", - "model": "orgtextnode" - }, - "model": "contenttypes.contenttype", - "pk": 7 - }, - { - "fields": { - "app_label": "seminar", - "model": "ulohazadaninode" - }, - "model": "contenttypes.contenttype", - "pk": 8 - }, - { - "fields": { - "app_label": "seminar", - "model": "ulohavzoraknode" - }, - "model": "contenttypes.contenttype", - "pk": 9 - }, - { - "fields": { - "app_label": "seminar", - "model": "pohadkanode" - }, - "model": "contenttypes.contenttype", - "pk": 10 - }, - { - "fields": { - "app_label": "seminar", - "model": "textnode" - }, - "model": "contenttypes.contenttype", - "pk": 11 - }, - { - "fields": { - "app_label": "seminar", - "model": "castnode" - }, - "model": "contenttypes.contenttype", - "pk": 12 - }, - { - "fields": { - "app_label": "seminar", - "model": "reseninode" - }, - "model": "contenttypes.contenttype", - "pk": 13 - }, - { - "fields": { - "app_label": "seminar", - "model": "tema" - }, - "model": "contenttypes.contenttype", - "pk": 14 - }, - { - "fields": { - "app_label": "seminar", - "model": "clanek" - }, - "model": "contenttypes.contenttype", - "pk": 15 - }, - { - "fields": { - "app_label": "seminar", - "model": "uloha" - }, - "model": "contenttypes.contenttype", - "pk": 16 - }, - { - "fields": { - "app_label": "auth", - "model": "user" - }, - "model": "contenttypes.contenttype", - "pk": 17 - }, - { - "fields": { - "app_label": "contenttypes", - "model": "contenttype" - }, - "model": "contenttypes.contenttype", - "pk": 18 - }, - { - "fields": { - "app_label": "sessions", - "model": "session" - }, - "model": "contenttypes.contenttype", - "pk": 19 - }, - { - "fields": { - "app_label": "sites", - "model": "site" - }, - "model": "contenttypes.contenttype", - "pk": 20 - }, - { - "fields": { - "app_label": "auth", - "model": "permission" - }, - "model": "contenttypes.contenttype", - "pk": 21 - }, - { - "fields": { - "app_label": "auth", - "model": "group" - }, - "model": "contenttypes.contenttype", - "pk": 22 - }, - { - "fields": { - "app_label": "reversion", - "model": "revision" - }, - "model": "contenttypes.contenttype", - "pk": 23 - }, - { - "fields": { - "app_label": "reversion", - "model": "version" - }, - "model": "contenttypes.contenttype", - "pk": 24 - }, - { - "fields": { - "app_label": "taggit", - "model": "tag" - }, - "model": "contenttypes.contenttype", - "pk": 25 - }, - { - "fields": { - "app_label": "taggit", - "model": "taggeditem" - }, - "model": "contenttypes.contenttype", - "pk": 26 - }, - { - "fields": { - "app_label": "fluent_comments", - "model": "fluentcomment" - }, - "model": "contenttypes.contenttype", - "pk": 27 - }, - { - "fields": { - "app_label": "threadedcomments", - "model": "threadedcomment" - }, - "model": "contenttypes.contenttype", - "pk": 28 - }, - { - "fields": { - "app_label": "django_comments", - "model": "comment" - }, - "model": "contenttypes.contenttype", - "pk": 29 - }, - { - "fields": { - "app_label": "django_comments", - "model": "commentflag" - }, - "model": "contenttypes.contenttype", - "pk": 30 - }, - { - "fields": { - "app_label": "flatpages", - "model": "flatpage" - }, - "model": "contenttypes.contenttype", - "pk": 31 - }, - { - "fields": { - "app_label": "sitetree", - "model": "tree" - }, - "model": "contenttypes.contenttype", - "pk": 32 - }, - { - "fields": { - "app_label": "sitetree", - "model": "treeitem" - }, - "model": "contenttypes.contenttype", - "pk": 33 - }, - { - "fields": { - "app_label": "seminar", - "model": "cislo" - }, - "model": "contenttypes.contenttype", - "pk": 34 - }, - { - "fields": { - "app_label": "seminar", - "model": "resitel" - }, - "model": "contenttypes.contenttype", - "pk": 35 - }, - { - "fields": { - "app_label": "seminar", - "model": "rocnik" - }, - "model": "contenttypes.contenttype", - "pk": 36 - }, - { - "fields": { - "app_label": "seminar", - "model": "skola" - }, - "model": "contenttypes.contenttype", - "pk": 37 - }, - { - "fields": { - "app_label": "seminar", - "model": "soustredeni" - }, - "model": "contenttypes.contenttype", - "pk": 38 - }, - { - "fields": { - "app_label": "seminar", - "model": "reseni" - }, - "model": "contenttypes.contenttype", - "pk": 39 - }, - { - "fields": { - "app_label": "seminar", - "model": "prilohareseni" - }, - "model": "contenttypes.contenttype", - "pk": 40 - }, - { - "fields": { - "app_label": "seminar", - "model": "nastaveni" - }, - "model": "contenttypes.contenttype", - "pk": 41 - }, - { - "fields": { - "app_label": "seminar", - "model": "soustredeni_ucastnici" - }, - "model": "contenttypes.contenttype", - "pk": 42 - }, - { - "fields": { - "app_label": "seminar", - "model": "novinky" - }, - "model": "contenttypes.contenttype", - "pk": 43 - }, - { - "fields": { - "app_label": "seminar", - "model": "organizator" - }, - "model": "contenttypes.contenttype", - "pk": 44 - }, - { - "fields": { - "app_label": "seminar", - "model": "soustredeni_organizatori" - }, - "model": "contenttypes.contenttype", - "pk": 45 - }, - { - "fields": { - "app_label": "seminar", - "model": "konfera" - }, - "model": "contenttypes.contenttype", - "pk": 46 - }, - { - "fields": { - "app_label": "seminar", - "model": "osoba" - }, - "model": "contenttypes.contenttype", - "pk": 47 - }, - { - "fields": { - "app_label": "seminar", - "model": "prijemce" - }, - "model": "contenttypes.contenttype", - "pk": 48 - }, - { - "fields": { - "app_label": "seminar", - "model": "text" - }, - "model": "contenttypes.contenttype", - "pk": 49 - }, - { - "fields": { - "app_label": "seminar", - "model": "pohadka" - }, - "model": "contenttypes.contenttype", - "pk": 50 - }, - { - "fields": { - "app_label": "seminar", - "model": "reseni_resitele" - }, - "model": "contenttypes.contenttype", - "pk": 51 - }, - { - "fields": { - "app_label": "seminar", - "model": "obrazek" - }, - "model": "contenttypes.contenttype", - "pk": 52 - }, - { - "fields": { - "app_label": "seminar", - "model": "hodnoceni" - }, - "model": "contenttypes.contenttype", - "pk": 53 - }, - { - "fields": { - "app_label": "seminar", - "model": "konfery_ucastnici" - }, - "model": "contenttypes.contenttype", - "pk": 54 - }, - { - "fields": { - "app_label": "galerie", - "model": "galerie" - }, - "model": "contenttypes.contenttype", - "pk": 55 - }, - { - "fields": { - "app_label": "galerie", - "model": "obrazek" - }, - "model": "contenttypes.contenttype", - "pk": 56 - }, - { - "fields": { - "app_label": "korektury", - "model": "korekturovanepdf" - }, - "model": "contenttypes.contenttype", - "pk": 57 - }, - { - "fields": { - "app_label": "korektury", - "model": "oprava" - }, - "model": "contenttypes.contenttype", - "pk": 58 - }, - { - "fields": { - "app_label": "korektury", - "model": "komentar" - }, - "model": "contenttypes.contenttype", - "pk": 59 - }, - { - "fields": { - "app_label": "prednasky", - "model": "hlasovani" - }, - "model": "contenttypes.contenttype", - "pk": 60 - }, - { - "fields": { - "app_label": "prednasky", - "model": "prednaska" - }, - "model": "contenttypes.contenttype", - "pk": 61 - }, - { - "fields": { - "app_label": "prednasky", - "model": "seznam" - }, - "model": "contenttypes.contenttype", - "pk": 62 - }, - { - "fields": { - "app_label": "header_fotky", - "model": "fotkaheader" - }, - "model": "contenttypes.contenttype", - "pk": 63 - }, - { - "fields": { - "app_label": "header_fotky", - "model": "fotkaurlvazba" - }, - "model": "contenttypes.contenttype", - "pk": 64 - }, - { - "fields": { - "app_label": "admin", - "model": "logentry" - }, - "model": "contenttypes.contenttype", - "pk": 65 - }, - { - "fields": { - "app_label": "authtoken", - "model": "token" - }, - "model": "contenttypes.contenttype", - "pk": 66 - } -] \ No newline at end of file From 0c2715bdc93f4db6bcfc8c3554bb232c2a63d46b Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 3 Mar 2021 00:57:37 +0100 Subject: [PATCH 14/16] =?UTF-8?q?Ohackov=C3=A1na=20neexistuj=C3=ADc=C3=AD?= =?UTF-8?q?=20DB=20p=C5=99i=20v=C3=BDrob=C4=9B=20testdat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Teď zrovna mi DB hází I/O errory, ale to by snad nemělo souviset... --- seminar/forms.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/seminar/forms.py b/seminar/forms.py index 39714fae..f26d11fa 100644 --- a/seminar/forms.py +++ b/seminar/forms.py @@ -350,9 +350,17 @@ class OdevzdavatkoTabulkaFiltrForm(forms.Form): def gen_terminy(): import datetime from time import strftime - - aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik - aktualni_cislo = m.Nastaveni.get_solo().aktualni_cislo + + from django.db.utils import OperationalError + try: + aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik + aktualni_cislo = m.Nastaveni.get_solo().aktualni_cislo + except OperationalError: + # 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 + logger = logging.getLogger(__name__) + logger.error("Rozbitá databáze (před počátečními migracemi?)") + return [('broken', 'Je to rozbitý'), ('fubar', 'Nefunguje to')] result = [] From 4b141e38192d8c6de1a59eaf321e81e185b9c7e0 Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 9 Mar 2021 20:16:01 +0100 Subject: [PATCH 15/16] =?UTF-8?q?fix:=20Ve=C5=99ejnost=20bod=C5=AF=20ve=20?= =?UTF-8?q?v=C3=BDsledkovce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/utils.py | 2 +- seminar/views/vysledkovka.py | 34 ++++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/seminar/utils.py b/seminar/utils.py index e28f3cbc..26d52665 100644 --- a/seminar/utils.py +++ b/seminar/utils.py @@ -230,7 +230,7 @@ def cisla_rocniku(rocnik, jen_verejne=True): seznam objektů typu Cislo """ if jen_verejne: - return rocnik.verejna_cisla() + return rocnik.verejne_vysledkovky_cisla() else: return rocnik.cisla.all().order_by('poradi') diff --git a/seminar/views/vysledkovka.py b/seminar/views/vysledkovka.py index f4fa5edb..6a5da6a9 100644 --- a/seminar/views/vysledkovka.py +++ b/seminar/views/vysledkovka.py @@ -48,7 +48,7 @@ def sloupec_s_poradim(setrizene_body): -def body_resitelu(resitele, za, odjakziva=True): +def body_resitelu(resitele, za, odjakziva=True, jen_verejne=False): """ Funkce počítající počty bodů pro zadané řešitele, buď odjakživa do daného ročníku/čísla anebo za daný ročník/číslo. Parametry: @@ -94,12 +94,22 @@ def body_resitelu(resitele, za, odjakziva=True): body_k_zapocteni = Sum('reseni__hodnoceni__body', filter=( Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok=rok, reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi) )) - elif rocnik and odjakziva: # Spočítáme body za starší ročníky až do zadaného včetně. - body_k_zapocteni = Sum('reseni__hodnoceni__body', - filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok)) + elif rocnik and odjakziva: # Spočítáme body za starší ročníky až do zadaného včetně. + if jen_verejne: + body_k_zapocteni = Sum('reseni__hodnoceni__body', + filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok, + reseni__hodnoceni__cislo_body__verejna_vysledkovka=True)) + else: + body_k_zapocteni = Sum('reseni__hodnoceni__body', + filter= Q(reseni__hodnoceni__cislo_body__rocnik__prvni_rok__lte=rok)) elif rocnik and not odjakziva: # Spočítáme body za daný ročník. - body_k_zapocteni = Sum('reseni__hodnoceni__body', - filter= Q(reseni__hodnoceni__cislo_body__rocnik=rocnik)) + if jen_verejne: + body_k_zapocteni = Sum('reseni__hodnoceni__body', + filter=Q(reseni__hodnoceni__cislo_body__rocnik=rocnik, + reseni__hodnoceni__cislo_body__verejna_vysledkovka=True)) + else: + body_k_zapocteni = Sum('reseni__hodnoceni__body', + filter=Q(reseni__hodnoceni__cislo_body__rocnik=rocnik)) else: assert True, "body_resitelu: Neplatná kombinace za a odjakživa." @@ -149,14 +159,14 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True): body_cisla_slov[cislo.id] = cislobody # získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně - resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele) + resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele, jen_verejne=jen_verejne) # setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší setrizeni_resitele_id, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn) poradi = sloupec_s_poradim(setrizene_body) # získáme body odjakživa - resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, rocnik) + resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, rocnik, jen_verejne=jen_verejne) # vytvoříme jednotlivé sloupce výsledkovky radky_vysledkovky = [] @@ -216,7 +226,7 @@ def pricti_body(slovnik, resitel, body): slovnik[resitel.id] += body -def secti_body_za_rocnik(za, aktivni_resitele): +def secti_body_za_rocnik(za, aktivni_resitele, jen_verejne): """ Spočítá body za ročník (celý nebo do daného čísla), setřídí je sestupně a vrátí jako seznam. Parametry: @@ -224,7 +234,7 @@ def secti_body_za_rocnik(za, aktivni_resitele): daného čísla """ # spočítáme všem řešitelům jejich body za ročník (False => ne odjakživa) - resitel_rocnikbody_slov = body_resitelu(aktivni_resitele, za, False) + resitel_rocnikbody_slov = body_resitelu(aktivni_resitele, za, False, jen_verejne=jen_verejne) # zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), key = lambda x: x[1], reverse = True) @@ -380,10 +390,10 @@ def vysledkovka_cisla(cislo, context=None): hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) # získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně - resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo, aktivni_resitele) + resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo, aktivni_resitele, jen_verejne=True) # získáme body odjakživa - resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, cislo) + resitel_odjakzivabody_slov = body_resitelu(aktivni_resitele, cislo, jen_verejne=True) # řešitelé setřídění podle bodů za číslo sestupně setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] From eecaa20cc2cce68a1912ee33977ee1ab1ed5f548 Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 9 Mar 2021 20:28:27 +0100 Subject: [PATCH 16/16] =?UTF-8?q?fix:=20Chyb=C4=9Bj=C3=ADc=C3=AD=20cached?= =?UTF-8?q?=5Fproperty=20u=20=C4=8Dl=C3=A1nku=20(padala=20v=C3=BDsledkovka?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seminar/models.py b/seminar/models.py index f2c418e6..b7147106 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -962,6 +962,7 @@ class Clanek(Problem): cislo = models.ForeignKey(Cislo, blank=True, null=True, on_delete=models.PROTECT, verbose_name='číslo vydání', related_name='vydane_clanky') + @cached_property def kod_v_rocniku(self): if self.stav == 'zadany': # Nemělo by být potřeba