Compare commits
No commits in common. "f96c24a4746bc6632af5481992e1a9d4a911d61d" and "09e2df75ce20de22894fd5b3c3dc9af541400b39" have entirely different histories.
f96c24a474
...
09e2df75ce
14 changed files with 25 additions and 115 deletions
File diff suppressed because one or more lines are too long
|
@ -2,4 +2,3 @@ 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
|
||||
* změnit veškerý text na oranžovo
|
||||
|
|
14
docs/conf.py
14
docs/conf.py
|
@ -85,17 +85,3 @@ source_suffix = {
|
|||
'.rst': 'restructuredtext',
|
||||
'.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,31 +6,15 @@
|
|||
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::
|
||||
:caption: M&M web
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
vyvoj
|
||||
sphinx
|
||||
dalsi_soubory
|
||||
skripty
|
||||
modules/modules
|
||||
dalsi_soubory
|
||||
zapisy/zapisy
|
||||
|
||||
|
||||
|
|
|
@ -8,14 +8,12 @@ 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`_
|
||||
|
||||
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
|
||||
.. _Cheat sheet: https://sphinx-tutorial.readthedocs.io/cheatsheet/
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
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,7 +2,4 @@ Zápisy
|
|||
======
|
||||
|
||||
.. 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>
|
||||
{% endif %}
|
||||
{% if o.status != 'neni_chyba' %}
|
||||
<button type='submit' name='action' value='wontfix' title='Označ, že se nebude měnit'>
|
||||
<button type='submit' name='action' value='wontfix' title='Označ jako irelevantní '>
|
||||
<img src="{% static "korektury/imgs/cross.png" %}"/>
|
||||
</button>
|
||||
{% endif %}
|
||||
|
|
15
make/lib.sh
15
make/lib.sh
|
@ -6,7 +6,6 @@ VENV_PATH="${VENV_PATH:-env}"
|
|||
BRANCH="${BRANCH:-master}"
|
||||
|
||||
REPO="${REPO:-git@gitea.ks.matfyz.cz:mam/mamweb.git}"
|
||||
UPSTREAM_REMOTE='origin'
|
||||
GIMLI='gimli.ms.mff.cuni.cz'
|
||||
GIMLI_LOGIN="mam-web@$GIMLI"
|
||||
# Skutečné cesty, jak je vrátí `realpath`
|
||||
|
@ -71,26 +70,16 @@ function safe_checkout_branch {
|
|||
local SCRIPT="$0"
|
||||
|
||||
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ěží.
|
||||
# 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í.
|
||||
# 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 "$UPSTREAM_BRANCH":make/lib.sh)"
|
||||
if test "$(git rev-parse @:make/lib.sh)" != "$(git rev-parse "$BRANCH@{u}":make/lib.sh)"
|
||||
then
|
||||
echo >&2 "Změna v make/lib.sh, prosím pullni manuálně"
|
||||
exit 1
|
||||
fi
|
||||
if test "$(git rev-parse @:"$SCRIPT")" != "$(git rev-parse "$UPSTREAM_BRANCH":"$SCRIPT")"
|
||||
if test "$(git rev-parse @:"$SCRIPT")" != "$(git rev-parse "$BRANCH@{u}":"$SCRIPT")"
|
||||
then
|
||||
echo >&2 "Změna v $SCRIPT, prosím pullni manuálně"
|
||||
exit 1
|
||||
|
|
|
@ -1222,13 +1222,6 @@ div.gdpr {
|
|||
width: 100vw;
|
||||
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 {
|
||||
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
|
||||
if 'rocnik' in self.kwargs:
|
||||
self.aktualni_rocnik = get_object_or_404(m.Rocnik, rocnik=self.kwargs['rocnik'])
|
||||
self.aktualni_rocnik = m.Rocnik.objects.get(rocnik=self.kwargs['rocnik'])
|
||||
|
||||
form = FiltrForm(self.request.GET, rocnik=self.aktualni_rocnik)
|
||||
if form.is_valid():
|
||||
|
@ -102,21 +102,16 @@ 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....
|
||||
# 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().distinct()
|
||||
self.problemy = self.problemy.non_polymorphic()
|
||||
|
||||
self.reseni = self.reseni.filter(cas_doruceni__date__gt=reseni_od, cas_doruceni__date__lte=reseni_do)
|
||||
if jen_neobodovane:
|
||||
self.reseni = self.reseni.filter(hodnoceni__body__isnull=True)
|
||||
self.jen_neobodovane = jen_neobodovane
|
||||
|
||||
def get_queryset(self):
|
||||
self.inicializuj_osy_tabulky()
|
||||
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')
|
||||
# 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
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
|
|
|
@ -43,7 +43,7 @@ class OrganizatorAdmin(ReverseModelAdmin):
|
|||
@admin.register(m.Resitel)
|
||||
class ResitelAdmin(ReverseModelAdmin):
|
||||
search_fields = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__prezdivka']
|
||||
ordering = ('osoba__prijmeni', 'osoba__jmeno')
|
||||
ordering = ('osoba__jmeno','osoba__prijmeni')
|
||||
inline_type = 'stacked'
|
||||
inline_reverse = ['osoba']
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ def resiteleRocnikuCsvExportView(request, rocnik):
|
|||
assert request.method in ('GET', 'HEAD')
|
||||
return dataResiteluCsvResponse(
|
||||
utils.resi_v_rocniku(
|
||||
get_object_or_404(m.Rocnik, rocnik=rocnik)
|
||||
m.Rocnik.objects.get(rocnik=rocnik)
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -442,17 +442,17 @@ class OdmenyView(generic.TemplateView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
fromcislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('frocnik'), poradi=self.kwargs.get('fcislo'))
|
||||
tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo'))
|
||||
fromcislo = Cislo.objects.get(rocnik=self.kwargs.get('frocnik'), poradi=self.kwargs.get('fcislo'))
|
||||
tocislo = Cislo.objects.get(rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo'))
|
||||
resitele = aktivniResitele(tocislo)
|
||||
|
||||
def get_diff(from_deadline: Deadline, to_deadline: Deadline):
|
||||
frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline)
|
||||
tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline)
|
||||
outlist = []
|
||||
for resitel in resitele:
|
||||
fbody = frombody.get(resitel.id, 0)
|
||||
tbody = tobody.get(resitel.id, 0)
|
||||
for (aid, tbody) in tobody.items():
|
||||
fbody = frombody.get(aid,0)
|
||||
resitel = Resitel.objects.get(pk=aid)
|
||||
ftitul = resitel.get_titul(fbody)
|
||||
ttitul = resitel.get_titul(tbody)
|
||||
if ftitul != ttitul:
|
||||
|
@ -554,7 +554,7 @@ class RocnikVysledkovkaView(RocnikView):
|
|||
#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
|
||||
|
||||
def cisloObalkyView(request, rocnik, cislo):
|
||||
realne_cislo = get_object_or_404(Cislo, poradi=cislo, rocnik__rocnik=rocnik)
|
||||
realne_cislo = Cislo.objects.get(poradi=cislo, rocnik__rocnik=rocnik)
|
||||
return obalkyView(request, aktivniResitele(realne_cislo))
|
||||
|
||||
|
||||
|
@ -580,14 +580,14 @@ def TitulyViewRocnik(request, rocnik):
|
|||
|
||||
def TitulyView(request, rocnik, cislo):
|
||||
""" View pro stažení makra titulů v TeXu."""
|
||||
rocnik_obj = get_object_or_404(Rocnik, rocnik = rocnik)
|
||||
rocnik_obj = Rocnik.objects.get(rocnik = rocnik)
|
||||
resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok)
|
||||
|
||||
asciijmena = []
|
||||
jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka),
|
||||
# pokud ano, vrátí se jako true
|
||||
if cislo is not None:
|
||||
cislo_obj = get_object_or_404(Cislo, rocnik=rocnik_obj, poradi=cislo)
|
||||
cislo_obj = Cislo.objects.get(rocnik=rocnik_obj, poradi=cislo)
|
||||
slovnik_s_body = body_resitelu(do=cislo_obj.zlomovy_deadline_pro_papirove_cislo(), jen_verejne=False)
|
||||
else:
|
||||
slovnik_s_body = body_resitelu(do=Deadline.objects.filter(cislo__rocnik=rocnik_obj).last(), jen_verejne=False)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import abc
|
||||
from functools import cached_property
|
||||
from typing import Union, Iterable # TODO: s pythonem 3.10 přepsat na '|'
|
||||
from typing import Union # TODO: s pythonem 3.10 přepsat na '|'
|
||||
|
||||
import seminar.models as m
|
||||
from django.db.models import Q, Sum
|
||||
|
@ -22,7 +22,7 @@ def body_resitelu(
|
|||
do: m.Deadline = None,
|
||||
od: m.Deadline = None,
|
||||
jen_verejne: bool = True,
|
||||
resitele: Iterable[m.Resitel] = None,
|
||||
resitele=None,
|
||||
null=0 # Výchozí hodnota, pokud pro daného řešitele nejsou body
|
||||
) -> dict[int, int]:
|
||||
filtr = Q()
|
||||
|
|
Loading…
Reference in a new issue