Compare commits
24 commits
09e2df75ce
...
f96c24a474
Author | SHA1 | Date | |
---|---|---|---|
f96c24a474 | |||
c76fcb363a | |||
246f63d6e0 | |||
0e0bd76f28 | |||
72b72899fd | |||
![]() |
5977f472c7 | ||
![]() |
3c3047b548 | ||
ea7075f707 | |||
e10a8e0b6d | |||
3110eb92a5 | |||
abdd2d65dd | |||
d14b6bb799 | |||
bebc120e8f | |||
58f05724e1 | |||
5690dc297e | |||
![]() |
485c4180da | ||
![]() |
c2ad4c560d | ||
![]() |
4d97e21e96 | ||
![]() |
4378c05e3e | ||
![]() |
332e5e88d5 | ||
9a3f51ca6b | |||
315dc97635 | |||
fd3df6c344 | |||
7ccaf87dfc |
14 changed files with 115 additions and 25 deletions
File diff suppressed because one or more lines are too long
|
@ -2,3 +2,4 @@ Aprílové nápad
|
||||||
==============
|
==============
|
||||||
|
|
||||||
* aprílový easter-egg pro řešitele - vytvořit nějakou vtipnou testovací databázi a nasadit ji místo produkce
|
* aprílový easter-egg pro řešitele - vytvořit nějakou vtipnou testovací databázi a nasadit ji místo produkce
|
||||||
|
* změnit veškerý text na oranžovo
|
||||||
|
|
14
docs/conf.py
14
docs/conf.py
|
@ -85,3 +85,17 @@ source_suffix = {
|
||||||
'.rst': 'restructuredtext',
|
'.rst': 'restructuredtext',
|
||||||
'.md': 'markdown',
|
'.md': 'markdown',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Autodoc má ignorovat některé moduly
|
||||||
|
# Ref: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#event-autodoc-skip-member
|
||||||
|
# Kudos: https://stackoverflow.com/a/21449475/
|
||||||
|
def ignorovat(app, what, name, obj, skip, options):
|
||||||
|
blacklist = (
|
||||||
|
# typ (what), name
|
||||||
|
('module', 'settings.mamweb_prod'),
|
||||||
|
)
|
||||||
|
ignore = (what, name) in blacklist
|
||||||
|
return True if ignore else None
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.connect('autodoc-skip-member', ignorovat)
|
||||||
|
|
|
@ -6,15 +6,31 @@
|
||||||
Vítejte v dokumentaci M&Mího webu!
|
Vítejte v dokumentaci M&Mího webu!
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
Tzv. produkce (tedy to, co vidí uživatelé) běží na `<mam.mff.cuni.cz>`_ (resp.
|
||||||
|
`<mam.matfyz.cz>`_), menu, obrázky v pozadí menu a spousta stránek (ty pouze se
|
||||||
|
statickým textem/obrázky) se mění přímo na produkci. Testovací verze běží na
|
||||||
|
`<https://mam-test.ks.matfyz.cz/>`_.
|
||||||
|
|
||||||
|
Abychom uměli web vyvíjet, musíme ho většinou nejdřív umět
|
||||||
|
:doc:`naklonovat a spustit lokálně <vyvoj>`.
|
||||||
|
|
||||||
|
:doc:`struktura mamwebu <struktura>` se řídí hlavně djangem, ale snažíme se
|
||||||
|
také o oddělení jednotlivých částí do :doc:`samostatných aplikací
|
||||||
|
<modules/modules>`.
|
||||||
|
|
||||||
|
Dokumentace (jak v ``docs/``, tak přímo v kódu) je psaná ve
|
||||||
|
:doc:`sphinxu <sphinx>`.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: M&M web
|
:caption: M&M web
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
:titlesonly:
|
||||||
|
|
||||||
vyvoj
|
vyvoj
|
||||||
sphinx
|
sphinx
|
||||||
dalsi_soubory
|
|
||||||
skripty
|
skripty
|
||||||
modules/modules
|
modules/modules
|
||||||
|
dalsi_soubory
|
||||||
zapisy/zapisy
|
zapisy/zapisy
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,14 @@ Jinak všechny rst, co jsou ve složce ``doc`` a jejích podsložkách nezačín
|
||||||
|
|
||||||
Sphinx se píše v rst: `Návod na syntaxi rst`_ `Cheat sheet`_
|
Sphinx se píše v rst: `Návod na syntaxi rst`_ `Cheat sheet`_
|
||||||
|
|
||||||
|
To je snad vše, co je potřeba vědět k dokumentaci mamwebu. Následující sekce jsou o tom, co jsem provedl Sphinxu, aby to fungovalo:
|
||||||
|
|
||||||
.. _Návod na syntaxi rst: https://sphinx-tutorial.readthedocs.io/step-1/#sections
|
.. _Návod na syntaxi rst: https://sphinx-tutorial.readthedocs.io/step-1/#sections
|
||||||
.. _Cheat sheet: https://sphinx-tutorial.readthedocs.io/cheatsheet/
|
.. _Cheat sheet: https://sphinx-tutorial.readthedocs.io/cheatsheet/
|
||||||
|
|
||||||
make html
|
make html
|
||||||
---------
|
---------
|
||||||
Make html dělá následující: Vygenerují se rst soubory do modules z pythoní dokumentace pomocí::
|
``make html`` dělá následující: Vygenerují se rst soubory do modules z pythoní dokumentace pomocí::
|
||||||
|
|
||||||
sphinx-apidoc --module-first -o modules .. ../*/migrations --templatedir _templates -f
|
sphinx-apidoc --module-first -o modules .. ../*/migrations --templatedir _templates -f
|
||||||
|
|
||||||
|
|
31
docs/struktura.rst
Normal file
31
docs/struktura.rst
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
Co kde najít (mamweb + django)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Nejdůležitější aplikace z pohledu djanga je ``mamweb``. Tu totiž django pouští
|
||||||
|
a obsahuje tedy nastavení (tam se přidávají ostatní aplikace, včetně těch
|
||||||
|
importovaných z djanga, a nastavují se tam různé věci jak v djangu, tak i naše,
|
||||||
|
například složky, kam se budou věci přidané uživateli ukládat). Dále obsahuje
|
||||||
|
základní urls, udávající, „na jaké adrese co je“. A nakonec obsahuje obecné
|
||||||
|
věci jako chybové hlášky a vzhled M&M stránek (menu, patička, atd.). Aktuálně
|
||||||
|
i veškeré csv.
|
||||||
|
|
||||||
|
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
|
||||||
|
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.**
|
||||||
|
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``,
|
||||||
|
kde je takový ten obsah webu, co by se měl dát snadno měnit (tudíž musí být v
|
||||||
|
databázi), tj. statické stránky, menu a obrázky v pozadí menu. Ten je třeba
|
||||||
|
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>`.
|
||||||
|
|
||||||
|
Základy djanga
|
||||||
|
--------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mamweb je psaný téměř čistě v djangu. Což znamená, že to „co je vidět na stránkách“
|
||||||
|
jsou views.
|
|
@ -2,4 +2,7 @@ Zápisy
|
||||||
======
|
======
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
:caption: Importy zápisů z Markdownu
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
2021-12-06-testovani_dokumentace_codereview
|
2021-12-06-testovani_dokumentace_codereview
|
|
@ -146,7 +146,7 @@
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if o.status != 'neni_chyba' %}
|
{% if o.status != 'neni_chyba' %}
|
||||||
<button type='submit' name='action' value='wontfix' title='Označ jako irelevantní '>
|
<button type='submit' name='action' value='wontfix' title='Označ, že se nebude měnit'>
|
||||||
<img src="{% static "korektury/imgs/cross.png" %}"/>
|
<img src="{% static "korektury/imgs/cross.png" %}"/>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
15
make/lib.sh
15
make/lib.sh
|
@ -6,6 +6,7 @@ VENV_PATH="${VENV_PATH:-env}"
|
||||||
BRANCH="${BRANCH:-master}"
|
BRANCH="${BRANCH:-master}"
|
||||||
|
|
||||||
REPO="${REPO:-git@gitea.ks.matfyz.cz:mam/mamweb.git}"
|
REPO="${REPO:-git@gitea.ks.matfyz.cz:mam/mamweb.git}"
|
||||||
|
UPSTREAM_REMOTE='origin'
|
||||||
GIMLI='gimli.ms.mff.cuni.cz'
|
GIMLI='gimli.ms.mff.cuni.cz'
|
||||||
GIMLI_LOGIN="mam-web@$GIMLI"
|
GIMLI_LOGIN="mam-web@$GIMLI"
|
||||||
# Skutečné cesty, jak je vrátí `realpath`
|
# Skutečné cesty, jak je vrátí `realpath`
|
||||||
|
@ -70,16 +71,26 @@ function safe_checkout_branch {
|
||||||
local SCRIPT="$0"
|
local SCRIPT="$0"
|
||||||
|
|
||||||
git fetch --all
|
git fetch --all
|
||||||
|
local UPSTREAM_BRANCH
|
||||||
|
if git rev-parse "$BRANCH@{u}" >/dev/null 2>/dev/null
|
||||||
|
then
|
||||||
|
UPSTREAM_BRANCH="$BRANCH@{u}" # Stačí symbolicky.
|
||||||
|
else
|
||||||
|
# Tohle je jediná možná záchrana.
|
||||||
|
UPSTREAM_BRANCH="$UPSTREAM_REMOTE/$BRANCH"
|
||||||
|
fi
|
||||||
|
git rev-parse "$UPSTREAM_BRANCH" || die "Vzdálená větev $UPSTREAM_BRANCH neexistuje?"
|
||||||
|
|
||||||
# Od teď si musíme dát pozor, abychom nezměnili kód, který právě běží.
|
# Od teď si musíme dát pozor, abychom nezměnili kód, který právě běží.
|
||||||
# Zkontrolujeme, že se nemění tahle knihovna a skript, který běží.
|
# Zkontrolujeme, že se nemění tahle knihovna a skript, který běží.
|
||||||
# `git rev-parse` dává SHA-1 hashe objektů, vizte manuálovou stránku pro pochopení.
|
# `git rev-parse` dává SHA-1 hashe objektů, vizte manuálovou stránku pro pochopení.
|
||||||
# Pozor: tohle porovnává jen verze commitnuté do gitu. Lokální změny udělají něco náhodného…
|
# Pozor: tohle porovnává jen verze commitnuté do gitu. Lokální změny udělají něco náhodného…
|
||||||
if test "$(git rev-parse @:make/lib.sh)" != "$(git rev-parse "$BRANCH@{u}":make/lib.sh)"
|
if test "$(git rev-parse @:make/lib.sh)" != "$(git rev-parse "$UPSTREAM_BRANCH":make/lib.sh)"
|
||||||
then
|
then
|
||||||
echo >&2 "Změna v make/lib.sh, prosím pullni manuálně"
|
echo >&2 "Změna v make/lib.sh, prosím pullni manuálně"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if test "$(git rev-parse @:"$SCRIPT")" != "$(git rev-parse "$BRANCH@{u}":"$SCRIPT")"
|
if test "$(git rev-parse @:"$SCRIPT")" != "$(git rev-parse "$UPSTREAM_BRANCH":"$SCRIPT")"
|
||||||
then
|
then
|
||||||
echo >&2 "Změna v $SCRIPT, prosím pullni manuálně"
|
echo >&2 "Změna v $SCRIPT, prosím pullni manuálně"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -1222,6 +1222,13 @@ div.gdpr {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
margin-left: calc(-50vw + 485px);
|
margin-left: calc(-50vw + 485px);
|
||||||
}
|
}
|
||||||
|
/* Na úzkém displeji nechceme nic dělat. */
|
||||||
|
@media(max-width: 860px) {
|
||||||
|
.full_width{
|
||||||
|
margin-left: 0;
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.dosla_reseni tr th, .dosla_reseni tr td {
|
.dosla_reseni tr th, .dosla_reseni tr td {
|
||||||
padding: 1px 10px 1px 10px;
|
padding: 1px 10px 1px 10px;
|
||||||
|
|
|
@ -60,7 +60,7 @@ class TabulkaOdevzdanychReseniView(ListView):
|
||||||
|
|
||||||
self.aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik # .get_solo() vrátí tu jedinou instanci
|
self.aktualni_rocnik = m.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 = m.Rocnik.objects.get(rocnik=self.kwargs['rocnik'])
|
self.aktualni_rocnik = get_object_or_404(m.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():
|
||||||
|
@ -102,16 +102,21 @@ class TabulkaOdevzdanychReseniView(ListView):
|
||||||
)
|
)
|
||||||
#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.
|
||||||
self.problemy = self.problemy.non_polymorphic()
|
self.problemy = self.problemy.non_polymorphic().distinct()
|
||||||
|
|
||||||
self.reseni = self.reseni.filter(cas_doruceni__date__gt=reseni_od, cas_doruceni__date__lte=reseni_do)
|
self.reseni = self.reseni.filter(cas_doruceni__date__gt=reseni_od, cas_doruceni__date__lte=reseni_do)
|
||||||
if jen_neobodovane:
|
if jen_neobodovane:
|
||||||
self.reseni = self.reseni.filter(hodnoceni__body__isnull=True)
|
self.reseni = self.reseni.filter(hodnoceni__body__isnull=True)
|
||||||
|
self.jen_neobodovane = jen_neobodovane
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
self.inicializuj_osy_tabulky()
|
self.inicializuj_osy_tabulky()
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
|
if self.jen_neobodovane:
|
||||||
|
qs = qs.filter(body__isnull=True)
|
||||||
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')
|
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')
|
||||||
|
# FIXME tohle je ošklivé, na špatném místě a pomalé. Ale moc mě štvalo, že musím hledat správná místa v tabulce.
|
||||||
|
self.problemy = self.problemy.filter(id__in=qs.values("problem__id"))
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
|
|
@ -43,7 +43,7 @@ class OrganizatorAdmin(ReverseModelAdmin):
|
||||||
@admin.register(m.Resitel)
|
@admin.register(m.Resitel)
|
||||||
class ResitelAdmin(ReverseModelAdmin):
|
class ResitelAdmin(ReverseModelAdmin):
|
||||||
search_fields = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__prezdivka']
|
search_fields = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__prezdivka']
|
||||||
ordering = ('osoba__jmeno','osoba__prijmeni')
|
ordering = ('osoba__prijmeni', 'osoba__jmeno')
|
||||||
inline_type = 'stacked'
|
inline_type = 'stacked'
|
||||||
inline_reverse = ['osoba']
|
inline_reverse = ['osoba']
|
||||||
|
|
||||||
|
|
|
@ -349,7 +349,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(
|
||||||
m.Rocnik.objects.get(rocnik=rocnik)
|
get_object_or_404(m.Rocnik, rocnik=rocnik)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -442,17 +442,17 @@ class OdmenyView(generic.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)
|
||||||
fromcislo = Cislo.objects.get(rocnik=self.kwargs.get('frocnik'), poradi=self.kwargs.get('fcislo'))
|
fromcislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('frocnik'), poradi=self.kwargs.get('fcislo'))
|
||||||
tocislo = Cislo.objects.get(rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo'))
|
tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo'))
|
||||||
resitele = aktivniResitele(tocislo)
|
resitele = aktivniResitele(tocislo)
|
||||||
|
|
||||||
def get_diff(from_deadline: Deadline, to_deadline: Deadline):
|
def get_diff(from_deadline: Deadline, to_deadline: Deadline):
|
||||||
frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline)
|
frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline)
|
||||||
tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline)
|
tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline)
|
||||||
outlist = []
|
outlist = []
|
||||||
for (aid, tbody) in tobody.items():
|
for resitel in resitele:
|
||||||
fbody = frombody.get(aid,0)
|
fbody = frombody.get(resitel.id, 0)
|
||||||
resitel = Resitel.objects.get(pk=aid)
|
tbody = tobody.get(resitel.id, 0)
|
||||||
ftitul = resitel.get_titul(fbody)
|
ftitul = resitel.get_titul(fbody)
|
||||||
ttitul = resitel.get_titul(tbody)
|
ttitul = resitel.get_titul(tbody)
|
||||||
if ftitul != ttitul:
|
if ftitul != ttitul:
|
||||||
|
@ -554,7 +554,7 @@ class RocnikVysledkovkaView(RocnikView):
|
||||||
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
||||||
|
|
||||||
def cisloObalkyView(request, rocnik, cislo):
|
def cisloObalkyView(request, rocnik, cislo):
|
||||||
realne_cislo = Cislo.objects.get(poradi=cislo, rocnik__rocnik=rocnik)
|
realne_cislo = get_object_or_404(Cislo, poradi=cislo, rocnik__rocnik=rocnik)
|
||||||
return obalkyView(request, aktivniResitele(realne_cislo))
|
return obalkyView(request, aktivniResitele(realne_cislo))
|
||||||
|
|
||||||
|
|
||||||
|
@ -580,14 +580,14 @@ def TitulyViewRocnik(request, rocnik):
|
||||||
|
|
||||||
def TitulyView(request, rocnik, cislo):
|
def TitulyView(request, rocnik, cislo):
|
||||||
""" View pro stažení makra titulů v TeXu."""
|
""" View pro stažení makra titulů v TeXu."""
|
||||||
rocnik_obj = Rocnik.objects.get(rocnik = rocnik)
|
rocnik_obj = get_object_or_404(Rocnik, rocnik = rocnik)
|
||||||
resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok)
|
resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok)
|
||||||
|
|
||||||
asciijmena = []
|
asciijmena = []
|
||||||
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
|
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
|
||||||
# pokud ano, vrátí se jako true
|
# pokud ano, vrátí se jako true
|
||||||
if cislo is not None:
|
if cislo is not None:
|
||||||
cislo_obj = Cislo.objects.get(rocnik=rocnik_obj, poradi=cislo)
|
cislo_obj = get_object_or_404(Cislo, rocnik=rocnik_obj, poradi=cislo)
|
||||||
slovnik_s_body = body_resitelu(do=cislo_obj.zlomovy_deadline_pro_papirove_cislo(), jen_verejne=False)
|
slovnik_s_body = body_resitelu(do=cislo_obj.zlomovy_deadline_pro_papirove_cislo(), jen_verejne=False)
|
||||||
else:
|
else:
|
||||||
slovnik_s_body = body_resitelu(do=Deadline.objects.filter(cislo__rocnik=rocnik_obj).last(), jen_verejne=False)
|
slovnik_s_body = body_resitelu(do=Deadline.objects.filter(cislo__rocnik=rocnik_obj).last(), jen_verejne=False)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import abc
|
import abc
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from typing import Union # TODO: s pythonem 3.10 přepsat na '|'
|
from typing import Union, Iterable # TODO: s pythonem 3.10 přepsat na '|'
|
||||||
|
|
||||||
import seminar.models as m
|
import seminar.models as m
|
||||||
from django.db.models import Q, Sum
|
from django.db.models import Q, Sum
|
||||||
|
@ -22,7 +22,7 @@ def body_resitelu(
|
||||||
do: m.Deadline = None,
|
do: m.Deadline = None,
|
||||||
od: m.Deadline = None,
|
od: m.Deadline = None,
|
||||||
jen_verejne: bool = True,
|
jen_verejne: bool = True,
|
||||||
resitele=None,
|
resitele: Iterable[m.Resitel] = None,
|
||||||
null=0 # Výchozí hodnota, pokud pro daného řešitele nejsou body
|
null=0 # Výchozí hodnota, pokud pro daného řešitele nejsou body
|
||||||
) -> dict[int, int]:
|
) -> dict[int, int]:
|
||||||
filtr = Q()
|
filtr = Q()
|
||||||
|
|
Loading…
Reference in a new issue