From e3ebb925e1746aaa6953bd714df11d352e18237e Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 7 Nov 2022 22:32:06 +0100 Subject: [PATCH 01/68] =?UTF-8?q?Reforma=20Makefil=C5=AF=20WIP=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 156 ++------------------------------- Makefile_old | 128 +++++++++++++++++++++++++++ make/all | 17 ++++ make/deploy | 3 + make/deploy_prod | 3 + make/install | 1 + make/install_venv | 3 + make/install_web | 3 + make/lib.sh | 26 ++++++ make/push_compiled_vue_to_test | 3 + make/run | 3 + make/schema | 3 + make/schema_all.pdf | 3 + make/schema_seminar.pdf | 3 + make/sync_local | 3 + make/sync_local_db | 3 + make/sync_local_media | 3 + make/sync_prod_flatpages | 3 + make/sync_test | 3 + make/sync_test_db_aggressive | 3 + make/sync_test_media | 3 + make/test | 3 + make/venv_check | 3 + 23 files changed, 231 insertions(+), 151 deletions(-) create mode 100644 Makefile_old create mode 100755 make/all create mode 100755 make/deploy create mode 100755 make/deploy_prod create mode 120000 make/install create mode 100755 make/install_venv create mode 100755 make/install_web create mode 100644 make/lib.sh create mode 100755 make/push_compiled_vue_to_test create mode 100755 make/run create mode 100755 make/schema create mode 100755 make/schema_all.pdf create mode 100755 make/schema_seminar.pdf create mode 100755 make/sync_local create mode 100755 make/sync_local_db create mode 100755 make/sync_local_media create mode 100755 make/sync_prod_flatpages create mode 100755 make/sync_test create mode 100755 make/sync_test_db_aggressive create mode 100755 make/sync_test_media create mode 100755 make/test create mode 100755 make/venv_check diff --git a/Makefile b/Makefile index 94a377c4..5e3acddc 100644 --- a/Makefile +++ b/Makefile @@ -1,154 +1,8 @@ -PYTHON ?= python3 -VENV ?= ${PYTHON} -m venv -# Všechny flagy, které se s venvem/virtualenvem/... mají volat patří sem. Volá se "${VENV} cesta" -VENV_PATH ?= env -# Musí být definovaná, i kdyby to měla být "." +%: + @make/$* -.PHONY: all venv_check clean install install_web install_venv clean_venv clean_schema run test deploy_test deploy_prod sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local - -# activate by mělo být předpokladem ke všemu, co volá webový python (i.e. python nasazený do ${VENV}u kvůli webu, např. manage.py) all: - @# Just echo: - # Install je trochu magický: - # Spusť následující posloupnost příkazů: - # make install_venv - # . ${VENV_PATH}/bin/activate - # make install_web - # - # Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev - # Pokud chybová hláška obsahuje #include , nainstaluj si python3-dev - # - # Až skončíš s vývojem webu, spusť "deactivate". Tím zmizí '(${VENV_PATH})' ze začátku promptu. - -venv_check: - @# Pokud org nemá zapnutý venv, poradíme mu, aby si ho zapnul a spadneme. Jinak nic. - @expr $$PATH : ".*:*$(shell pwd)/${VENV_PATH}/bin" > /dev/null && exit 0 || echo 'Není zapnutý venv, spusť ". ${VENV_PATH}/bin/activate".\nPokud není venv nainstalovaný, spusť "make install_venv"' && false - -clean: clean_venv clean_schema - -install: install_web - -install_web: venv_check - @# venv může být příšerně starý, takže nejdříve upgradujeme venvové věci - pip install --upgrade pip - pip install --upgrade setuptools - # Instalace závislostí webu - pip install -r requirements.txt --upgrade - # Pro vygenerování tesdat spusť ./manage.py testdata - # Po vygenerování testdat spusť ./manage.py loaddata data/*, ať máš menu a další modely - # Pro synchronizaci flatpages spusť make sync_prod_flatpages - -install_venv: - ${VENV} ${VENV_PATH} - -clean_venv: - # Možná není 100% foolproof... - @test ! ${VENV_PATH} = . || ! echo "Smaž si prosím venv sám, nebudu mazat celý web" - rm -rfv ${VENV_PATH} - rm -f pip-selfcheck.json -clean_schema: - rm -f schema_seminar.pdf schema_all.pdf - -run: venv_check - ./manage.py runserver - -test: venv_check - ./manage.py test -v2 seminar mamweb - -# DB schemata - -schema: schema_seminar.pdf schema_all.pdf - -schema_seminar.pdf: venv_check - ./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf - -schema_all.pdf: venv_check - ./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf - -# Deploy to current *mamweb-test* directory -deploy_test: venv_check - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in directory mamweb-test"; exit 1; fi - @echo "Installing version from origin/test ..." - git pull origin test - git clean -f - make install - ./manage.py migrate - ./manage.py collectstatic --noinput - (chown -R :mam . || true ) - (chmod -R g+rX,go-w . || true ) - @echo Restarting systemd unit - systemctl --user restart mamweb-test.service - @echo Done. - -# Deploy to current *mamweb-prod* directory -deploy_prod: venv_check - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-prod" ]; then echo "Only possible in directory mamweb-prod"; exit 1; fi - @echo "Backing up production DB ..." - ( cd -P .. && ./backup_prod_db.sh ) - @echo "Installing version from origin/master ..." - git pull origin master - git clean -f - make install - ./manage.py migrate - ./manage.py collectstatic --noinput - (chown -R :mam . || true ) - (chmod -R g+rX,go-w . || true ) - @echo Restarting systemd user unit for MaM web - systemctl --user restart mamweb-prod.service - @echo Done. - - -sync_prod_flatpages: venv_check - @echo Downloading current version of flatpages from mamweb-prod. - ssh mam-web@gimli.ms.mff.cuni.cz \ - "cd /akce/mam/www/mamweb-prod; . env/bin/activate; ./manage.py dumpdata flatpages --indent=2 > flat.json; ./fix_json.py flat.json flat_fixed.json" - rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat_fixed.json data/flat.json - @echo "Applying downloaded flatpages." - ./manage.py loaddata data/flat.json - @echo "Done." - -# Sync test media directory with production -sync_test_media: - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi - rsync -av --delete /akce/mam/www/mamweb-prod/media/ ./media - -# Sync (with drop) test database with production database -sync_test_db_aggressive: - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql - pg_dump -Fc mam_prod > dump-prod.sql - @# I am not sure which shell is used, so I am calling bash to make sure - psql mam_test -c 'DROP OWNED BY "mam-web";' - pg_restore -c --if-exists -d mam_test dump-prod.sql - rm dump-prod.sql - psql mam_test -c "UPDATE django_site SET name='MaMweb (test)', domain='mam-test.ks.matfyz.cz' WHERE id=1" - @echo Done. - -# Sync test with production -# HACK ALERT: using aggressive variant, due to the schemas being too different. -sync_test: sync_test_media sync_test_db_aggressive - - -# Sync media directory with atrey. Useful for local development with production database -# Does not sync Galerie and CACHE (too huge). -sync_local_media: - rsync -ave ssh --exclude Galerie --exclude CACHE\ - mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/media/ ./media/ -# Downloads and restores production database to local database. PostgreSQL only. -sync_local_db: - scp mam-web@gimli.ms.mff.cuni.cz:`ssh mam-web@gimli.ms.mff.cuni.cz 'ls -v /akce/mam/www/backups/mam_prod-*\.pgdump.xz | tail -n 1'` \ - ./last.pgdump.xz - xz -fd last.pgdump.xz - pg_restore -c -d mam-prod last.pgdump - -# Sync database and media. See above lines -sync_local: sync_local_media sync_local_db + @# Nevím, proč to nefunguje bez těla, ale vlastně je mi to jedno… + @make/all -# Push local compiled Vue to gimli test site -push_compiled_vue_to_test: - scp vue_frontend/webpack-stats.json mam-web@gimli:/akce/mam/www/mamweb-test/vue_frontend/ - rsync -ave ssh seminar/static/seminar/vue mam-web@gimli:/akce/mam/www/mamweb-test/seminar/static/seminar/ - ssh mam-web@gimli.ms.mff.cuni.cz 'cd /akce/mam/www/mamweb-test/ && . env/bin/activate && ./manage.py collectstatic --noinput' +.PHONY: all diff --git a/Makefile_old b/Makefile_old new file mode 100644 index 00000000..ccfdb143 --- /dev/null +++ b/Makefile_old @@ -0,0 +1,128 @@ +.PHONY: all venv_check clean install install_web install_venv clean_venv clean_schema run test deploy_test deploy_prod sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local + +install: install_web + +install_web: venv_check + @# venv může být příšerně starý, takže nejdříve upgradujeme venvové věci + pip install --upgrade pip + pip install --upgrade setuptools + # Instalace závislostí webu + pip install -r requirements.txt --upgrade + # Pro vygenerování tesdat spusť ./manage.py testdata + # Po vygenerování testdat spusť ./manage.py loaddata data/*, ať máš menu a další modely + # Pro synchronizaci flatpages spusť make sync_prod_flatpages + +install_venv: + ${VENV} ${VENV_PATH} + +clean_venv: + # Možná není 100% foolproof... + @test ! ${VENV_PATH} = . || ! echo "Smaž si prosím venv sám, nebudu mazat celý web" + rm -rfv ${VENV_PATH} + rm -f pip-selfcheck.json +clean_schema: + rm -f schema_seminar.pdf schema_all.pdf + +run: venv_check + ./manage.py runserver + +test: venv_check + ./manage.py test -v2 seminar mamweb + +# DB schemata + +schema: schema_seminar.pdf schema_all.pdf + +schema_seminar.pdf: venv_check + ./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf + +schema_all.pdf: venv_check + ./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf + +# Deploy to current *mamweb-test* directory +deploy: venv_check + @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi + @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in directory mamweb-test"; exit 1; fi + @echo "Installing version from origin/${BRANCH} ..." + git pull origin ${BRANCH} + git clean -f + make install + ./manage.py migrate + ./manage.py collectstatic --noinput + (chown -R :mam . || true ) + (chmod -R g+rX,go-w . || true ) + @echo Restarting systemd unit + systemctl --user restart mamweb-test.service + @echo Done. + +# Deploy to current *mamweb-prod* directory +deploy_prod: venv_check + @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi + @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-prod" ]; then echo "Only possible in directory mamweb-prod"; exit 1; fi + @echo "Backing up production DB ..." + ( cd -P .. && ./backup_prod_db.sh ) + @echo "Installing version from origin/master ..." + git pull origin master + git clean -f + make install + ./manage.py migrate + ./manage.py collectstatic --noinput + (chown -R :mam . || true ) + (chmod -R g+rX,go-w . || true ) + @echo Restarting systemd user unit for MaM web + systemctl --user restart mamweb-prod.service + @echo Done. + + +sync_prod_flatpages: venv_check + @echo Downloading current version of flatpages from mamweb-prod. + ssh mam-web@gimli.ms.mff.cuni.cz \ + "cd /akce/mam/www/mamweb-prod; . env/bin/activate; ./manage.py dumpdata flatpages --indent=2 > flat.json; ./fix_json.py flat.json flat_fixed.json" + rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat_fixed.json data/flat.json + @echo "Applying downloaded flatpages." + ./manage.py loaddata data/flat.json + @echo "Done." + +# Sync test media directory with production +sync_test_media: + @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi + @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi + rsync -av --delete /akce/mam/www/mamweb-prod/media/ ./media + +# Sync (with drop) test database with production database +sync_test_db_aggressive: + @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi + pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql + pg_dump -Fc mam_prod > dump-prod.sql + @# I am not sure which shell is used, so I am calling bash to make sure + psql mam_test -c 'DROP OWNED BY "mam-web";' + pg_restore -c --if-exists -d mam_test dump-prod.sql + rm dump-prod.sql + psql mam_test -c "UPDATE django_site SET name='MaMweb (test)', domain='mam-test.ks.matfyz.cz' WHERE id=1" + @echo Done. + +# Sync test with production +# HACK ALERT: using aggressive variant, due to the schemas being too different. +sync_test: sync_test_media sync_test_db_aggressive + + +# Sync media directory with atrey. Useful for local development with production database +# Does not sync Galerie and CACHE (too huge). +sync_local_media: + rsync -ave ssh --exclude Galerie --exclude CACHE\ + mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/media/ ./media/ +# Downloads and restores production database to local database. PostgreSQL only. +sync_local_db: + scp mam-web@gimli.ms.mff.cuni.cz:`ssh mam-web@gimli.ms.mff.cuni.cz 'ls -v /akce/mam/www/backups/mam_prod-*\.pgdump.xz | tail -n 1'` \ + ./last.pgdump.xz + xz -fd last.pgdump.xz + pg_restore -c -d mam-prod last.pgdump + +# Sync database and media. See above lines +sync_local: sync_local_media sync_local_db + +# Push local compiled Vue to gimli test site +push_compiled_vue_to_test: + scp vue_frontend/webpack-stats.json mam-web@gimli:/akce/mam/www/mamweb-test/vue_frontend/ + rsync -ave ssh seminar/static/seminar/vue mam-web@gimli:/akce/mam/www/mamweb-test/seminar/static/seminar/ + ssh mam-web@gimli.ms.mff.cuni.cz 'cd /akce/mam/www/mamweb-test/ && . env/bin/activate && ./manage.py collectstatic --noinput' diff --git a/make/all b/make/all new file mode 100755 index 00000000..de25100a --- /dev/null +++ b/make/all @@ -0,0 +1,17 @@ +#!/bin/bash + +set -euo pipefail +. make/lib.sh + +echo "Install je trochu magický: + Spusť následující posloupnost příkazů: + make install_venv + . ${VENV_PATH}/bin/activate + make install_web + + Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev + Pokud chybová hláška obsahuje #include , nainstaluj si python3-dev + + Až skončíš s vývojem webu, spusť "deactivate". Tím zmizí '(${VENV_PATH})' ze začátku promptu." + + diff --git a/make/deploy b/make/deploy new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/deploy @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/deploy_prod b/make/deploy_prod new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/deploy_prod @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/install b/make/install new file mode 120000 index 00000000..d6d811b7 --- /dev/null +++ b/make/install @@ -0,0 +1 @@ +make/install_web \ No newline at end of file diff --git a/make/install_venv b/make/install_venv new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/install_venv @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/install_web b/make/install_web new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/install_web @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/lib.sh b/make/lib.sh new file mode 100644 index 00000000..e4aac157 --- /dev/null +++ b/make/lib.sh @@ -0,0 +1,26 @@ +#!/bin/false Tohle je knihovna, nemá se spouštět, ale načítat pomocí source(1) nebo '.' + +PYTHON="${PYTHON:-python3}" +VENV="${VENV:-${PYTHON} -m venv}" +VENV_PATH="${VENV_PATH:-env}" +BRANCH="${BRANCH:-master}" + +REPO="${REPO:-git@gitea.ks.matfyz.cz:mam/mamweb.git}" +GIMLI='gimli.ms.mff.cuni.cz' +GIMLI_LOGIN="mam-web@$GIMLI" +# Skutečné cesty, jak je vrátí `realpath` +PRODWEB="/aux/akce/mam/www/mamweb-prod" +TESTWEB="/aux/akce/mam/www/mamweb-test" + +function die { + echo "$@" >&2 + exit 1 +} + +# Vždycky chceme zajistit, že běžíme z rootu repozitáře +test -d '.git' || die "Make skript spuštěn ve špatné složce, spusť ho z kořenového adresáře repozitáře." + +function ensure_venv { + test -f "$VENV_PATH/bin/activate" || $VENV "$VENV_PATH" + . "$VENV_PATH/bin/activate" +} diff --git a/make/push_compiled_vue_to_test b/make/push_compiled_vue_to_test new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/push_compiled_vue_to_test @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/run b/make/run new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/run @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/schema b/make/schema new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/schema @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/schema_all.pdf b/make/schema_all.pdf new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/schema_all.pdf @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/schema_seminar.pdf b/make/schema_seminar.pdf new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/schema_seminar.pdf @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_local b/make/sync_local new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_local @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_local_db b/make/sync_local_db new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_local_db @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_local_media b/make/sync_local_media new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_local_media @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_prod_flatpages b/make/sync_prod_flatpages new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_prod_flatpages @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_test b/make/sync_test new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_test @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_test_db_aggressive b/make/sync_test_db_aggressive new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_test_db_aggressive @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/sync_test_media b/make/sync_test_media new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/sync_test_media @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/test b/make/test new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/test @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail diff --git a/make/venv_check b/make/venv_check new file mode 100755 index 00000000..60347f1e --- /dev/null +++ b/make/venv_check @@ -0,0 +1,3 @@ +#!/bin/bash + +set -exuo pipefail From 75f388ddfb0fd8780c79ceaecb8b4685ffe9d676 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 7 Nov 2022 22:34:54 +0100 Subject: [PATCH 02/68] Fix symlink --- make/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/install b/make/install index d6d811b7..53e51b50 120000 --- a/make/install +++ b/make/install @@ -1 +1 @@ -make/install_web \ No newline at end of file +install_web \ No newline at end of file From 9f78963e7f26963cca1d8442d9508f5f179aa7d2 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 7 Nov 2022 23:12:57 +0100 Subject: [PATCH 03/68] =?UTF-8?q?Pozn=C3=A1mka=20o=20neplatnosti=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 369dd30e..5d2f9c30 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**TODO: přepsat, tohle dávno neplatí!** + Basic commands for web development ================================== From 8b36e79f045c58d45f2432b9393f8c1babac0ff1 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 7 Nov 2022 23:14:06 +0100 Subject: [PATCH 04/68] Makefile reforma vol.2 [WIP] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Už máme ty jednoduché targety (nebo byly smazány), zbývá dořešit několik složitých. --- Makefile_old | 63 ---------------------------------- make/install_venv | 3 ++ make/install_web | 13 +++++++ make/lib.sh | 1 + make/push_compiled_vue_to_test | 6 ++++ make/run | 5 +++ make/schema | 6 ++++ make/schema_all.pdf | 3 -- make/schema_seminar.pdf | 3 -- make/sync_local | 3 -- make/sync_local_db | 3 -- make/sync_local_media | 3 -- make/test | 5 +++ 13 files changed, 39 insertions(+), 78 deletions(-) delete mode 100755 make/schema_all.pdf delete mode 100755 make/schema_seminar.pdf delete mode 100755 make/sync_local delete mode 100755 make/sync_local_db delete mode 100755 make/sync_local_media diff --git a/Makefile_old b/Makefile_old index ccfdb143..d9f1f8a2 100644 --- a/Makefile_old +++ b/Makefile_old @@ -1,44 +1,3 @@ -.PHONY: all venv_check clean install install_web install_venv clean_venv clean_schema run test deploy_test deploy_prod sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local - -install: install_web - -install_web: venv_check - @# venv může být příšerně starý, takže nejdříve upgradujeme venvové věci - pip install --upgrade pip - pip install --upgrade setuptools - # Instalace závislostí webu - pip install -r requirements.txt --upgrade - # Pro vygenerování tesdat spusť ./manage.py testdata - # Po vygenerování testdat spusť ./manage.py loaddata data/*, ať máš menu a další modely - # Pro synchronizaci flatpages spusť make sync_prod_flatpages - -install_venv: - ${VENV} ${VENV_PATH} - -clean_venv: - # Možná není 100% foolproof... - @test ! ${VENV_PATH} = . || ! echo "Smaž si prosím venv sám, nebudu mazat celý web" - rm -rfv ${VENV_PATH} - rm -f pip-selfcheck.json -clean_schema: - rm -f schema_seminar.pdf schema_all.pdf - -run: venv_check - ./manage.py runserver - -test: venv_check - ./manage.py test -v2 seminar mamweb - -# DB schemata - -schema: schema_seminar.pdf schema_all.pdf - -schema_seminar.pdf: venv_check - ./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf - -schema_all.pdf: venv_check - ./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf - # Deploy to current *mamweb-test* directory deploy: venv_check @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi @@ -104,25 +63,3 @@ sync_test_db_aggressive: # Sync test with production # HACK ALERT: using aggressive variant, due to the schemas being too different. sync_test: sync_test_media sync_test_db_aggressive - - -# Sync media directory with atrey. Useful for local development with production database -# Does not sync Galerie and CACHE (too huge). -sync_local_media: - rsync -ave ssh --exclude Galerie --exclude CACHE\ - mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/media/ ./media/ -# Downloads and restores production database to local database. PostgreSQL only. -sync_local_db: - scp mam-web@gimli.ms.mff.cuni.cz:`ssh mam-web@gimli.ms.mff.cuni.cz 'ls -v /akce/mam/www/backups/mam_prod-*\.pgdump.xz | tail -n 1'` \ - ./last.pgdump.xz - xz -fd last.pgdump.xz - pg_restore -c -d mam-prod last.pgdump - -# Sync database and media. See above lines -sync_local: sync_local_media sync_local_db - -# Push local compiled Vue to gimli test site -push_compiled_vue_to_test: - scp vue_frontend/webpack-stats.json mam-web@gimli:/akce/mam/www/mamweb-test/vue_frontend/ - rsync -ave ssh seminar/static/seminar/vue mam-web@gimli:/akce/mam/www/mamweb-test/seminar/static/seminar/ - ssh mam-web@gimli.ms.mff.cuni.cz 'cd /akce/mam/www/mamweb-test/ && . env/bin/activate && ./manage.py collectstatic --noinput' diff --git a/make/install_venv b/make/install_venv index 60347f1e..f5f3664f 100755 --- a/make/install_venv +++ b/make/install_venv @@ -1,3 +1,6 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +${VENV} ${VENV_PATH} diff --git a/make/install_web b/make/install_web index 60347f1e..5ebf963d 100755 --- a/make/install_web +++ b/make/install_web @@ -1,3 +1,16 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +ensure_venv + +# Aktualizace toolchainu +pip install --upgrade pip setuptools +# Instalace závislostí webu +pip install -r requirements.txt --upgrade + +# XXX: Připomínka z původního Makefile: +echo 'Pro vygenerování tesdat spusť ./manage.py testdata +Po vygenerování testdat spusť ./manage.py loaddata data/*, ať máš menu a další modely +Pro synchronizaci flatpages spusť make/sync_prod_flatpages' diff --git a/make/lib.sh b/make/lib.sh index e4aac157..3e4e99c9 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -18,6 +18,7 @@ function die { } # Vždycky chceme zajistit, že běžíme z rootu repozitáře +# TODO: chceme? Nechceme naopak umět to spouštět odkudkoliv, aspoň u většiny targetů? test -d '.git' || die "Make skript spuštěn ve špatné složce, spusť ho z kořenového adresáře repozitáře." function ensure_venv { diff --git a/make/push_compiled_vue_to_test b/make/push_compiled_vue_to_test index 60347f1e..8ed57cd4 100755 --- a/make/push_compiled_vue_to_test +++ b/make/push_compiled_vue_to_test @@ -1,3 +1,9 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +scp vue_frontend/webpack-stats.json "$GIMLI_LOGIN:$TESTWEB/vue_frontend/" +rsync -ave ssh seminar/static/seminar/vue "$GIMLI_LOGIN:$TESTWEB/seminar/static/seminar/" +# TODO: Je OK tady zapínat venv přímo takhle, nebo by to taky mělo být enkapsulováno do nějakého skriptu (e.g. make/deploy/collect_static)? +ssh "$GIMLI_LOGIN" "cd $TESTWEB && . env/bin/activate && ./manage.py collectstatic --noinput' diff --git a/make/run b/make/run index 60347f1e..44852432 100755 --- a/make/run +++ b/make/run @@ -1,3 +1,8 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +ensure_venv + +./manage.py runserver diff --git a/make/schema b/make/schema index 60347f1e..9688e49a 100755 --- a/make/schema +++ b/make/schema @@ -1,3 +1,9 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +ensure_venv + +./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf +./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf diff --git a/make/schema_all.pdf b/make/schema_all.pdf deleted file mode 100755 index 60347f1e..00000000 --- a/make/schema_all.pdf +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/schema_seminar.pdf b/make/schema_seminar.pdf deleted file mode 100755 index 60347f1e..00000000 --- a/make/schema_seminar.pdf +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/sync_local b/make/sync_local deleted file mode 100755 index 60347f1e..00000000 --- a/make/sync_local +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/sync_local_db b/make/sync_local_db deleted file mode 100755 index 60347f1e..00000000 --- a/make/sync_local_db +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/sync_local_media b/make/sync_local_media deleted file mode 100755 index 60347f1e..00000000 --- a/make/sync_local_media +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/test b/make/test index 60347f1e..bdf9f12b 100755 --- a/make/test +++ b/make/test @@ -1,3 +1,8 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +ensure_venv + +./manage.py test -v2 From 657e73f2f0ac199dc9bf82bae029b3e634a1af45 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 7 Nov 2022 23:15:39 +0100 Subject: [PATCH 05/68] =?UTF-8?q?Pozn=C3=A1mka=20o=20d=C5=AFvodu=20existen?= =?UTF-8?q?ce=20Makefile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5e3acddc..5f902dda 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# Existence tohohle Makefile je tu jen proto, aby fungovala svalová paměť. Pokud můžete, použijte rovnou `make/…` %: @make/$* From 4f7c4057eafd8e49700650a57e4ead3f732addd5 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 14 Nov 2022 21:37:01 +0100 Subject: [PATCH 06/68] fix uvozovek Thanks shellcheck --- make/all | 2 +- make/push_compiled_vue_to_test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/make/all b/make/all index de25100a..c6a92157 100755 --- a/make/all +++ b/make/all @@ -12,6 +12,6 @@ echo "Install je trochu magický: Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev Pokud chybová hláška obsahuje #include , nainstaluj si python3-dev - Až skončíš s vývojem webu, spusť "deactivate". Tím zmizí '(${VENV_PATH})' ze začátku promptu." + Až skončíš s vývojem webu, spusť 'deactivate'. Tím zmizí '(${VENV_PATH})' ze začátku promptu." diff --git a/make/push_compiled_vue_to_test b/make/push_compiled_vue_to_test index 8ed57cd4..f386ee86 100755 --- a/make/push_compiled_vue_to_test +++ b/make/push_compiled_vue_to_test @@ -6,4 +6,4 @@ set -exuo pipefail scp vue_frontend/webpack-stats.json "$GIMLI_LOGIN:$TESTWEB/vue_frontend/" rsync -ave ssh seminar/static/seminar/vue "$GIMLI_LOGIN:$TESTWEB/seminar/static/seminar/" # TODO: Je OK tady zapínat venv přímo takhle, nebo by to taky mělo být enkapsulováno do nějakého skriptu (e.g. make/deploy/collect_static)? -ssh "$GIMLI_LOGIN" "cd $TESTWEB && . env/bin/activate && ./manage.py collectstatic --noinput' +ssh "$GIMLI_LOGIN" "cd $TESTWEB && . env/bin/activate && ./manage.py collectstatic --noinput" From a9e7cd7af27014dc3904ae9039fb9feb68b09daa Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 14 Nov 2022 23:16:19 +0100 Subject: [PATCH 07/68] =?UTF-8?q?Deploy=20v=20nov=C3=A9m=20kab=C3=A1tu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prosím čtěte… --- Makefile_old | 35 ----------------------------------- make/deploy | 22 ++++++++++++++++++++++ make/deploy_prod | 31 +++++++++++++++++++++++++++++++ make/lib.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 35 deletions(-) diff --git a/Makefile_old b/Makefile_old index d9f1f8a2..20a19bdf 100644 --- a/Makefile_old +++ b/Makefile_old @@ -1,38 +1,3 @@ -# Deploy to current *mamweb-test* directory -deploy: venv_check - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in directory mamweb-test"; exit 1; fi - @echo "Installing version from origin/${BRANCH} ..." - git pull origin ${BRANCH} - git clean -f - make install - ./manage.py migrate - ./manage.py collectstatic --noinput - (chown -R :mam . || true ) - (chmod -R g+rX,go-w . || true ) - @echo Restarting systemd unit - systemctl --user restart mamweb-test.service - @echo Done. - -# Deploy to current *mamweb-prod* directory -deploy_prod: venv_check - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-prod" ]; then echo "Only possible in directory mamweb-prod"; exit 1; fi - @echo "Backing up production DB ..." - ( cd -P .. && ./backup_prod_db.sh ) - @echo "Installing version from origin/master ..." - git pull origin master - git clean -f - make install - ./manage.py migrate - ./manage.py collectstatic --noinput - (chown -R :mam . || true ) - (chmod -R g+rX,go-w . || true ) - @echo Restarting systemd user unit for MaM web - systemctl --user restart mamweb-prod.service - @echo Done. - - sync_prod_flatpages: venv_check @echo Downloading current version of flatpages from mamweb-prod. ssh mam-web@gimli.ms.mff.cuni.cz \ diff --git a/make/deploy b/make/deploy index 60347f1e..d25df6ce 100755 --- a/make/deploy +++ b/make/deploy @@ -1,3 +1,25 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +if test "$USER" != "mam-web"; +then + echo >&2 "Nasadit web smí jen uživatel mam-web" + exit 1 +fi + +if test "$(readlink -f .)" != "$TESTWEB"; +then + echo >&2 "Nasadit testweb lze jen v jeho složce" + exit 1 +fi + +CURRENT_BRANCH="$(git branch --show-current)" +BRANCH="${1:-$CURRENT_BRANCH}" + +safe_checkout_branch "$BRANCH" "$0" + +# Teď máme správnou větev, jdeme vše nainstalovat +install_everything +systemctl --user restart mamweb-test.service diff --git a/make/deploy_prod b/make/deploy_prod index 60347f1e..8e006938 100755 --- a/make/deploy_prod +++ b/make/deploy_prod @@ -1,3 +1,34 @@ #!/bin/bash set -exuo pipefail +. make/lib.sh + +if test "$USER" != "mam-web" +then + echo >&2 "Nasadit web smí jen uživatel mam-web" + exit 1 +fi + +if test "$(readlink -f .)" != "$PRODWEB" +then + echo >&2 "Nasadit testweb lze jen v jeho složce" + exit 1 +fi + +CURRENT_BRANCH="$(git branch --show-current)" +BRANCH="${1:-$CURRENT_BRANCH}" + +if test "$BRANCH" != master +then + echo "Pozor, nasazuješ na produkci větev, která není master ($BRANCH), chceš pokračovat? Pokud ne, sestřel tento skript." + read +fi + +# Záloha DB +( cd -P .. && ./backup_prod_db.sh ) + +safe_checkout_branch "$BRANCH" "$0" + +# Teď máme správnou větev, jdeme vše nainstalovat +install_everything +systemctl --user restart mamweb-prod.service diff --git a/make/lib.sh b/make/lib.sh index 3e4e99c9..fb56e991 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -25,3 +25,45 @@ function ensure_venv { test -f "$VENV_PATH/bin/activate" || $VENV "$VENV_PATH" . "$VENV_PATH/bin/activate" } + + +function safe_checkout_branch { + if "$#" -ne 2; + then + echo >&2 "Použití: $0 " + return 1 + fi + + BRANCH="$1" + SCRIPT="$2" + + echo "Debug: I am $0, $SCRIPT as param" + + git fetch --all + # 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ěží. + if test $(git rev-parse @:make/lib.sh) != $(git rev-parse "$BRANCH":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 "$BRANCH":"$SCRIPT") + then + echo >&2 "Změna v $SCRIPT, prosím pullni manuálně" + exit 1 + fi + git checkout "$BRANCH" + git pull + git clean -f +} + +function install_everything { + # Skoro celé nasazení webu je stejné pro testweb i pro produkci, tak je to tady dohromady + ensure_venv + make/install + ./manage.py migrate + ./manage.py collectstatic --noinput + chown -R :mam . || true + chmod -R g+rX,go-w . || true +} + From d80babfd73cab28df5ba6effe77edf680e51d2d6 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 14 Nov 2022 23:20:55 +0100 Subject: [PATCH 08/68] =?UTF-8?q?Smaz=C3=A1n=20obsah=20make/sync*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nic tam nebylo a teď je vidět ve `file *`, že tam nic není. --- make/sync_prod_flatpages | 3 --- make/sync_test | 3 --- make/sync_test_db_aggressive | 3 --- make/sync_test_media | 3 --- 4 files changed, 12 deletions(-) diff --git a/make/sync_prod_flatpages b/make/sync_prod_flatpages index 60347f1e..e69de29b 100755 --- a/make/sync_prod_flatpages +++ b/make/sync_prod_flatpages @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/sync_test b/make/sync_test index 60347f1e..e69de29b 100755 --- a/make/sync_test +++ b/make/sync_test @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/sync_test_db_aggressive b/make/sync_test_db_aggressive index 60347f1e..e69de29b 100755 --- a/make/sync_test_db_aggressive +++ b/make/sync_test_db_aggressive @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail diff --git a/make/sync_test_media b/make/sync_test_media index 60347f1e..e69de29b 100755 --- a/make/sync_test_media +++ b/make/sync_test_media @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail From 323477dbf23a46fa20e59ca47e5968a1c18e600c Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 14 Nov 2022 23:21:20 +0100 Subject: [PATCH 09/68] =?UTF-8?q?Smaz=C3=A1n=20venv=5Fcheck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Je úplně k ničemu, když si nové skripty zapínají venv samy --- make/venv_check | 3 --- 1 file changed, 3 deletions(-) delete mode 100755 make/venv_check diff --git a/make/venv_check b/make/venv_check deleted file mode 100755 index 60347f1e..00000000 --- a/make/venv_check +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -set -exuo pipefail From f6d939fc31251ddfe451930e57275f842f287356 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 15 Nov 2022 11:48:48 +0100 Subject: [PATCH 10/68] =?UTF-8?q?P=C5=99ebyte=C4=8Dn=C3=BD=20st=C5=99edn?= =?UTF-8?q?=C3=ADk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib.sh b/make/lib.sh index fb56e991..8ae08e1f 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -28,7 +28,7 @@ function ensure_venv { function safe_checkout_branch { - if "$#" -ne 2; + if "$#" -ne 2 then echo >&2 "Použití: $0 " return 1 From 0458abb41900904d96d3a2d82f516296aa8509ae Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 15 Nov 2022 11:58:22 +0100 Subject: [PATCH 11/68] Kontroly prerekvizit do knihovny --- make/deploy | 13 ++----------- make/deploy_prod | 13 ++----------- make/lib.sh | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/make/deploy b/make/deploy index d25df6ce..4e93d5e1 100755 --- a/make/deploy +++ b/make/deploy @@ -3,17 +3,8 @@ set -exuo pipefail . make/lib.sh -if test "$USER" != "mam-web"; -then - echo >&2 "Nasadit web smí jen uživatel mam-web" - exit 1 -fi - -if test "$(readlink -f .)" != "$TESTWEB"; -then - echo >&2 "Nasadit testweb lze jen v jeho složce" - exit 1 -fi +gimli_only +only_in_directory "$TESTWEB" CURRENT_BRANCH="$(git branch --show-current)" BRANCH="${1:-$CURRENT_BRANCH}" diff --git a/make/deploy_prod b/make/deploy_prod index 8e006938..0c10219d 100755 --- a/make/deploy_prod +++ b/make/deploy_prod @@ -3,17 +3,8 @@ set -exuo pipefail . make/lib.sh -if test "$USER" != "mam-web" -then - echo >&2 "Nasadit web smí jen uživatel mam-web" - exit 1 -fi - -if test "$(readlink -f .)" != "$PRODWEB" -then - echo >&2 "Nasadit testweb lze jen v jeho složce" - exit 1 -fi +gimli_only +only_in_directory "$PRODWEB" CURRENT_BRANCH="$(git branch --show-current)" BRANCH="${1:-$CURRENT_BRANCH}" diff --git a/make/lib.sh b/make/lib.sh index 8ae08e1f..20329d3f 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -26,6 +26,24 @@ function ensure_venv { . "$VENV_PATH/bin/activate" } +function gimli_only { + # Rovnou zkontrolujeme i uživatele + if test "$HOSTNAME" != gimli -o "$USER" != mam-web + then + echo "Tento příkaz se má spouštět na gimlim, chceš pokračovat? Pokud ne, sestřel tento skript." + read + fi +} + +function only_in_directory { + DIR="$1" + CURRENT="$(readlink -f .)" + if test "$CURRENT" != "$DIR" + then + echo "Tento příkaz se má spouštět ve složce $DIR, chceš pokračovat? Pokud ne, sestřel tento skript." + read + fi +} function safe_checkout_branch { if "$#" -ne 2 From 5cfadf9236890bcfc418f1b9af6aa223d7e1d1d1 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 15 Nov 2022 12:05:12 +0100 Subject: [PATCH 12/68] =?UTF-8?q?Make:=20p=C5=99esunuty=20sync=5Ftest=5Fme?= =?UTF-8?q?dia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Taky jsem smazal nějaké komentáře v Makefile_old, aby nepřekážely. --- Makefile_old | 8 -------- make/sync_test_media | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Makefile_old b/Makefile_old index 20a19bdf..7f3799cc 100644 --- a/Makefile_old +++ b/Makefile_old @@ -7,12 +7,6 @@ sync_prod_flatpages: venv_check ./manage.py loaddata data/flat.json @echo "Done." -# Sync test media directory with production -sync_test_media: - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - @if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi - rsync -av --delete /akce/mam/www/mamweb-prod/media/ ./media - # Sync (with drop) test database with production database sync_test_db_aggressive: @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi @@ -25,6 +19,4 @@ sync_test_db_aggressive: psql mam_test -c "UPDATE django_site SET name='MaMweb (test)', domain='mam-test.ks.matfyz.cz' WHERE id=1" @echo Done. -# Sync test with production -# HACK ALERT: using aggressive variant, due to the schemas being too different. sync_test: sync_test_media sync_test_db_aggressive diff --git a/make/sync_test_media b/make/sync_test_media index e69de29b..d7991b65 100755 --- a/make/sync_test_media +++ b/make/sync_test_media @@ -0,0 +1,9 @@ +#!/bin/bash + +set -exuo pipefail +. make/lib.sh + +gimli_only +only_in_dir "$TESTWEB" + +rsync -av --delete "$PRODWEB/media/" ./media From 5abd93d27f82df656f95d66c823216ab6fc54ece Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 15 Nov 2022 12:16:50 +0100 Subject: [PATCH 13/68] Zbytek sync_test --- Makefile_old | 14 -------------- make/sync_test | 11 +++++++++++ make/sync_test_db_aggressive | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Makefile_old b/Makefile_old index 7f3799cc..3b32e7e7 100644 --- a/Makefile_old +++ b/Makefile_old @@ -6,17 +6,3 @@ sync_prod_flatpages: venv_check @echo "Applying downloaded flatpages." ./manage.py loaddata data/flat.json @echo "Done." - -# Sync (with drop) test database with production database -sync_test_db_aggressive: - @if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi - pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql - pg_dump -Fc mam_prod > dump-prod.sql - @# I am not sure which shell is used, so I am calling bash to make sure - psql mam_test -c 'DROP OWNED BY "mam-web";' - pg_restore -c --if-exists -d mam_test dump-prod.sql - rm dump-prod.sql - psql mam_test -c "UPDATE django_site SET name='MaMweb (test)', domain='mam-test.ks.matfyz.cz' WHERE id=1" - @echo Done. - -sync_test: sync_test_media sync_test_db_aggressive diff --git a/make/sync_test b/make/sync_test index e69de29b..68c6020d 100755 --- a/make/sync_test +++ b/make/sync_test @@ -0,0 +1,11 @@ +#!/bin/bash + +set -exuo pipefail +. make/lib.sh + +# Prerekvizity nekontrolujeme, dokud voláme další make skripty, tak by akorát +# vedly k víc dotazům na stejnou věc a bylo by to otravné. Pokud tu někdy bude +# něco jiného, tak pak ať tu prerekvizity zmíněné jsou. + +make/sync_test_db_aggressive +make/sync_test_media diff --git a/make/sync_test_db_aggressive b/make/sync_test_db_aggressive index e69de29b..11faba7b 100755 --- a/make/sync_test_db_aggressive +++ b/make/sync_test_db_aggressive @@ -0,0 +1,18 @@ +#!/bin/bash + +set -exuo pipefail +. make/lib.sh + +gimli_only +# Teoreticky není potřeba, ale stejně jinde make skripty nejsou a pouštět to z +# produkce nezní jako běžný stav, kromě toho to aktuálně vyrábí pomocné soubory +# v aktuální složce (FIXME do budoucna) a to na produkci nechceme +only_in_directory "$TESTWEB" + +pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql +pg_dump -Fc mam_prod > dump-prod.sql +psql mam_test -c 'DROP OWNED BY "mam-web";' +pg_restore -c --if-exists -d mam_test dump-prod.sql +rm dump-prod.sql +psql mam_test -c "UPDATE django_site SET name='MaMweb (test)', domain='mam-test.ks.matfyz.cz' WHERE id=1" + From 7c90c1ef5e4b7343ca6bc4a7d7a7c78c0c7b3af3 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 15 Nov 2022 12:43:31 +0100 Subject: [PATCH 14/68] sync_prod_flatpages --- Makefile_old | 8 -------- make/sync_prod_flatpages | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) delete mode 100644 Makefile_old diff --git a/Makefile_old b/Makefile_old deleted file mode 100644 index 3b32e7e7..00000000 --- a/Makefile_old +++ /dev/null @@ -1,8 +0,0 @@ -sync_prod_flatpages: venv_check - @echo Downloading current version of flatpages from mamweb-prod. - ssh mam-web@gimli.ms.mff.cuni.cz \ - "cd /akce/mam/www/mamweb-prod; . env/bin/activate; ./manage.py dumpdata flatpages --indent=2 > flat.json; ./fix_json.py flat.json flat_fixed.json" - rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat_fixed.json data/flat.json - @echo "Applying downloaded flatpages." - ./manage.py loaddata data/flat.json - @echo "Done." diff --git a/make/sync_prod_flatpages b/make/sync_prod_flatpages index e69de29b..76c31f1b 100755 --- a/make/sync_prod_flatpages +++ b/make/sync_prod_flatpages @@ -0,0 +1,18 @@ +#!/bin/bash + +set -exuo pipefail +. make/lib.sh + +ensure_venv + +# TODO: This is very ugly, will fix in a future PR (hopefully) +ssh "$GIMLI_LOGIN" " + cd $PRODWEB + . env/bin/activate + ./manage.py dumpdata flatpages --indent=2 > flat.json + ./fix_json.py flat.json flat_fixed.json + " +rsync -ave ssh "$GIMLI_LOGIN:$PRODWEB/flat_fixed.json" data/flat.json + +./manage.py loaddata data/flat.json + From 4fd3a0c4f51f57a45a5bdf14fd73dabc1135aea4 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 17 Nov 2022 01:57:37 +0100 Subject: [PATCH 15/68] =?UTF-8?q?Hlasit=C4=9Bj=C5=A1=C3=AD=20varov=C3=A1n?= =?UTF-8?q?=C3=AD=20p=C5=99i=20pou=C5=BEit=C3=AD=20make?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5f902dda..ff0af09e 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ # Existence tohohle Makefile je tu jen proto, aby fungovala svalová paměť. Pokud můžete, použijte rovnou `make/…` %: - @make/$* + # Používání make jako příkazu je zastaralé, prosím používej radši skripty ze složky make. Spouštím následující příkaz: + make/$* all: @# Nevím, proč to nefunguje bez těla, ale vlastně je mi to jedno… - @make/all + make/all .PHONY: all From 31834b7f8a26df3ab146152988bb416d2533f938 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:12:35 +0100 Subject: [PATCH 16/68] =?UTF-8?q?Zru=C5=A1en=20`make/all`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nic moc nedělal, tak jsem ho nahradil (IMHO lepší) dokumentací. --- Makefile | 3 +-- make/README.md | 34 ++++++++++++++++++++++++++++++++++ make/all | 17 ----------------- 3 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 make/README.md delete mode 100755 make/all diff --git a/Makefile b/Makefile index ff0af09e..09d9acc8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,6 @@ make/$* all: - @# Nevím, proč to nefunguje bez těla, ale vlastně je mi to jedno… - make/all + @cat make/README.md .PHONY: all diff --git a/make/README.md b/make/README.md new file mode 100644 index 00000000..1d1baa47 --- /dev/null +++ b/make/README.md @@ -0,0 +1,34 @@ +Milý člověče, M&Mí web tě vítá. Prosím, neděs se, zkusím tě provést lokálním zprovozněním webu. + +Předně: většina příkazů bude asi vypisovat spoustu detailů, takže ti doporučuji +si tento text otevřít někde separátně. Nachází se v repozitáři v +`make/README.md`, případně si jej můžeš zobrazit hezčeji vykreslený na +[Gitee](https://gitea.ks.matfyz.cz/mam/mamweb/src/branch/master/make/README.md). + +O zprovoznění webu se stará hlavně skript `make/install_web`. Ten vytvoří +virtualenv (neexistuje-li) a nainstaluje do něj závislosti webu. Pak ovšem +budeš potřebovat nahrát další data do databáze, což uděláš pomocí příkazů +`./manage.py testdata` a `./manage.py loaddata data/*`. Skript +`make/install_web` ti to kdyžtak připomene. + +Samotný web spustíš třeba pomocí `make/run`, nebo ekvivalentně `./manage.py runserver`. + +Pozor: zatímco skripty v `make/` to nepotřebují, pro použití skriptu +`./manage.py` se potřebuješ přepnout do virtuálního prostředí. To uděláš velmi +pravděpodobně spuštěním `source env/bin/activate`, před začátkem _promptu_ by +se mělo objevit `(env)`. Pro opuštění spusť `deactivate`. + +Časté problémy +----- +Je možné, že nemáš všechny potřebné závislosti v systému. Proto je možné, že +`make/install_web` vyhodí nějakou chybovou hlášku: + +- `Error: pg_config executable not found.`: nainstaluj si `libpq-dev` (na Ubuntu/Debianu, jinde se příslušný balíček může jmenovat jinak) +- Chybová hláška obsahuje `#include `: nainstaluj si `python3-dev` + + + diff --git a/make/all b/make/all deleted file mode 100755 index c6a92157..00000000 --- a/make/all +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -euo pipefail -. make/lib.sh - -echo "Install je trochu magický: - Spusť následující posloupnost příkazů: - make install_venv - . ${VENV_PATH}/bin/activate - make install_web - - Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev - Pokud chybová hláška obsahuje #include , nainstaluj si python3-dev - - Až skončíš s vývojem webu, spusť 'deactivate'. Tím zmizí '(${VENV_PATH})' ze začátku promptu." - - From 1a56ba02f35d2540ca176276be64dfbe35c2277d Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:13:15 +0100 Subject: [PATCH 17/68] =?UTF-8?q?Make:=20v=C3=BDchoz=C3=AD=20target=20se?= =?UTF-8?q?=20jmenuje=20`default`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `all` tam nemá žádnou sémantiku… --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 09d9acc8..fb967112 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Používání make jako příkazu je zastaralé, prosím používej radši skripty ze složky make. Spouštím následující příkaz: make/$* -all: +default: @cat make/README.md -.PHONY: all +.PHONY: default From d0865010956dbf66f885e87c88050237b03248e6 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:15:00 +0100 Subject: [PATCH 18/68] =?UTF-8?q?make/lib:=20lok=C3=A1ln=C3=AD=20prom?= =?UTF-8?q?=C4=9Bnn=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/make/lib.sh b/make/lib.sh index 20329d3f..727df395 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -36,8 +36,8 @@ function gimli_only { } function only_in_directory { - DIR="$1" - CURRENT="$(readlink -f .)" + local DIR="$1" + local CURRENT="$(readlink -f .)" if test "$CURRENT" != "$DIR" then echo "Tento příkaz se má spouštět ve složce $DIR, chceš pokračovat? Pokud ne, sestřel tento skript." @@ -52,8 +52,8 @@ function safe_checkout_branch { return 1 fi - BRANCH="$1" - SCRIPT="$2" + local BRANCH="$1" + local SCRIPT="$2" echo "Debug: I am $0, $SCRIPT as param" From 346079cee3e0eb20c924bf09af61e59eac8106a4 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:17:57 +0100 Subject: [PATCH 19/68] make/lib: Funkce install_everything je jen pro Gimliho --- make/lib.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/make/lib.sh b/make/lib.sh index 727df395..bc919886 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -77,6 +77,7 @@ function safe_checkout_branch { function install_everything { # Skoro celé nasazení webu je stejné pro testweb i pro produkci, tak je to tady dohromady + gimli_only ensure_venv make/install ./manage.py migrate From ac9cb53185edf2c2ee29bea8bffece0d21015bc2 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:23:41 +0100 Subject: [PATCH 20/68] =?UTF-8?q?Hez=C4=8D=C3=AD=20SSH=20spojen=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Přidal jsem `set -euxo pipefail`, takže nejsou potřeba `&&` a obecně se to chová víc jako ostatní make skripty - Venv se zapíná stejně jako v lokálních skriptech, takže se dá jednoduše změnit jeho cesta --- make/push_compiled_vue_to_test | 9 +++++++-- make/sync_prod_flatpages | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/make/push_compiled_vue_to_test b/make/push_compiled_vue_to_test index f386ee86..99495a7b 100755 --- a/make/push_compiled_vue_to_test +++ b/make/push_compiled_vue_to_test @@ -5,5 +5,10 @@ set -exuo pipefail scp vue_frontend/webpack-stats.json "$GIMLI_LOGIN:$TESTWEB/vue_frontend/" rsync -ave ssh seminar/static/seminar/vue "$GIMLI_LOGIN:$TESTWEB/seminar/static/seminar/" -# TODO: Je OK tady zapínat venv přímo takhle, nebo by to taky mělo být enkapsulováno do nějakého skriptu (e.g. make/deploy/collect_static)? -ssh "$GIMLI_LOGIN" "cd $TESTWEB && . env/bin/activate && ./manage.py collectstatic --noinput" +ssh "$GIMLI_LOGIN" " + set -euxo pipefail + cd $TESTWEB + . make/lib.sh + ensure_venv + ./manage.py collectstatic --noinput + " diff --git a/make/sync_prod_flatpages b/make/sync_prod_flatpages index 76c31f1b..4d9d8e1f 100755 --- a/make/sync_prod_flatpages +++ b/make/sync_prod_flatpages @@ -7,8 +7,10 @@ ensure_venv # TODO: This is very ugly, will fix in a future PR (hopefully) ssh "$GIMLI_LOGIN" " + set -euxo pipefail cd $PRODWEB - . env/bin/activate + . make/lib.sh + ensure_venv ./manage.py dumpdata flatpages --indent=2 > flat.json ./fix_json.py flat.json flat_fixed.json " From e36410ee823bffb7e8dbe0be819aa78fc391cbea Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:27:16 +0100 Subject: [PATCH 21/68] =?UTF-8?q?make/lib:=20koment=C3=A1=C5=99e=20kolem?= =?UTF-8?q?=20git-rev-parse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/make/lib.sh b/make/lib.sh index bc919886..062dc617 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -60,12 +60,13 @@ function safe_checkout_branch { git fetch --all # 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ěží. - if test $(git rev-parse @:make/lib.sh) != $(git rev-parse "$BRANCH":make/lib.sh) + # `git rev-parse` dává SHA-1 hashe objektů, vizte manuálovou stránku pro pochopení. + if test "$(git rev-parse @:make/lib.sh)" != "$(git rev-parse "$BRANCH":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 "$BRANCH":"$SCRIPT") + if test "$(git rev-parse @:"$SCRIPT")" != "$(git rev-parse "$BRANCH":"$SCRIPT")" then echo >&2 "Změna v $SCRIPT, prosím pullni manuálně" exit 1 From 28760e2c4d0e8adb43c90b3eeed7f9c764996686 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:33:19 +0100 Subject: [PATCH 22/68] =?UTF-8?q?Smaz=C3=A1n=20install=5Fvenv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Všechny make skripty stejně vyrábí venv přes `ensure_venv` a protože web nikdo nikdy nebude instalovat jinak (nebo když bude, tak asi ví, co dělá), tak tohle nedává smysl spouštět. --- make/install_venv | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 make/install_venv diff --git a/make/install_venv b/make/install_venv deleted file mode 100755 index f5f3664f..00000000 --- a/make/install_venv +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -set -exuo pipefail -. make/lib.sh - -${VENV} ${VENV_PATH} From 5963089539c955363f18a2558f5175ce5ae4fdae Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:37:27 +0100 Subject: [PATCH 23/68] =?UTF-8?q?make/lib:=20.git=20m=C5=AF=C5=BEe=20b?= =?UTF-8?q?=C3=BDt=20i=20norm=C3=A1ln=C3=AD=20soubor=20(worktree)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib.sh b/make/lib.sh index 062dc617..7df79d82 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -19,7 +19,7 @@ function die { # Vždycky chceme zajistit, že běžíme z rootu repozitáře # TODO: chceme? Nechceme naopak umět to spouštět odkudkoliv, aspoň u většiny targetů? -test -d '.git' || die "Make skript spuštěn ve špatné složce, spusť ho z kořenového adresáře repozitáře." +test -e '.git' || die "Make skript spuštěn ve špatné složce, spusť ho z kořenového adresáře repozitáře." function ensure_venv { test -f "$VENV_PATH/bin/activate" || $VENV "$VENV_PATH" From e4c2eda955aef9c1442189273f552f20401158c9 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:38:03 +0100 Subject: [PATCH 24/68] make/run bere parametry --- make/run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/run b/make/run index 44852432..c601593a 100755 --- a/make/run +++ b/make/run @@ -5,4 +5,4 @@ set -exuo pipefail ensure_venv -./manage.py runserver +./manage.py runserver "$@" From a390ef03293d70945800a3fecbe5041ebfed03d9 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:40:03 +0100 Subject: [PATCH 25/68] =?UTF-8?q?make/lib:=20safe=5Fcheckout=5Fbranch=20st?= =?UTF-8?q?a=C4=8D=C3=AD=201=20parametr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/deploy | 2 +- make/deploy_prod | 2 +- make/lib.sh | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/make/deploy b/make/deploy index 4e93d5e1..24ade165 100755 --- a/make/deploy +++ b/make/deploy @@ -9,7 +9,7 @@ only_in_directory "$TESTWEB" CURRENT_BRANCH="$(git branch --show-current)" BRANCH="${1:-$CURRENT_BRANCH}" -safe_checkout_branch "$BRANCH" "$0" +safe_checkout_branch "$BRANCH" # Teď máme správnou větev, jdeme vše nainstalovat install_everything diff --git a/make/deploy_prod b/make/deploy_prod index 0c10219d..ec3110c6 100755 --- a/make/deploy_prod +++ b/make/deploy_prod @@ -18,7 +18,7 @@ fi # Záloha DB ( cd -P .. && ./backup_prod_db.sh ) -safe_checkout_branch "$BRANCH" "$0" +safe_checkout_branch "$BRANCH" # Teď máme správnou větev, jdeme vše nainstalovat install_everything diff --git a/make/lib.sh b/make/lib.sh index 7df79d82..581252cf 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -48,14 +48,12 @@ function only_in_directory { function safe_checkout_branch { if "$#" -ne 2 then - echo >&2 "Použití: $0 " + echo >&2 "Použití: $0 " return 1 fi local BRANCH="$1" - local SCRIPT="$2" - - echo "Debug: I am $0, $SCRIPT as param" + local SCRIPT="$0" git fetch --all # Od teď si musíme dát pozor, abychom nezměnili kód, který právě běží. From 1615e921590d06e151d80b3bf8e56e615bc0ee2d Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:45:48 +0100 Subject: [PATCH 26/68] =?UTF-8?q?safe=5Fcheckout=5Fbranch:=20porovn=C3=A1v?= =?UTF-8?q?=C3=A1me=20proti=20upstreamu,=20ne=20aktu=C3=A1ln=C3=AD=20verzi?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/lib.sh b/make/lib.sh index 581252cf..e45df48f 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -59,12 +59,12 @@ function safe_checkout_branch { # 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í. - if test "$(git rev-parse @:make/lib.sh)" != "$(git rev-parse "$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 "$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 From 34e751fd699b4b0e637935848b00145925925a4c Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:52:51 +0100 Subject: [PATCH 27/68] =?UTF-8?q?fixup!=20make/lib:=20safe=5Fcheckout=5Fbr?= =?UTF-8?q?anch=20sta=C4=8D=C3=AD=201=20parametr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib.sh b/make/lib.sh index e45df48f..2085ad8f 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -46,7 +46,7 @@ function only_in_directory { } function safe_checkout_branch { - if "$#" -ne 2 + if test "$#" -ne 1 then echo >&2 "Použití: $0 " return 1 From b1e6448c3c47a0b2bc936c9bb4da18cdda3fb348 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 04:57:48 +0100 Subject: [PATCH 28/68] =?UTF-8?q?safe=5Fcheckout=5Fbranch:=20varov=C3=A1n?= =?UTF-8?q?=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/make/lib.sh b/make/lib.sh index 2085ad8f..ce4c9a4d 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -59,6 +59,7 @@ function safe_checkout_branch { # 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 "$BRANCH"@{u}:make/lib.sh)" then echo >&2 "Změna v make/lib.sh, prosím pullni manuálně" From 3fcc03b769014fad6be594c18b3d714eae1901a4 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 05:08:24 +0100 Subject: [PATCH 29/68] Shellcheck :-) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ne že by mi na tom záviselo, ale kód to nezhoršuje a pokud to aspoň o trochu zmenší šanci na nějaké přehlédnutí, tak je to OK. A spoustu varování shellchecku jsem vyignoroval a nemíním plevelit kód komentáři, o čem všem vím a on ne :-) --- make/lib.sh | 4 ++-- make/sync_test_db_aggressive | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/make/lib.sh b/make/lib.sh index ce4c9a4d..f04b9941 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -60,12 +60,12 @@ function safe_checkout_branch { # 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 "$BRANCH"@{u}: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 "$BRANCH"@{u}:"$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 diff --git a/make/sync_test_db_aggressive b/make/sync_test_db_aggressive index 11faba7b..9acce93b 100755 --- a/make/sync_test_db_aggressive +++ b/make/sync_test_db_aggressive @@ -9,7 +9,7 @@ gimli_only # v aktuální složce (FIXME do budoucna) a to na produkci nechceme only_in_directory "$TESTWEB" -pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql +pg_dump mam_test > "dump-test-$(date +"%Y%m%d_%H%M").sql" pg_dump -Fc mam_prod > dump-prod.sql psql mam_test -c 'DROP OWNED BY "mam-web";' pg_restore -c --if-exists -d mam_test dump-prod.sql From a184871bf9b26aa4977e5227a809a7a4811b24bd Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 05:16:02 +0100 Subject: [PATCH 30/68] =?UTF-8?q?make/lib:=20Kdy=C5=BE=20se=20to=20nepoved?= =?UTF-8?q?e,=20tak=20budeme=20k=C5=99i=C4=8Det?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uvědomil jsem si, že aktuálně nejde skoro vůbec poznat, jestli make skript uspěl nebo ne. Tohle by se mělo vypsat, když se nepovede. Víc by se mi líbilo, kdyby úspěšné doběhnutí ohlásilo "OK", ale to neumím udělat bez nějakého zápatí skriptů. (Resp. uměl bych: make/lib může být interpretr, který na začátku zinicalizuje proměnné, pak natáhne příslušný skript a na konci ohlásí OK. Ale přijde mi to trochu moc magické, takže pokud někdo nebude nějak extra pro, tak to tak neudělám :-)) --- make/lib.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make/lib.sh b/make/lib.sh index f04b9941..135f859e 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -17,6 +17,8 @@ function die { exit 1 } +trap 'echo Něco se nepovedlo :-/' ERR + # Vždycky chceme zajistit, že běžíme z rootu repozitáře # TODO: chceme? Nechceme naopak umět to spouštět odkudkoliv, aspoň u většiny targetů? test -e '.git' || die "Make skript spuštěn ve špatné složce, spusť ho z kořenového adresáře repozitáře." From 50eaaf9eb7838b8560e2823b26bda124c8e8f054 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 15:38:41 +0100 Subject: [PATCH 31/68] =?UTF-8?q?P=C5=99ed=C4=9Bl=C3=A1no=20Readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Teď vypadá víc jako readme, na které chceš narazit v gitee, než jako pár random tipů. Random tipy jsem přesunul do dokumentace --- README.md | 137 +++++++++++++++++++++++------------------------------- 1 file changed, 58 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 5d2f9c30..94b8cf2d 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,58 @@ -**TODO: přepsat, tohle dávno neplatí!** - -Basic commands for web development -================================== - -After you clone this repository, run `make`. It will download, locally install -and setup virtualenv and pip, and then locally install all required packages -from `requirements.txt`. - -When working with the code, always use the binaries in `./bin/`, such as -`bin/pip`, `bin/python`, ... never the global python, pip, ... -Use `make` and `./manage.py` for most things. - -Use git :-) - -Quickstart ----------- -Run the following commands: - make install_venv - . env/bin/activate - make install_web - -Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev -Pokud chybová hláška obsahuje #include , nainstaluj si python3-dev - -After finishing development, run "deactivate". - -Make commands -------------- - -* `make install` (or `make`) - locally install and setup virtualpy, install - required packages. Ran again installs missing packages. Run after changing - `requirements.txt`. - -* `make clean` - remove local python packages. - -* `make veryclean` - remove local packages and virtualpy enviroment and - binaries. - -* `make run` - runs "./manage.py runserver_plus" - -* `make push_test` - pushes the last commited version to test location. - Only git-commited changes are pushed! Rest is re-generated from scratch. - At test server, the media data and database are kept the same. - Everything else not in .gitignore is deleted/overwritten on the test server. - -* `make schema` - generates graph of seminar and all schemas as PDF. Supercool! - -* `make sync_prod_flatpages` - downloads and applies static/flat pages from mamweb-prod - -./manage.py commands --------------------- - -* `./manage.py migrate` - update the database schema, initialise the database. - You need to run this in the beginning. - -* `./manage.py runserver_plus` - run a debugging server for the web. Slightly - enhanced compared to `./manage.py runserver`. - Open [127.0.0.1:8000](127.0.0.1:8000). - -* `./manage.py testdata` - create pseudo-random seminar data and admin/admin - user. - -* `./manage.py test` - run the tests. - -* `./manage.py shell` - run commands, list elemements of database, check syntax - by importing files, etc. - -Configurations --------------- - -* `mamweb/settings_common.py` contains most configuration options. -* `mamweb/settings.py` is used only for local development. -* `mamweb/settings_test.py` is used for testing on atrey. -* `mamweb/settings_prod.py` is used in production deployment. - -These are automatically switched by `make`. - - +Web M&M +====== + +Tohle je repozitář s kódem M&Mího webu. Pokud zde hledáte web samotný nebo +informace o semináři, najdete je na (a upřímně nechápu, +jak jste se dostali k tomuhle textu :-D) + +Pokud jste tu zůstali, tak vás beztak zajímá vývoj webu (a jestli ne, tak +budeme rádi, když začne :-)). + +Co je M&Mweb uvnitř +------ +Celý náš web je napsaný v [Pythonu](https://www.python.org) ve frameworku +[Django](https://www.djangoproject.com/). Web běží na serveru zvaném Gimli, +jako databázi používá PostgreSQL (pro lokální vývoj naopak SQLite) a všechen +náš kód je uložený v [Gitu](https://git-scm.com/) na [téhle +gitee](https://gitea.ks.matfyz.cz/). Pro dokumentaci používáme +[Sphinx](https://www.sphinx-doc.org). + + + +Jak si web pořídit +------ +Prosím přečti si podrobnější návod v (tady by bylo zbytečné +ho duplikovat). + +Jak web vyvíjet +---- + + +Na webu je mnoho věcí k dělání, některé ani nevyžadují kódění (třeba uhánění +orgů, aby si psali medailonky, aktualizace fotek, …), některé se naopak týkají +infrastruktury pod kódem (Gitea, Gimli, …). Je proto těžké mít na to úplně +obecný návod, tak tady je zhruba návod na úpravy kódu a pokud se něco z toho +nedá aplikovat, tak to prostě zkus nějak udělat jinak, po svém. (Omlouvám se +neinformatikům, ale líp to teď nesepíšu :-)) + +1. Nejprve si stáhni repozitář a rozběhni si lokální web u sebe (viz ). +1. Najdi si problém v Kanboardu (klikni na „Issues“ na Gitee) a/nebo se domluv + s webaři, na čem bys tak mohl/a pracovat. +1. Najdi místo, kde se to dá opravit a zkus to tam opravit. Uznávám, že tenhle + bod je otravně obecný, pokud tápeš, zkus se zeptat zkušenějších webařů nebo + podívat do dokumentace. +1. Vyzkoušej, že ti to lokálně funguje tak, jak má. +1. Zvládneš-li a máš-li čas, zkus to i zdokumentovat a/nebo napsat testy (TODO: chybí návod) +1. Po dohodě s webaři to vyzkoušej na testwebu +1. Pošli pull-request a případně zkus reagovat na komentáře +1. Až se změna začlení do hlavní větve (`master`) a nasadí se web na produkci, + můžeš mít radost, že se web bude používat lépe Tobě i ostatním orgům :-) + +### Proč pull-requesty? + + +Účelů pull-requestů je několik. Jednak doufáme, že pomůže webařům se orientovat +v kódu, jednak tím umožňujeme dělat experimenty a dávat si zpětnou vazbu. V +neposlední řadě pomáhají držet aspoň trochu konzistentní kód, což má pomoci +pohodě při programování… (A asi jsem na něco zapomněl :-)) From bac44b41f8a489b0ac2a3d6af449632c9b264539 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 15:39:20 +0100 Subject: [PATCH 32/68] =?UTF-8?q?Dokumentace=20lok=C3=A1ln=C3=ADho=20v?= =?UTF-8?q?=C3=BDvoje?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Obsahuje tipy z Readme, obsahuje velkou část make/README.md. Zatím nevím, co provedu s make/README.md, ale na něco třeba přijdu :-) --- docs/vyvoj.rst | 197 ++++++++++++++++++++++++++++++++++++++++++++----- make/README.md | 32 -------- 2 files changed, 179 insertions(+), 50 deletions(-) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index 438e8199..3bfdace8 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -1,20 +1,181 @@ Lokální vývoj mamwebu ===================== -Stačí spustit:: - - ## Nahradte svym gimli username - git clone USER@gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb.git mamweb - cd mamweb - ## Instalace je trochu magická, spusť následující posloupnost příkazů: - make install_venv - . env/bin/activate - make install_web - - ## Vygeneruje nejaka testovaci data (spis chuda) - ./manage.py testdata - ## Nahraje statické stránky, menu a obrázky v pozadí menu - ./manage.py loaddata data/* - ## Spusti testovaci server na http://127.0.0.1:8000/ - ./manage.py runserver - -Když si lokálně spustíte web, běží na http://127.0.0.1:8000/, admin najdete na http://127.0.0.1:8000/admin/ (admin/admin) Až skončíš s vývojem webu, spusť “deactivate”. Tím zmizí ‘(env)’ ze začátku promptu. \ No newline at end of file + +Asi hlavní část vývoje většiny webu probíhá lokálně. Každý tak může pracovat na +vlastních úpravách nezávisle na ostatních. + +Potřebné vybavení +------- + +Tento soupis cílí na nějakého typického vývojáře webu – Linuxáka. Jistě je +spousta dalších možností, které zde nejsou postihnuty – poraď se s webaři, +pokud si nejsi jistý. (Speciálně lze nějak vyvíjet na Windows, leč lze často +narazit na odlišné chování od Linuxu.) + +Motivace cílení na Linux je to, že Gimli je Linuxový stroj, takže je vývojové +prostředí pak podobné produkci a zmenšuje to množství odlišného chování. + +.. TODO: Na dokumentaci odlišného chování (Postgres vs. SQLite, Win vs. Linux, …) + by to asi chtělo výhledově separátní stránku, ale teď píšu tuhle :-) + +Nutné +^^^^ + +- `Git `_ +- `Python `_ + + - Ideálně ve verzi 3.9 (to je to, co je aktuálně (2022) na Gimlim) + - Včetně pip-u (na Ubuntu balíček ``python3-pip``) a knihoven pro kompilaci + Cčkových rozšíření (``python3-dev``) +- Knihovna pro práci s PostgreSQL (``libpq-dev``) +- Webový prohlížeč +- \*NIXový shell (typicky ``bash``) + +.. TODO: Pokud tu něco chybí, tak to dopiš :-) + +Kromě toho je potřeba mít účet na `Gitee `_, kde +bydlí gitový repozitář s kódem. + +Doporučené +^^^^^^^^^^ + +- Python wheel (možná řeší problémy s potřebou ``-dev`` balíčků…) +- Editor / IDE podporující `Editorconfig `_ +- Uživatelská zkušenost s `produkční verzí webu `_ +- Účet v `Kanci `_ + +.. TODO: A nejspíš další věci, na které jsem si teď nevzpomněl. + + +Zprovoznění +------- + +Nejprve je potřeba stáhnout si repozitář. To se provede příkazem ``git clone +https://gitea.ks.matfyz.cz/mam/mamweb.git``, případně ``git clone +git@gitea.ks.matfyz.cz:mam/mamweb.git``, pokud už máš nahraný SSH klíč na +Giteu. (Obě adresy se dají zkopírovat ze `stránky repozitáře +`_.) To vyrobí složku ``mamweb``, přepni +se do ní (``cd mamweb``) + +O zprovoznění webu se stará skript ``make/install_web``, stačí ho spustit. Ten +vytvoří virtualenv (neexistuje-li) a nainstaluje do něj závislosti webu (podle +souboru ``requirements.txt``). + +.. FIXME: Novowebaři zmínka o requirements.txt tady moc nepomůže, to má být na + stránce o celkové stavbě repozitáře a stacku… + +Následně je potřeba nahrát další data do databáze, což uděláš pomocí příkazů +``./manage.py testdata`` a ``./manage.py loaddata data/*``. Skript +``make/install_web`` to kdyžtak na konci připomene. + +.. caution:: Zatímco skripty v ``make/`` to nepotřebují, pro použití skriptu + ``./manage.py`` (a dalších) se potřebuješ přepnout do virtuálního prostředí. + To uděláš velmi pravděpodobně spuštěním ``source env/bin/activate``, před + začátkem *promptu* by se mělo objevit ``(env)``. Pro opuštění spusť + ``deactivate``. + +Samotný web se spustí třeba pomocí ``make/run``, nebo ekvivalentně +``./manage.py runserver`` a pak je vidět na ``_. + +Časté problémy +^^^^^^ + +- ``make/install_web`` vypíše ``Error: pg_config executable not found.``: + Chybí ``libpq-dev`` +- Chybová hláška obsahuje ``#include ``: chybí ``python3-dev`` +- Na webu není vidět meníčko: spusť ``./manage.py loaddata data/*`` + +S dalšími problémy se zkus obrátit na další webaře, třeba někdo bude vědět :-) + +Příkazy pro ovládání webu +------- + +Příkazy se dělí do několika skupin. Některé souvisí přímo s webem, Djangem, +databází a podobně, ty typicky používají ``./manage.py``. Skripty pro +obhospodařování repozitáře a webu „zvenku“ typicky bydlí ve složce ``make/``. +Ostatní skripty jsou na náhodných místech :-) + +Tady jsou rozebrány jen příkazy relevantní pro lokální web a univerzálně +užitečné, všechny by chtěly být sepsané jinde (ale zatím nejsou :-/) + +Make skripty +^^^^^^^ + +- ``make/install_web`` nainstaluje závislosti webu +- ``make/run`` spustí web (ekvivalentní s ``./manage.py runserver``) +- ``make/schema`` nakreslí schéma vazeb modelů (může se hodit pro referenci a představu) +- ``make/test`` spustí testy (ale moc jich zatím není; ekvivalentní s ``./manage.py test``) +- ``make/sync_prod_flatpages`` stáhne statické stránky z produkčního webu a + uloží je do souboru v gitu, což umožňuje jejich verzování +- ``make/push_compiled_vue_to_test`` nahraje lokálně zkompilované části + frontendu ve Vue na testweb (Gimli má typicky moc starou verzi nodejs, takže + nejde kompilovat tam.) + +Manage.py skripty +^^^^^ + +.. note:: Je potřeba je spouštět ve virtuálním prostředí, viz výše. + +Všechny skripty kdyžtak mají ``--help``, dá se tak zjistit, co všechno umějí. + +- ``./manage.py testdata`` vygeneruje spíše chudá testovací data, aby bylo na + čem testovat web. +- ``./manage.py loaddata `` nahraje data ze souborů do databáze +- ``./manage.py dumpdata `` naopak z databáze vyrobí textovou reprezentaci +- ``./manage.py shell`` spustí interaktivní pythoní shell, ze kterého lze + interagovat s webem / Djangem. +- ``./manage.py dbshell`` spustí databázový shell (typicky používá SQL) + +- ``./manage.py makemigrations`` vyrobí popis migrací, ``./manage.py migrate`` + je spustí, ``showmigrations`` ukáže, které migrace jsou aplikované a které + ne. +- ``./manage.py runserver_plus`` spouští o něco lepší vývojový server (ale + nikdy jsem asi ty lepší featury nepoužil) + +Může se hodit vědět, že spuštění ``./manage.py`` bez parametrů vypíše seznam +všech příkazů, které lze spustit. + +Dokumentace djangových příkazů je v `dokumentaci Djanga +`_ + +Ostatní užitečné příkazy +^^^^^ + +- ``git status`` je univerzální nápověda na aktuální stav repozitáře a co s tím + lze dělat. +- ``git clean -fxd`` smaže všechny soubory, které nejsou uložené v gitu (včetně + ignorovaných). **Nebezpečný příkaz**, zamysli se, než ho spustíš + +Specifika lokálního webu +------- + +Lokální uživatelé +^^^^^^^ + +Přihlašovací údaje jsou psány jako ``login:heslo`` + +- Superuživatel: ``admin:admin`` +- Orgovské účty: ``o:o``, ``o1:o1`` až ``o3:o3`` +- Řešitelské účty: ``r:r``, ``r1:r1`` až ``r3:r3`` + +Všechny tyto účty jsou (?) svázané s nějakými fiktivními osobami, není ale zřejmé se +kterými, budeš to muset vyzkoušet a pak tady zdokumentovat :-) + +E-maily +^^^^^ + +Posílání e-mailů se lokálně dá zkoušet, e-mail se vypíše do terminálu, kde je +web spuštěn (e.g. pomocí ``make/run``). + +Pruhy +^^^^ + +To, že má lokální web po stranách zelené pruhy je normální a správně, slouží to +k vizuálnímu odlišení lokálního webu. + +.. TODO: Mít někde popis všech tří instancí a tady na něj pak odkázat. +.. - Tahák k používání gitových větví: do workflow, ne sem… +.. - Užitečné odkazy – kam se kouknout + (dohledávání views podle URL, settings_*, ) +.. - Zpříjemnění práce (ssh-klíče, tea, --help, …) + diff --git a/make/README.md b/make/README.md index 1d1baa47..f7e873f1 100644 --- a/make/README.md +++ b/make/README.md @@ -1,34 +1,2 @@ Milý člověče, M&Mí web tě vítá. Prosím, neděs se, zkusím tě provést lokálním zprovozněním webu. -Předně: většina příkazů bude asi vypisovat spoustu detailů, takže ti doporučuji -si tento text otevřít někde separátně. Nachází se v repozitáři v -`make/README.md`, případně si jej můžeš zobrazit hezčeji vykreslený na -[Gitee](https://gitea.ks.matfyz.cz/mam/mamweb/src/branch/master/make/README.md). - -O zprovoznění webu se stará hlavně skript `make/install_web`. Ten vytvoří -virtualenv (neexistuje-li) a nainstaluje do něj závislosti webu. Pak ovšem -budeš potřebovat nahrát další data do databáze, což uděláš pomocí příkazů -`./manage.py testdata` a `./manage.py loaddata data/*`. Skript -`make/install_web` ti to kdyžtak připomene. - -Samotný web spustíš třeba pomocí `make/run`, nebo ekvivalentně `./manage.py runserver`. - -Pozor: zatímco skripty v `make/` to nepotřebují, pro použití skriptu -`./manage.py` se potřebuješ přepnout do virtuálního prostředí. To uděláš velmi -pravděpodobně spuštěním `source env/bin/activate`, před začátkem _promptu_ by -se mělo objevit `(env)`. Pro opuštění spusť `deactivate`. - -Časté problémy ------ -Je možné, že nemáš všechny potřebné závislosti v systému. Proto je možné, že -`make/install_web` vyhodí nějakou chybovou hlášku: - -- `Error: pg_config executable not found.`: nainstaluj si `libpq-dev` (na Ubuntu/Debianu, jinde se příslušný balíček může jmenovat jinak) -- Chybová hláška obsahuje `#include `: nainstaluj si `python3-dev` - - - From 2ffd3bf445eec5b86e300b4c1329bdae1106955e Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 20 Nov 2022 15:52:23 +0100 Subject: [PATCH 33/68] =?UTF-8?q?Aspo=C5=88=20trochu=20relevantn=C3=AD=20m?= =?UTF-8?q?ake/README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A není to zas tak moc README, spíš intro :-/ --- make/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/make/README.md b/make/README.md index f7e873f1..0597a96b 100644 --- a/make/README.md +++ b/make/README.md @@ -1,2 +1,9 @@ -Milý člověče, M&Mí web tě vítá. Prosím, neděs se, zkusím tě provést lokálním zprovozněním webu. +TL;DR: Web vyrobíš pomocí následující posloupnosti příkazů: + make/install_web + . env/bin/activate + ./manage.py testdata + ./manage.py loaddata data/* + make/run +a web potom najdeš na +Pro detaily a nápovědu si prosím přečti dokumentaci v docs/vyvoj.rst. From 25fcddfba8e0296d7eb43cf7d8b722841c0d0709 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 20:18:22 +0100 Subject: [PATCH 34/68] =?UTF-8?q?P=C5=99i=20deployi=20vyrob=20dokumentaci?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/deploy | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/make/deploy b/make/deploy index 24ade165..635364b6 100755 --- a/make/deploy +++ b/make/deploy @@ -14,3 +14,10 @@ safe_checkout_branch "$BRANCH" # Teď máme správnou větev, jdeme vše nainstalovat install_everything systemctl --user restart mamweb-test.service + +# Build dokumentace +ensure_venv +( + cd docs + make html +) From e612899dc2bfa9f7484a69b63797c55f4cb46740 Mon Sep 17 00:00:00 2001 From: MaM Web user Date: Mon, 21 Nov 2022 20:05:06 +0100 Subject: [PATCH 35/68] Requirements: myst_parser pro dokumentaci --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 9ad24a7f..d4713d76 100644 --- a/requirements.txt +++ b/requirements.txt @@ -62,3 +62,4 @@ lorem sphinx sphinx_rtd_theme +myst_parser From dfc12671197dcb85a8df83db3ce6df26963fc751 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 20:40:43 +0100 Subject: [PATCH 36/68] =?UTF-8?q?deploy:=20pr=C3=A1va=20k=20dokumentaci?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/deploy | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/make/deploy b/make/deploy index 635364b6..779bbd5c 100755 --- a/make/deploy +++ b/make/deploy @@ -21,3 +21,7 @@ ensure_venv cd docs make html ) +# Oprava práv k dokumentaci +setfacl -m u:www-data:x . docs docs/_build +setfacl -R -m u:www-data:rX docs/_build/html +setfacl -R -m default:u:www-data:rX docs/_build/html From 5c97735948bd727bae692415b7fef8ad53238be7 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 20:54:36 +0100 Subject: [PATCH 37/68] testweb heslo --- make/deploy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/make/deploy b/make/deploy index 779bbd5c..eaccc25b 100755 --- a/make/deploy +++ b/make/deploy @@ -15,6 +15,9 @@ safe_checkout_branch "$BRANCH" install_everything systemctl --user restart mamweb-test.service +# Přihlášení +htpasswd -bc .htpasswd test lisakjelisak + # Build dokumentace ensure_venv ( From df9e473686300f0feee5ffa26cb5fda3005651ae Mon Sep 17 00:00:00 2001 From: MaM Web user Date: Mon, 21 Nov 2022 20:59:14 +0100 Subject: [PATCH 38/68] fixup! testweb heslo --- make/deploy | 1 + 1 file changed, 1 insertion(+) diff --git a/make/deploy b/make/deploy index eaccc25b..b615f73f 100755 --- a/make/deploy +++ b/make/deploy @@ -17,6 +17,7 @@ systemctl --user restart mamweb-test.service # Přihlášení htpasswd -bc .htpasswd test lisakjelisak +setfacl -m u:www-data:r .htpasswd # Build dokumentace ensure_venv From 5985c4940f23f0000c33e17b232ba8978342c07e Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 21:03:42 +0100 Subject: [PATCH 39/68] fix --- make/sync_test_media | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/sync_test_media b/make/sync_test_media index d7991b65..44b0e830 100755 --- a/make/sync_test_media +++ b/make/sync_test_media @@ -4,6 +4,6 @@ set -exuo pipefail . make/lib.sh gimli_only -only_in_dir "$TESTWEB" +only_in_directory "$TESTWEB" rsync -av --delete "$PRODWEB/media/" ./media From 66ce7d209da592422ec9f65decfaec2e59311e79 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 21:11:50 +0100 Subject: [PATCH 40/68] =?UTF-8?q?M=C3=A9n=C4=9B=20hlu=C4=8Dn=C3=A9=20testy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/test | 1 + 1 file changed, 1 insertion(+) diff --git a/make/test b/make/test index bdf9f12b..ff5175c9 100755 --- a/make/test +++ b/make/test @@ -5,4 +5,5 @@ set -exuo pipefail ensure_venv +trap - ERR # Testy nejspíš selžou, ale nechceme kolem toho dělat další chybovou hlášku. ./manage.py test -v2 From 6b306f0849bc628bb2ec39f16c31eabdd0b15e12 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 21:57:41 +0100 Subject: [PATCH 41/68] ensure_venv v2 --- make/lib.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/make/lib.sh b/make/lib.sh index 135f859e..195b6647 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -26,6 +26,11 @@ test -e '.git' || die "Make skript spuštěn ve špatné složce, spusť ho z ko function ensure_venv { test -f "$VENV_PATH/bin/activate" || $VENV "$VENV_PATH" . "$VENV_PATH/bin/activate" + # To ale není všechno Horste – ten venv nemusí fungovat, chceme to ověřit a případně spadnout. + local SPRAVNA_CESTA="$(readlink -f "$env/bin/python")" + local SKUTECNA_CESTA="$(readlink -f "$(which python)")" + test "$SPRAVNA_CESTA" != "$SKUTECNA_CESTA" || die "Venv asi nefunguje. Prosím smaž si ho a zkus to znovu." + python -c 'print()' > /dev/null || die "Python ve venvu je rozbitý. Prosím smaž venv a zkus to znovu." } function gimli_only { From d468108188c40be69e71e84d0eeeabf894ce5517 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 21:59:38 +0100 Subject: [PATCH 42/68] ensure_web_installed --- make/lib.sh | 7 +++++++ make/run | 2 +- make/schema | 2 +- make/sync_prod_flatpages | 2 +- make/test | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/make/lib.sh b/make/lib.sh index 195b6647..a02b94e2 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -33,6 +33,13 @@ function ensure_venv { python -c 'print()' > /dev/null || die "Python ve venvu je rozbitý. Prosím smaž venv a zkus to znovu." } +function ensure_web_installed { + ensure_venv + python -c 'import django; print(django.__version__)' > /dev/null && return + echo >&2 "POZOR: Web nevypadá nainstalovaně, instaluji." + make/install_web +} + function gimli_only { # Rovnou zkontrolujeme i uživatele if test "$HOSTNAME" != gimli -o "$USER" != mam-web diff --git a/make/run b/make/run index c601593a..c3caf58d 100755 --- a/make/run +++ b/make/run @@ -3,6 +3,6 @@ set -exuo pipefail . make/lib.sh -ensure_venv +ensure_web_installed ./manage.py runserver "$@" diff --git a/make/schema b/make/schema index 9688e49a..05e84b61 100755 --- a/make/schema +++ b/make/schema @@ -3,7 +3,7 @@ set -exuo pipefail . make/lib.sh -ensure_venv +ensure_web_installed ./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf ./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf diff --git a/make/sync_prod_flatpages b/make/sync_prod_flatpages index 4d9d8e1f..ca32c95b 100755 --- a/make/sync_prod_flatpages +++ b/make/sync_prod_flatpages @@ -3,7 +3,7 @@ set -exuo pipefail . make/lib.sh -ensure_venv +ensure_web_installed # TODO: This is very ugly, will fix in a future PR (hopefully) ssh "$GIMLI_LOGIN" " diff --git a/make/test b/make/test index ff5175c9..155d03fa 100755 --- a/make/test +++ b/make/test @@ -3,7 +3,7 @@ set -exuo pipefail . make/lib.sh -ensure_venv +ensure_web_installed trap - ERR # Testy nejspíš selžou, ale nechceme kolem toho dělat další chybovou hlášku. ./manage.py test -v2 From dfede45535ce07ff36f99945a18abc57762315a1 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 22:17:52 +0100 Subject: [PATCH 43/68] init_local --- make/init_local | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 make/init_local diff --git a/make/init_local b/make/init_local new file mode 100755 index 00000000..75ee1ccf --- /dev/null +++ b/make/init_local @@ -0,0 +1,10 @@ +#!/bin/bash + +set -exuo pipefail +. make/lib.sh + +make/install_web +ensure_venv +./manage.py testdata +./manage.py loaddata data/* +make/sync_prod_flatpages From 5e26ac5e692047b17effb549b2cf4a585262cbce Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 22:21:34 +0100 Subject: [PATCH 44/68] =?UTF-8?q?fix=20pr=C3=A1v=20v=20deploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/lib.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make/lib.sh b/make/lib.sh index a02b94e2..65f19e47 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -96,6 +96,8 @@ function install_everything { make/install ./manage.py migrate ./manage.py collectstatic --noinput + setfacl -R -m default:u:www-data:rX media static + setfacl -R -m u:www-data:rX media static chown -R :mam . || true chmod -R g+rX,go-w . || true } From 9c92ca6575f6afeacc7138f257f24c30dc5d9b9b Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 22:51:02 +0100 Subject: [PATCH 45/68] make/README.md z make_docs --- make/README.md | 43 +++++++++---------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/make/README.md b/make/README.md index 1d1baa47..0597a96b 100644 --- a/make/README.md +++ b/make/README.md @@ -1,34 +1,9 @@ -Milý člověče, M&Mí web tě vítá. Prosím, neděs se, zkusím tě provést lokálním zprovozněním webu. - -Předně: většina příkazů bude asi vypisovat spoustu detailů, takže ti doporučuji -si tento text otevřít někde separátně. Nachází se v repozitáři v -`make/README.md`, případně si jej můžeš zobrazit hezčeji vykreslený na -[Gitee](https://gitea.ks.matfyz.cz/mam/mamweb/src/branch/master/make/README.md). - -O zprovoznění webu se stará hlavně skript `make/install_web`. Ten vytvoří -virtualenv (neexistuje-li) a nainstaluje do něj závislosti webu. Pak ovšem -budeš potřebovat nahrát další data do databáze, což uděláš pomocí příkazů -`./manage.py testdata` a `./manage.py loaddata data/*`. Skript -`make/install_web` ti to kdyžtak připomene. - -Samotný web spustíš třeba pomocí `make/run`, nebo ekvivalentně `./manage.py runserver`. - -Pozor: zatímco skripty v `make/` to nepotřebují, pro použití skriptu -`./manage.py` se potřebuješ přepnout do virtuálního prostředí. To uděláš velmi -pravděpodobně spuštěním `source env/bin/activate`, před začátkem _promptu_ by -se mělo objevit `(env)`. Pro opuštění spusť `deactivate`. - -Časté problémy ------ -Je možné, že nemáš všechny potřebné závislosti v systému. Proto je možné, že -`make/install_web` vyhodí nějakou chybovou hlášku: - -- `Error: pg_config executable not found.`: nainstaluj si `libpq-dev` (na Ubuntu/Debianu, jinde se příslušný balíček může jmenovat jinak) -- Chybová hláška obsahuje `#include `: nainstaluj si `python3-dev` - - - +TL;DR: Web vyrobíš pomocí následující posloupnosti příkazů: + make/install_web + . env/bin/activate + ./manage.py testdata + ./manage.py loaddata data/* + make/run +a web potom najdeš na + +Pro detaily a nápovědu si prosím přečti dokumentaci v docs/vyvoj.rst. From d186575712d0519c7f399df6ddb642a954591e32 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 22:51:39 +0100 Subject: [PATCH 46/68] =?UTF-8?q?make/README.md:=20V=C3=ADc=20fancy,=20pou?= =?UTF-8?q?=C5=BE=C3=ADt=20make/init=5Flocal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- make/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/make/README.md b/make/README.md index 0597a96b..16b77901 100644 --- a/make/README.md +++ b/make/README.md @@ -1,9 +1,8 @@ +Milý člověče, M&Mí web tě vítá. Prosím, neděs se, zkusím tě provést lokálním zprovozněním webu. +Pro detaily a nápovědu si prosím přečti dokumentaci v docs/vyvoj.rst. + TL;DR: Web vyrobíš pomocí následující posloupnosti příkazů: - make/install_web - . env/bin/activate - ./manage.py testdata - ./manage.py loaddata data/* + make/init_local make/run a web potom najdeš na -Pro detaily a nápovědu si prosím přečti dokumentaci v docs/vyvoj.rst. From 41c2ed0dee42df8ceab7b34fe09ddef1d6064b5c Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 23:48:12 +0100 Subject: [PATCH 47/68] =?UTF-8?q?Dokumentace=20make=20skript=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/skripty.rst | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 docs/skripty.rst diff --git a/docs/skripty.rst b/docs/skripty.rst new file mode 100644 index 00000000..ca45394b --- /dev/null +++ b/docs/skripty.rst @@ -0,0 +1,108 @@ +Skripty pro práci s repozitářem +=================== + +Máme dvě hlavní sady skriptů/příkazů na ovládání webu a repozitáře. Skripty pro +práci s webem psané v Pythonu jsou uložené ve složkách +``/management/commands/``, případně vestavěné, a volají se pomocí +``./manage.py ``. Oproti tomu skripty pro práci s repozitářem a pro +úpravy databáze a souborů „zvenčí“ se nejčastěji nacházejí ve složce ``make/`` +a volají se pomocí cesty: ``make/``. + +Občas existují i nějaké další skripty na různých jiných místech. Všechny by +měly být ideálně popsány asi tady. + +Make skripty +---- + +Skripty v ``make/`` se označují jako „Make skripty“. Slouží často k velkým +úkonům s repozitářem, jako je nasazení celého webu, zprovoznění lokálního webu +a podobně. + +.. hint:: Označení pro tyto skripty je dáno tím, že byly původně volány pomocí + make (tj. z Makefile). Ve skutečnosti je lze stále volat i jako ``make + ``, ale pak není možné předávat parametry a obecně je tato cesta + zastaralá a existuje jen pro zpětnou kompatibilitu se svalovou pamětí. + +Tyto skripty jsou samonosné, dají se spustit rovnou a v případě problémů si +budou hlasitě stěžovat. Pro účely debugování různých věcí jsou ale (bohužel?) +hlasité i při normálním spuštění, konkrétně vypisují všechny příkazy, které se +spouštějí (\ ``set -x``). Tyto příkazy jsou vidět za jedním či více plusky (\ ``+``). + +.. tip:: Pokud některý make skript selže, tak by na konci měl vypsat, že se něco nepovedlo. + + +Knihovna ``make/lib.sh`` +^^^^^^ + +Pro pohodlí při psaní velká část z nich využívá knihovnu uloženou +v ``make/lib.sh``. Jsou zde definované užitečné proměnné, kontroly a společný +kód. Kromě toho při inicializaci otestuje, že je skript spuštěn z kořene +repozitáře (takže to pak není potřeba zkoumat v ostatních skriptech). + +Proměnné +""""" + +Popsány jsou jen užitečné proměnné, ve skutečnosti jich je definovaných víc, +ale jsou triviální a samopopisné. + +``VENV_PATH`` : + Cesta virtuálního prostředí. Též lze přepsat. +``REPO`` : + Cesta ke gitovému repozitáři na serveru, rovnou použitelná v ``git clone`` +``GIMLI_LOGIN`` : + Přihlašovací údaje ke Gimlimu +``PRODWEB`` a ``TESTWEB`` : + Cesty ke složkám s produkčním a testovacím webem + +Funkce a další zkratky +"""""" + +``ensure_venv`` : + Zajistí, že se zbytek skriptu spustí ve virtuálním prostředí, a pokud neexistuje, tak jej založí. +``ensure_web_installed`` : + Vyzkouší, že je web (django) aspoň elementárně zprovozněno a pokud ne, tak vyzve uživatele, aby to spravil. +``gimli_only`` : + Otestuje, že je příkaz spuštěn na Gimlim, pokud tomu tak není, zeptá se, jestli si uživatel skutečně přeje zbytek skriptu vykonat +``only_in_directory `` : + Otestuje, že skript běží z konkrétní složky. Zejména použitelné s ``gimli_only`` a ``$TESTWEB`` +``safe_checkout_branch `` : + Bezpečně přepne repozitář na jinou větev. Pokud by mělo dojít k přepsání + knihovny nebo volajícího make skriptu, vyzve uživatele, aby přepnul ručně. +``install_everything`` : + Společná část kódu pro nasazování produkce a testwebu. + +Skripty pro lokální vývoj +^^^^^^^ + +``make/install_web`` (nebo ekvivalentně ``make/install``) : + Vytvoří virtualenv a nainstaluje do něj závislosti webu podle ``requirements.txt``. Následně popíše, jak vyrobit zbytek lokálního webu. +``make/run`` : + Spustí lokální web (ekvivalentní s ``./manage.py runserver``) +``make/schema`` : + Vykreslí závislosti a atributy modelů +``make/sync_prod_flatpages`` : + Stáhne z produkce aktuální statické stránky a uloží je do složky ``data/`` +``make/test`` : + Spustí testy (ekvivalentní s ``./manage.py test -v2``) +``make/init_local`` : + Zkratka za posloupnost ``make/install_web``, ``./manage.py testdata``, ``./manage.py loaddata data/*``, ``make/sync_prod_flatpages`` + +Práce s testwebem +^^^^^^^ + +``make/deploy`` : + Nasadí testweb. Volitelně bere jako parametr jméno větve, kterou má nasadit. + Rovnou nastaví přihlašování a vygeneruje příslušnou verzi dokumentace `sem `_. +``make/push_compiled_vue_to_test`` : + **Neotestováno** Nahraje Vue z lokálního počítače na testweb. (Gimli často má moc starou verzi Node.js, takže nejde zkompilovat tam) +``make/sync_test_db_aggressive`` : + Zkopíruje databázi z produkčního webu. +``make/sync_test_media`` : + Zkopíruje média (obrázky, nahrané soubory) z produkčního webu. +``make/sync_test`` : + Zkratka za ``make/sync_test_db_aggressive`` + ``make/sync_test_media``. + +Nasazení produkce +^^^^ + +``make/deploy_prod``. Před samotným nasazením zálohuje databázi a zkontroluje, že se nasazuje větev ``master``. From fef51e2a755dd3fa4c9f013841c2382e4d0856ee Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 23:52:58 +0100 Subject: [PATCH 48/68] =?UTF-8?q?fixup!=20Dokumentace=20make=20skript?= =?UTF-8?q?=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/skripty.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/skripty.rst b/docs/skripty.rst index ca45394b..aa2d8016 100644 --- a/docs/skripty.rst +++ b/docs/skripty.rst @@ -18,7 +18,7 @@ Skripty v ``make/`` se označují jako „Make skripty“. Slouží často k vel úkonům s repozitářem, jako je nasazení celého webu, zprovoznění lokálního webu a podobně. -.. hint:: Označení pro tyto skripty je dáno tím, že byly původně volány pomocí +.. note:: Označení pro tyto skripty je dáno tím, že byly původně volány pomocí make (tj. z Makefile). Ve skutečnosti je lze stále volat i jako ``make ``, ale pak není možné předávat parametry a obecně je tato cesta zastaralá a existuje jen pro zpětnou kompatibilitu se svalovou pamětí. From 1b34c2dbc443cc9202cbd583a5bb7a09e7dff4b2 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 21 Nov 2022 23:59:19 +0100 Subject: [PATCH 49/68] =?UTF-8?q?P=C5=99id=C3=A1n=C3=AD=20do=20sidebaru?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index 10d6016f..92d27c50 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,6 +13,7 @@ Vítejte v dokumentaci M&Mího webu! vyvoj sphinx dalsi_soubory + skripty modules/modules zapisy/zapisy From 61bb9786b30d1e26e3558efbd584e00c3bdc3ad4 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 22 Nov 2022 00:00:22 +0100 Subject: [PATCH 50/68] =?UTF-8?q?Zru=C5=A1en=C3=AD=20dvojte=C4=8Dek?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/skripty.rst | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/skripty.rst b/docs/skripty.rst index aa2d8016..8f9e1064 100644 --- a/docs/skripty.rst +++ b/docs/skripty.rst @@ -45,61 +45,61 @@ Proměnné Popsány jsou jen užitečné proměnné, ve skutečnosti jich je definovaných víc, ale jsou triviální a samopopisné. -``VENV_PATH`` : +``VENV_PATH`` Cesta virtuálního prostředí. Též lze přepsat. -``REPO`` : +``REPO`` Cesta ke gitovému repozitáři na serveru, rovnou použitelná v ``git clone`` -``GIMLI_LOGIN`` : +``GIMLI_LOGIN`` Přihlašovací údaje ke Gimlimu -``PRODWEB`` a ``TESTWEB`` : +``PRODWEB`` a ``TESTWEB`` Cesty ke složkám s produkčním a testovacím webem Funkce a další zkratky """""" -``ensure_venv`` : +``ensure_venv`` Zajistí, že se zbytek skriptu spustí ve virtuálním prostředí, a pokud neexistuje, tak jej založí. -``ensure_web_installed`` : +``ensure_web_installed`` Vyzkouší, že je web (django) aspoň elementárně zprovozněno a pokud ne, tak vyzve uživatele, aby to spravil. -``gimli_only`` : +``gimli_only`` Otestuje, že je příkaz spuštěn na Gimlim, pokud tomu tak není, zeptá se, jestli si uživatel skutečně přeje zbytek skriptu vykonat -``only_in_directory `` : +``only_in_directory `` Otestuje, že skript běží z konkrétní složky. Zejména použitelné s ``gimli_only`` a ``$TESTWEB`` -``safe_checkout_branch `` : +``safe_checkout_branch `` Bezpečně přepne repozitář na jinou větev. Pokud by mělo dojít k přepsání knihovny nebo volajícího make skriptu, vyzve uživatele, aby přepnul ručně. -``install_everything`` : +``install_everything`` Společná část kódu pro nasazování produkce a testwebu. Skripty pro lokální vývoj ^^^^^^^ -``make/install_web`` (nebo ekvivalentně ``make/install``) : +``make/install_web`` (nebo ekvivalentně ``make/install``) Vytvoří virtualenv a nainstaluje do něj závislosti webu podle ``requirements.txt``. Následně popíše, jak vyrobit zbytek lokálního webu. -``make/run`` : +``make/run`` Spustí lokální web (ekvivalentní s ``./manage.py runserver``) -``make/schema`` : +``make/schema`` Vykreslí závislosti a atributy modelů -``make/sync_prod_flatpages`` : +``make/sync_prod_flatpages`` Stáhne z produkce aktuální statické stránky a uloží je do složky ``data/`` -``make/test`` : +``make/test`` Spustí testy (ekvivalentní s ``./manage.py test -v2``) -``make/init_local`` : +``make/init_local`` Zkratka za posloupnost ``make/install_web``, ``./manage.py testdata``, ``./manage.py loaddata data/*``, ``make/sync_prod_flatpages`` Práce s testwebem ^^^^^^^ -``make/deploy`` : +``make/deploy`` Nasadí testweb. Volitelně bere jako parametr jméno větve, kterou má nasadit. Rovnou nastaví přihlašování a vygeneruje příslušnou verzi dokumentace `sem `_. -``make/push_compiled_vue_to_test`` : +``make/push_compiled_vue_to_test`` **Neotestováno** Nahraje Vue z lokálního počítače na testweb. (Gimli často má moc starou verzi Node.js, takže nejde zkompilovat tam) -``make/sync_test_db_aggressive`` : +``make/sync_test_db_aggressive`` Zkopíruje databázi z produkčního webu. -``make/sync_test_media`` : +``make/sync_test_media`` Zkopíruje média (obrázky, nahrané soubory) z produkčního webu. -``make/sync_test`` : +``make/sync_test`` Zkratka za ``make/sync_test_db_aggressive`` + ``make/sync_test_media``. Nasazení produkce From fc6f29bbf15abd4a4da7037d39e7d889dcbc26f8 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 22 Nov 2022 00:05:56 +0100 Subject: [PATCH 51/68] Fix hesel --- docs/vyvoj.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index 3bfdace8..c2eb3d1f 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -155,8 +155,8 @@ Lokální uživatelé Přihlašovací údaje jsou psány jako ``login:heslo`` - Superuživatel: ``admin:admin`` -- Orgovské účty: ``o:o``, ``o1:o1`` až ``o3:o3`` -- Řešitelské účty: ``r:r``, ``r1:r1`` až ``r3:r3`` +- Orgovské účty: ``o:o``, ``o1:o`` až ``o3:o`` +- Řešitelské účty: ``r:r``, ``r1:r`` až ``r3:r`` Všechny tyto účty jsou (?) svázané s nějakými fiktivními osobami, není ale zřejmé se kterými, budeš to muset vyzkoušet a pak tady zdokumentovat :-) From 4549a91e062a9886ed6d952ee1d31a33384d46ed Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 22 Nov 2022 00:11:16 +0100 Subject: [PATCH 52/68] =?UTF-8?q?Dokumentace=20Jid=C3=A1=C5=A1ova=20bugu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Není to častý bug, ale nějaký obsah přece potřebujeme :-) --- docs/vyvoj.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index c2eb3d1f..08d44e38 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -84,6 +84,9 @@ Samotný web se spustí třeba pomocí ``make/run``, nebo ekvivalentně Chybí ``libpq-dev`` - Chybová hláška obsahuje ``#include ``: chybí ``python3-dev`` - Na webu není vidět meníčko: spusť ``./manage.py loaddata data/*`` +- ``locale.Error: unsupported locale setting``: Chybí podpora pro příslušný + jazyk ve tvém systému. Odkomentuj příslušnou lokalizaci v ``/etc/locale.gen`` + a spusť ``locale-gen`` jako root, tím se to spraví. S dalšími problémy se zkus obrátit na další webaře, třeba někdo bude vědět :-) From 4853a47899944039bfe28a9eae2ec97fdf838c2c Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 22 Nov 2022 00:11:41 +0100 Subject: [PATCH 53/68] =?UTF-8?q?vyvoj.rst:=20Odkaz=20na=20dokumentaci=20m?= =?UTF-8?q?ake=20skript=C5=AF=20+=20smaz=C3=A1n=C3=AD=20irelevantn=C3=ADho?= =?UTF-8?q?=20p=C5=99=C3=ADkazu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/vyvoj.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index 08d44e38..625245a1 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -99,7 +99,7 @@ obhospodařování repozitáře a webu „zvenku“ typicky bydlí ve složce `` Ostatní skripty jsou na náhodných místech :-) Tady jsou rozebrány jen příkazy relevantní pro lokální web a univerzálně -užitečné, všechny by chtěly být sepsané jinde (ale zatím nejsou :-/) +užitečné, ostatní najdeš v :ref:`Skripty pro práci s repozitářem` Make skripty ^^^^^^^ @@ -110,9 +110,6 @@ Make skripty - ``make/test`` spustí testy (ale moc jich zatím není; ekvivalentní s ``./manage.py test``) - ``make/sync_prod_flatpages`` stáhne statické stránky z produkčního webu a uloží je do souboru v gitu, což umožňuje jejich verzování -- ``make/push_compiled_vue_to_test`` nahraje lokálně zkompilované části - frontendu ve Vue na testweb (Gimli má typicky moc starou verzi nodejs, takže - nejde kompilovat tam.) Manage.py skripty ^^^^^ From 1bfe8cee5ee88e190719416f080d22fa0b067f08 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 22 Nov 2022 00:22:01 +0100 Subject: [PATCH 54/68] =?UTF-8?q?te=C4=8Dka?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/vyvoj.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index 625245a1..cedd7a67 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -99,7 +99,7 @@ obhospodařování repozitáře a webu „zvenku“ typicky bydlí ve složce `` Ostatní skripty jsou na náhodných místech :-) Tady jsou rozebrány jen příkazy relevantní pro lokální web a univerzálně -užitečné, ostatní najdeš v :ref:`Skripty pro práci s repozitářem` +užitečné, ostatní najdeš v :ref:`Skripty pro práci s repozitářem`. Make skripty ^^^^^^^ From d8554ad70dad95da64f1df984afa800e011397b9 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Nov 2022 02:05:09 +0100 Subject: [PATCH 55/68] =?UTF-8?q?Ubuntu=20m=C3=A1=20i=20venv=20v=20separ?= =?UTF-8?q?=C3=A1tn=C3=ADm=20bal=C3=AD=C4=8Dku?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/vyvoj.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index cedd7a67..583521b1 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -25,7 +25,7 @@ Nutné - `Python `_ - Ideálně ve verzi 3.9 (to je to, co je aktuálně (2022) na Gimlim) - - Včetně pip-u (na Ubuntu balíček ``python3-pip``) a knihoven pro kompilaci + - Včetně pip-u (na Ubuntu balíček ``python3-pip``), venvu (``python3-venv``) a knihoven pro kompilaci Cčkových rozšíření (``python3-dev``) - Knihovna pro práci s PostgreSQL (``libpq-dev``) - Webový prohlížeč From fcd1320b45781e488f54d23a4f26f718d2e276a5 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Nov 2022 02:23:03 +0100 Subject: [PATCH 56/68] Fix cesty --- make/lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib.sh b/make/lib.sh index 65f19e47..fad464a5 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -27,7 +27,7 @@ function ensure_venv { test -f "$VENV_PATH/bin/activate" || $VENV "$VENV_PATH" . "$VENV_PATH/bin/activate" # To ale není všechno Horste – ten venv nemusí fungovat, chceme to ověřit a případně spadnout. - local SPRAVNA_CESTA="$(readlink -f "$env/bin/python")" + local SPRAVNA_CESTA="$(readlink -f "$VENV_PATH/bin/python")" local SKUTECNA_CESTA="$(readlink -f "$(which python)")" test "$SPRAVNA_CESTA" != "$SKUTECNA_CESTA" || die "Venv asi nefunguje. Prosím smaž si ho a zkus to znovu." python -c 'print()' > /dev/null || die "Python ve venvu je rozbitý. Prosím smaž venv a zkus to znovu." From 9fefbd4bbac1d680231ad2fa87279168fa2f469e Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Nov 2022 02:50:46 +0100 Subject: [PATCH 57/68] Fix logiky --- make/lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib.sh b/make/lib.sh index fad464a5..9dc3d6c5 100644 --- a/make/lib.sh +++ b/make/lib.sh @@ -29,7 +29,7 @@ function ensure_venv { # To ale není všechno Horste – ten venv nemusí fungovat, chceme to ověřit a případně spadnout. local SPRAVNA_CESTA="$(readlink -f "$VENV_PATH/bin/python")" local SKUTECNA_CESTA="$(readlink -f "$(which python)")" - test "$SPRAVNA_CESTA" != "$SKUTECNA_CESTA" || die "Venv asi nefunguje. Prosím smaž si ho a zkus to znovu." + test "$SPRAVNA_CESTA" == "$SKUTECNA_CESTA" || die "Venv asi nefunguje. Prosím smaž si ho a zkus to znovu." python -c 'print()' > /dev/null || die "Python ve venvu je rozbitý. Prosím smaž venv a zkus to znovu." } From 430430b4606b42fef9b695af4af092e09b2d9cd7 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Nov 2022 04:56:52 +0100 Subject: [PATCH 58/68] =?UTF-8?q?Tabulka=20prerekvizit=20v=20r=C5=AFzn?= =?UTF-8?q?=C3=BDch=20distribuc=C3=ADch=20/=20syst=C3=A9mech?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tabulka_prerekvizit.rst | 25 +++++++++++++++++++++++++ docs/vyvoj.rst | 3 +++ 2 files changed, 28 insertions(+) create mode 100644 docs/tabulka_prerekvizit.rst diff --git a/docs/tabulka_prerekvizit.rst b/docs/tabulka_prerekvizit.rst new file mode 100644 index 00000000..9dcce4c5 --- /dev/null +++ b/docs/tabulka_prerekvizit.rst @@ -0,0 +1,25 @@ +.. Není odkázaná z menu, je to záměr + +Tabulka prerekvizit v různých distribucích +========= + +.. admonition:: Metodika + + Na čistém repozitáři (``git clean -fxd``) a čistém systému spouštíme + ``make/init_local``. Když to spadne, tak do tabulky zapíšeme, co jsme + přiinstalovali. Protože větev ``makefiles`` aktuálně není mergenutá do + masteru, nefunguje synchronizace flatpages (a stejně nemáme SSH klíč), takže + tam ``make/init_local`` sestřelíme a vyzkoušíme, že ``make/test`` spustí + testy. + +.. Grafické tabulky (grid-tables, simple-tables) jsou strašný porod vyrábět, dlabu na to a cpu to do CSV… + +.. csv-table:: Prerekvizity v jednotlivých distribucích + :header: Distribuce / OS, Repozitář s Py3.9, venv, py knihovny, PostgreSQL knihovna, poznámky + + Ubuntu 22.10, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "Je potřeba zapnout zdroj ``universe`` a nainstalovat kompilátor C (``gcc``)?" + Linux Mint 21, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "" + Archlinux 2022.11.01, AUR, vestavěný, vestavěné, ``postgresql-libs``, "Je potřeba céčkový kompilátor (``gcc``)" + openSUSE Leap 15.4, oficiální (``python39``), předinstalovaný?, ``python39-devel``, ??FIXME!!, "Výchozí verze pythonu je 3.6 a ta je moc stará, potřeba instalovat ``gcc``. Nevím jak sehnat pg_config." + Debian 11, "oficiální, výchozí", ??, ??, ??, "Určitě to tam rozběhat jde, protože Gimli. Nejspíš bude relativně podobné Ubuntu." + diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index 583521b1..256f5eec 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -36,6 +36,9 @@ Nutné Kromě toho je potřeba mít účet na `Gitee `_, kde bydlí gitový repozitář s kódem. +.. tip:: Potřebné balíčky v různých distribucích jsou sepsané v :ref:`tabulce + prerekvizit `. + Doporučené ^^^^^^^^^^ From f86e6b68383697ba8d535691daf5fb47807283a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Mon, 28 Nov 2022 23:38:13 +0100 Subject: [PATCH 59/68] hotfix: #1430 --- mamweb/static/css/mamweb.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mamweb/static/css/mamweb.css b/mamweb/static/css/mamweb.css index 53e06967..236072f5 100644 --- a/mamweb/static/css/mamweb.css +++ b/mamweb/static/css/mamweb.css @@ -1152,8 +1152,7 @@ div.zadani_termin .datum { /* posune kotvu obrázku v galerii o oranžový pruh dolu, aby se pod ním obrázek neschovával */ /* https://stackoverflow.com/questions/10732690/offsetting-an-html-anchor-to-adjust-for-fixed-header */ .kotva_obrazku { - display: block; - position: relative; + position: absolute; width: 0; height: 55px; /* viz #title */ margin-top: -55px; /* viz #title */ From 91cf18fa9e0e04a8f34b43f226344ad64a01c998 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 29 Nov 2022 00:40:18 +0100 Subject: [PATCH 60/68] =?UTF-8?q?Odsazen=C3=AD=20pomoc=C3=AD=20tabul=C3=A1?= =?UTF-8?q?tor=C5=AF=20[NOT=20CHECKED]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pustil jsem na velkou část kódu skript, zatím nevím, co jsem rozbil. Prosím o review :-) --- header_fotky/context_processors.py | 84 +++---- korektury/views.py | 34 +-- mamweb/admin.py | 32 +-- mamweb/middleware.py | 152 ++++++------ mamweb/settings_common.py | 386 ++++++++++++++--------------- mamweb/settings_local.py | 96 +++---- mamweb/settings_prod.py | 20 +- mamweb/settings_test.py | 28 +-- seminar/models/base.py | 18 +- seminar/models/novinky.py | 42 ++-- seminar/models/odevzdavatko.py | 234 ++++++++--------- soustredeni/admin.py | 50 ++-- treenode/admin.py | 90 +++---- treenode/permissions.py | 4 +- various/autentizace/utils.py | 24 +- various/log_filters.py | 8 +- 16 files changed, 651 insertions(+), 651 deletions(-) diff --git a/header_fotky/context_processors.py b/header_fotky/context_processors.py index 0040cb5f..7f73faa7 100644 --- a/header_fotky/context_processors.py +++ b/header_fotky/context_processors.py @@ -12,46 +12,46 @@ from header_fotky.models import FotkaUrlVazba def vzhled(request): - """ - Podle času přidá do contextu, zdali je nebo není noc. Dále podle dení - doby a url přidá do contextu správnou fotku. - - url adresu nejprve vyzkouší celou, pak postupně odřezává věci za - lomítkem, dokud nenajde url, pro kterou existuje alespoň jedna fotka. - Z fotek pro toto url zkusí vybrat tu ve správné denní době a až poté - libovolnou. (Z více možných fotek pro 1 url a 1 dobu vybírá náhodně.) - """ - hodin = datetime.now().hour - if (hodin <= 6) or (hodin >= 20): - noc = True - nedoba = 'den' - doba = 'noc' - else: - noc = False - nedoba = 'noc' - doba = 'den' - url = request.path - - fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba) - fotka = None - - # TODO rychlejší patternmatch? - while (fotka is None) and (url != ''): - presne = fotky.filter(url__exact=url) - if presne.count() > 0: - presne_doba = presne.filter(denni_doba=doba) - if presne_doba.count() > 0: - fotka = random.choice(presne_doba).url_fotky() - else: - fotka = random.choice(presne).url_fotky() - - url = url[:-1] - index = url.rfind('/') - if index != -1: - url = url[:index+1] - - if fotka is None: - fotka = settings.STATIC_URL + "images/header/vikendovka.jpg" - - return {'noc': noc, 'fotka': fotka} + """ + Podle času přidá do contextu, zdali je nebo není noc. Dále podle dení + doby a url přidá do contextu správnou fotku. + + url adresu nejprve vyzkouší celou, pak postupně odřezává věci za + lomítkem, dokud nenajde url, pro kterou existuje alespoň jedna fotka. + Z fotek pro toto url zkusí vybrat tu ve správné denní době a až poté + libovolnou. (Z více možných fotek pro 1 url a 1 dobu vybírá náhodně.) + """ + hodin = datetime.now().hour + if (hodin <= 6) or (hodin >= 20): + noc = True + nedoba = 'den' + doba = 'noc' + else: + noc = False + nedoba = 'noc' + doba = 'den' + url = request.path + + fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba) + fotka = None + + # TODO rychlejší patternmatch? + while (fotka is None) and (url != ''): + presne = fotky.filter(url__exact=url) + if presne.count() > 0: + presne_doba = presne.filter(denni_doba=doba) + if presne_doba.count() > 0: + fotka = random.choice(presne_doba).url_fotky() + else: + fotka = random.choice(presne).url_fotky() + + url = url[:-1] + index = url.rfind('/') + if index != -1: + url = url[:index+1] + + if fotka is None: + fotka = settings.STATIC_URL + "images/header/vikendovka.jpg" + + return {'noc': noc, 'fotka': fotka} diff --git a/korektury/views.py b/korektury/views.py index d8d78c24..efeab19d 100644 --- a/korektury/views.py +++ b/korektury/views.py @@ -30,28 +30,28 @@ class KorekturyListView(generic.ListView): template_name = 'korektury/seznam.html' class KorekturyAktualniListView(KorekturyListView): - def get_queryset(self, *args, **kwargs): - queryset=super().get_queryset() - queryset=queryset.exclude(status="zastarale") - return queryset + def get_queryset(self, *args, **kwargs): + queryset=super().get_queryset() + queryset=queryset.exclude(status="zastarale") + return queryset - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['selected'] = 'aktualni' - return context + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['selected'] = 'aktualni' + return context class KorekturyZastaraleListView(KorekturyListView): - def get_queryset(self, *args, **kwargs): - queryset=super().get_queryset() - queryset=queryset.filter(status="zastarale").order_by("-cas") - return queryset - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['selected'] = 'zastarale' - return context + def get_queryset(self, *args, **kwargs): + queryset=super().get_queryset() + queryset=queryset.filter(status="zastarale").order_by("-cas") + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['selected'] = 'zastarale' + return context class KorekturySeskupeneListView(KorekturyAktualniListView): template_name = 'korektury/seskupeny_seznam.html' diff --git a/mamweb/admin.py b/mamweb/admin.py index 2ad1aaaa..b6924468 100644 --- a/mamweb/admin.py +++ b/mamweb/admin.py @@ -17,14 +17,14 @@ from ckeditor_uploader.widgets import CKEditorUploadingWidget class FlatpageForm(FlatpageFormOld): - content = forms.CharField(widget=CKEditorUploadingWidget()) - class Meta: - model = FlatPage # this is not automatically inherited from FlatpageFormOld - exclude = [] + content = forms.CharField(widget=CKEditorUploadingWidget()) + class Meta: + model = FlatPage # this is not automatically inherited from FlatpageFormOld + exclude = [] class FlatPageAdmin(FlatPageAdminOld): - form = FlatpageForm + form = FlatpageForm # We have to unregister the normal admin, and then reregister ours @@ -36,19 +36,19 @@ locale.setlocale(locale.LC_COLLATE, 'cs_CZ.UTF-8') # https://books.agiliq.com/projects/django-admin-cookbook/en/latest/set_ordering.html # FIXME zpraseno pomocí toho, že Python umí bez problému přepisovat funkce def get_app_list(self, request): - """ - Return a sorted list of all the installed apps that have been - registered in this site. - """ + """ + Return a sorted list of all the installed apps that have been + registered in this site. + """ - app_dict = self._build_app_dict(request) - # Sort the apps alphabetically. - app_list = sorted(app_dict.values(), key=lambda x: locale.strxfrm('!') if (x['name'] == "Seminar") else locale.strxfrm(x['name'].lower())) + app_dict = self._build_app_dict(request) + # Sort the apps alphabetically. + app_list = sorted(app_dict.values(), key=lambda x: locale.strxfrm('!') if (x['name'] == "Seminar") else locale.strxfrm(x['name'].lower())) - # Sort the models alphabetically within each app. - 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())) + # Sort the models alphabetically within each app. + 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())) - return app_list + return app_list AdminSite.get_app_list = get_app_list diff --git a/mamweb/middleware.py b/mamweb/middleware.py index c1014257..7109423e 100644 --- a/mamweb/middleware.py +++ b/mamweb/middleware.py @@ -6,83 +6,83 @@ from django.http import HttpResponse, HttpResponseRedirect class LoggedInHintCookieMiddleware(object): - """Middleware to securely help with 'logged-in' detection for dual HTTP/HTTPS sites. - - On insecure requests: Checks for a (non-secure) cookie settings.LOGGED_IN_HINT_COOKIE_NAME - and if present, redirects to HTTPS (same adress). - Note this usually breaks non-GET (POST) requests. - - On secure requests: Updates cookie settings.LOGGED_IN_HINT_COOKIE_NAME to reflect - whether an user is logged in in the current session (cookie set to 'True' or cleared). - The cookie is set to expire at the same time as the sessionid cookie. - - By default, LOGGED_IN_HINT_COOKIE_NAME = 'logged_in_hint'. - """ - - def __init__(self): - if hasattr(settings, 'LOGGED_IN_HINT_COOKIE_NAME'): - self.cookie_name = settings.LOGGED_IN_HINT_COOKIE_NAME - else: self.cookie_name = 'logged_in_hint' - self.cookie_value = 'True' - - def cookie_correct(self, request): - return self.cookie_name in request.COOKIES and request.COOKIES[self.cookie_name] == self.cookie_value - - def process_request(self, request): - if not request.is_secure(): - if self.cookie_correct(request): - # redirect insecure (assuming http) requests with hint cookie to https - url = request.build_absolute_uri() - assert url[:5] == 'http:' - return HttpResponseRedirect('https:' + url[5:]) - return None - - def process_response(self, request, response): - if request.is_secure(): - # assuming full session info (as the conn. is secure) - try: - user = request.user - except AttributeError: # no user - ajax or other special request - return response - if user.is_authenticated(): - if not self.cookie_correct(request): - expiry = None if request.session.get_expire_at_browser_close() else request.session.get_expiry_date() - response.set_cookie(self.cookie_name, value=self.cookie_value, expires=expiry, secure=False) - else: - if self.cookie_name in request.COOKIES: - response.delete_cookie(self.cookie_name) - return response + """Middleware to securely help with 'logged-in' detection for dual HTTP/HTTPS sites. + + On insecure requests: Checks for a (non-secure) cookie settings.LOGGED_IN_HINT_COOKIE_NAME + and if present, redirects to HTTPS (same adress). + Note this usually breaks non-GET (POST) requests. + + On secure requests: Updates cookie settings.LOGGED_IN_HINT_COOKIE_NAME to reflect + whether an user is logged in in the current session (cookie set to 'True' or cleared). + The cookie is set to expire at the same time as the sessionid cookie. + + By default, LOGGED_IN_HINT_COOKIE_NAME = 'logged_in_hint'. + """ + + def __init__(self): + if hasattr(settings, 'LOGGED_IN_HINT_COOKIE_NAME'): + self.cookie_name = settings.LOGGED_IN_HINT_COOKIE_NAME + else: self.cookie_name = 'logged_in_hint' + self.cookie_value = 'True' + + def cookie_correct(self, request): + return self.cookie_name in request.COOKIES and request.COOKIES[self.cookie_name] == self.cookie_value + + def process_request(self, request): + if not request.is_secure(): + if self.cookie_correct(request): + # redirect insecure (assuming http) requests with hint cookie to https + url = request.build_absolute_uri() + assert url[:5] == 'http:' + return HttpResponseRedirect('https:' + url[5:]) + return None + + def process_response(self, request, response): + if request.is_secure(): + # assuming full session info (as the conn. is secure) + try: + user = request.user + except AttributeError: # no user - ajax or other special request + return response + if user.is_authenticated(): + if not self.cookie_correct(request): + expiry = None if request.session.get_expire_at_browser_close() else request.session.get_expiry_date() + response.set_cookie(self.cookie_name, value=self.cookie_value, expires=expiry, secure=False) + else: + if self.cookie_name in request.COOKIES: + response.delete_cookie(self.cookie_name) + return response class vzhled: - def process_request(self, request): - return None - - def process_view(self, request, view_func, view_args, view_kwargs): - #print "====== process_request ======" - #print view_func - #print view_args - #print view_kwargs - #print "=============================" - return None - - def process_template_response(self, request, response): - hodin = datetime.now().hour - if (hodin <= 6) or (hodin >= 14): # TODO 20 - response.context_data['noc'] = True - else: - response.context_data['noc'] = False - return response - - def process_response(self, request, response): - #hodin = datetime.now().hour - #if (hodin <= 6) or (hodin >= 14): # TODO 20 - #response.context_data['noc'] = True - #else: - #response.context_data['noc'] = False - return response - - - ##def process_exception(request, exception): - #pass + def process_request(self, request): + return None + + def process_view(self, request, view_func, view_args, view_kwargs): + #print "====== process_request ======" + #print view_func + #print view_args + #print view_kwargs + #print "=============================" + return None + + def process_template_response(self, request, response): + hodin = datetime.now().hour + if (hodin <= 6) or (hodin >= 14): # TODO 20 + response.context_data['noc'] = True + else: + response.context_data['noc'] = False + return response + + def process_response(self, request, response): + #hodin = datetime.now().hour + #if (hodin <= 6) or (hodin >= 14): # TODO 20 + #response.context_data['noc'] = True + #else: + #response.context_data['noc'] = False + return response + + + ##def process_exception(request, exception): + #pass diff --git a/mamweb/settings_common.py b/mamweb/settings_common.py index 5a610795..139190fa 100644 --- a/mamweb/settings_common.py +++ b/mamweb/settings_common.py @@ -40,8 +40,8 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', - 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + 'django.contrib.staticfiles.finders.FileSystemFinder', ) # Where redirect for login required services @@ -57,41 +57,41 @@ DOBA_ODHLASENI_PRI_ZASKRTNUTI_NEODHLASOVAT = 365 * 24 * 3600 # rok # Modules configuration AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', + 'django.contrib.auth.backends.ModelBackend', ) MIDDLEWARE = ( # 'reversion.middleware.RevisionMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', # FIXME: rozbilo se při přechodu na Django 2.0, nevím, jestli # se to dá zahodit bez náhrady # 'mamweb.middleware.LoggedInHintCookieMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', ) TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': ( - 'django.contrib.auth.context_processors.auth', + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': ( + 'django.contrib.auth.context_processors.auth', 'django.template.context_processors.request', - 'django.contrib.messages.context_processors.messages', - 'sekizai.context_processors.sekizai', - 'header_fotky.context_processors.vzhled', - 'various.context_processors.rozliseni', - 'various.context_processors.april', - ) - }, - }, + 'django.contrib.messages.context_processors.messages', + 'sekizai.context_processors.sekizai', + 'header_fotky.context_processors.vzhled', + 'various.context_processors.rozliseni', + 'various.context_processors.april', + ) + }, + }, ] @@ -99,59 +99,59 @@ TEMPLATES = [ INSTALLED_APPS = ( - # Basic - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'django.contrib.auth', - - # Utilities - 'sekizai', - 'reversion', - 'django_countries', - 'solo', - 'ckeditor', - 'ckeditor_uploader', - 'taggit', - 'dal', - 'dal_select2', - - 'crispy_forms', - 'django_comments', - - 'django.contrib.flatpages', - 'django.contrib.humanize', - - 'sitetree', - - 'imagekit', - - 'polymorphic', - - 'webpack_loader', - 'rest_framework', - 'rest_framework.authtoken', - - # MaMweb - 'mamweb', - 'seminar', - 'galerie', - 'korektury', - 'prednasky', - 'header_fotky', - 'various', - 'various.autentizace', - 'api', - 'aesop', - 'odevzdavatko', - 'vysledkovky', - 'personalni', - 'soustredeni', - 'treenode', - - # Admin upravy: + # Basic + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.sites', + 'django.contrib.staticfiles', + 'django.contrib.auth', + + # Utilities + 'sekizai', + 'reversion', + 'django_countries', + 'solo', + 'ckeditor', + 'ckeditor_uploader', + 'taggit', + 'dal', + 'dal_select2', + + 'crispy_forms', + 'django_comments', + + 'django.contrib.flatpages', + 'django.contrib.humanize', + + 'sitetree', + + 'imagekit', + + 'polymorphic', + + 'webpack_loader', + 'rest_framework', + 'rest_framework.authtoken', + + # MaMweb + 'mamweb', + 'seminar', + 'galerie', + 'korektury', + 'prednasky', + 'header_fotky', + 'various', + 'various.autentizace', + 'api', + 'aesop', + 'odevzdavatko', + 'vysledkovky', + 'personalni', + 'soustredeni', + 'treenode', + + # Admin upravy: # 'material', # 'material.admin', @@ -159,76 +159,76 @@ INSTALLED_APPS = ( # 'admin_tools.theming', # 'admin_tools.menu', # 'admin_tools.dashboard', - 'django.contrib.admin', + 'django.contrib.admin', - # Nechat na konci (INSTALLED_APPS je uspořádané): - 'django_cleanup.apps.CleanupConfig', # Uklízí media/ + # Nechat na konci (INSTALLED_APPS je uspořádané): + 'django_cleanup.apps.CleanupConfig', # Uklízí media/ ) DEBUG_TOOLBAR_CONFIG = { - 'SHOW_COLLAPSED': True, + 'SHOW_COLLAPSED': True, } SUMMERNOTE_CONFIG = { - 'iframe': False, - 'airMode': False, - 'attachment_require_authentication': True, - 'width': '80%', + 'iframe': False, + 'airMode': False, + 'attachment_require_authentication': True, + 'width': '80%', # 'height': '30em', - 'toolbar': [ - ['style', ['style']], - ['font', ['bold', 'italic', 'superscript', 'subscript', 'clear']], - ['color', ['color']], - ['para', ['ul', 'ol', 'paragraph']], - ['table', ['table']], - ['insert', ['link', 'picture', 'hr']], - ['view', ['fullscreen', 'codeview']], - ['help', ['help']], - ] + 'toolbar': [ + ['style', ['style']], + ['font', ['bold', 'italic', 'superscript', 'subscript', 'clear']], + ['color', ['color']], + ['para', ['ul', 'ol', 'paragraph']], + ['table', ['table']], + ['insert', ['link', 'picture', 'hr']], + ['view', ['fullscreen', 'codeview']], + ['help', ['help']], + ] } CKEDITOR_UPLOAD_PATH = "uploads/" CKEDITOR_IMAGE_BACKEND = 'pillow' #CKEDITOR_JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js' CKEDITOR_CONFIGS = { - 'default': { - 'entities': False, - 'toolbar': [ - ['Source', 'ShowBlocks', '-', 'Maximize'], - ['Bold', 'Italic', 'Subscript', 'Superscript', '-', 'RemoveFormat'], - ['NumberedList','BulletedList','-','Blockquote','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], - ['Link', 'Unlink', 'Anchor', '-', 'Image', 'Table', 'HorizontalRule'], - ['Format'], - - ], + 'default': { + 'entities': False, + 'toolbar': [ + ['Source', 'ShowBlocks', '-', 'Maximize'], + ['Bold', 'Italic', 'Subscript', 'Superscript', '-', 'RemoveFormat'], + ['NumberedList','BulletedList','-','Blockquote','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], + ['Link', 'Unlink', 'Anchor', '-', 'Image', 'Table', 'HorizontalRule'], + ['Format'], + + ], # 'toolbar': 'full', - 'height': '40em', - 'width': '100%', - 'toolbarStartupExpanded': False, - 'allowedContent' : True, - }, + 'height': '40em', + 'width': '100%', + 'toolbarStartupExpanded': False, + 'allowedContent' : True, + }, } # Webpack loader VUE_FRONTEND_DIR = os.path.join(BASE_DIR, 'vue_frontend') WEBPACK_LOADER = { - 'DEFAULT': { - 'CACHE': False, - 'BUNDLE_DIR_NAME': 'vue/', # must end with slash - 'STATS_FILE': os.path.join(VUE_FRONTEND_DIR, 'webpack-stats.json'), - 'POLL_INTERVAL': 0.1, - 'TIMEOUT': None, - 'IGNORE': [r'.+\.hot-update.js', r'.+\.map'] - } + 'DEFAULT': { + 'CACHE': False, + 'BUNDLE_DIR_NAME': 'vue/', # must end with slash + 'STATS_FILE': os.path.join(VUE_FRONTEND_DIR, 'webpack-stats.json'), + 'POLL_INTERVAL': 0.1, + 'TIMEOUT': None, + 'IGNORE': [r'.+\.hot-update.js', r'.+\.map'] + } } # Dajngo REST Framework REST_FRAMEWORK = { - 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', - 'PAGE_SIZE': 100 + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'PAGE_SIZE': 100 } @@ -236,22 +236,22 @@ REST_FRAMEWORK = { # Create file 'django.secret' in every install (it is not kept in git) try: - with open(os.path.join(os.path.dirname(__file__), '..', 'django.secret')) as f: - SECRET_KEY = f.readline().strip() + with open(os.path.join(os.path.dirname(__file__), '..', 'django.secret')) as f: + SECRET_KEY = f.readline().strip() except: - SECRET_KEY = '12345zmr_k53a*@f4q_+ji^o@!pgpef*5&8c7zzdqwkdlkj' + SECRET_KEY = '12345zmr_k53a*@f4q_+ji^o@!pgpef*5&8c7zzdqwkdlkj' # Logging LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, + 'version': 1, + 'disable_existing_loggers': False, - 'formatters': { - 'verbose': { - 'format': '%(levelname)s %(asctime)s %(module)s (logger %(name)s): %(message)s' - }, - }, + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(module)s (logger %(name)s): %(message)s' + }, + }, 'filters': { 'Http404AsInfo': { @@ -262,76 +262,76 @@ LOGGING = { }, }, - 'loggers': { - - 'django': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'filters': ['StripSensitiveFormData'], - }, - 'django.security.csrf': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'filters': ['StripSensitiveFormData'], - }, - 'django.request': { - 'handlers': ['console'], - 'level': 'DEBUG', + 'loggers': { + + 'django': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'filters': ['StripSensitiveFormData'], + }, + 'django.security.csrf': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'filters': ['StripSensitiveFormData'], + }, + 'django.request': { + 'handlers': ['console'], + 'level': 'DEBUG', 'filters': ['Http404AsInfo'], - }, + }, - 'seminar.prihlaska.form':{ + 'seminar.prihlaska.form':{ 'handlers': ['console','registration_logfile'], 'level': 'INFO' }, - 'seminar.prihlaska.problem':{ + 'seminar.prihlaska.problem':{ 'handlers': ['console','mail_registration','registration_error_log'], 'level': 'INFO' }, - # Catch-all logger - '': { - 'handlers': ['console'], # Add 'mail_admins' in prod and test - 'level': 'DEBUG', - 'filters': ['StripSensitiveFormData'], - }, - - }, - - 'handlers': { - - 'console': { - 'level': 'WARNING', ## Set to 'DEBUG' in local - 'class': 'logging.StreamHandler', - 'formatter': 'verbose', - }, - - 'mail_admins': { - 'level': 'WARNING', - 'class': 'django.utils.log.AdminEmailHandler', - 'formatter': 'verbose', - 'filters': ['StripSensitiveFormData'], - }, - 'mail_registration': { - 'level': 'WARNING', - 'class': 'django.utils.log.AdminEmailHandler', - 'formatter': 'verbose', - }, - 'registration_logfile':{ - 'level': 'INFO', + # Catch-all logger + '': { + 'handlers': ['console'], # Add 'mail_admins' in prod and test + 'level': 'DEBUG', + 'filters': ['StripSensitiveFormData'], + }, + + }, + + 'handlers': { + + 'console': { + 'level': 'WARNING', ## Set to 'DEBUG' in local + 'class': 'logging.StreamHandler', + 'formatter': 'verbose', + }, + + 'mail_admins': { + 'level': 'WARNING', + 'class': 'django.utils.log.AdminEmailHandler', + 'formatter': 'verbose', + 'filters': ['StripSensitiveFormData'], + }, + 'mail_registration': { + 'level': 'WARNING', + 'class': 'django.utils.log.AdminEmailHandler', + 'formatter': 'verbose', + }, + 'registration_logfile':{ + 'level': 'INFO', 'class': 'logging.FileHandler', # filename declared in specific configuration files - 'formatter': 'verbose', + 'formatter': 'verbose', }, - 'registration_error_log':{ - 'level': 'INFO', + 'registration_error_log':{ + 'level': 'INFO', 'class': 'logging.FileHandler', # filename declared in specific configuration files - 'formatter': 'verbose', + 'formatter': 'verbose', }, - }, - } + }, + } # Permissions for uploads FILE_UPLOAD_PERMISSIONS = 0o0644 @@ -352,14 +352,14 @@ POSLI_MAILOVOU_NOTIFIKACI = False # Logování chyb class InvalidTemplateVariable(str): - def __mod__(self, variable): - import logging - logger = logging.getLogger(__name__) - for line in traceback.walk_stack(None): - if 'context' in line[0].f_locals and 'request' in line[0].f_locals['context']: - logger.warning("Proměnná '%s' neexistuje: %s" % (variable, line[0].f_locals['context']['request'])) - break - return '' + def __mod__(self, variable): + import logging + logger = logging.getLogger(__name__) + for line in traceback.walk_stack(None): + if 'context' in line[0].f_locals and 'request' in line[0].f_locals['context']: + logger.warning("Proměnná '%s' neexistuje: %s" % (variable, line[0].f_locals['context']['request'])) + break + return '' TEMPLATES[0]['OPTIONS']['string_if_invalid'] = InvalidTemplateVariable('%s') # Django 3.2 vyžaduje explicitní nastavení autoklíče, zatím nechápu proč diff --git a/mamweb/settings_local.py b/mamweb/settings_local.py index 4cf76dc2..540c0453 100644 --- a/mamweb/settings_local.py +++ b/mamweb/settings_local.py @@ -11,16 +11,16 @@ import os.path from .settings_common import * MIDDLEWARE += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', - ) + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ INSTALLED_APPS += ( - 'debug_toolbar', - 'django_extensions', - ) + 'debug_toolbar', + 'django_extensions', + ) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -37,10 +37,10 @@ ALLOWED_HOSTS.append('localhost') # https://docs.djangoproject.com/en/1.7/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db-local.sqlite3'), - } + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db-local.sqlite3'), + } } #DATABASES = { # 'default': { @@ -52,46 +52,46 @@ DATABASES = { # LOGGING LOGGING = { - 'version': 1, - 'disable_existing_loggers': True, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'formatters': { - 'simple': { - 'format': '%(asctime)s - %(name)s - %(levelname)-8s - %(message)s', - }, - }, - 'handlers': { - 'dummy': { - 'class': 'logging.NullHandler', - }, - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'formatter': 'simple', - }, - }, - 'loggers': { + 'version': 1, + 'disable_existing_loggers': True, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'formatters': { + 'simple': { + 'format': '%(asctime)s - %(name)s - %(levelname)-8s - %(message)s', + }, + }, + 'handlers': { + 'dummy': { + 'class': 'logging.NullHandler', + }, + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'simple', + }, + }, + 'loggers': { # Vypisovani databazovych dotazu do konzole - #'django.db.backends': { - # 'level': 'DEBUG', - # 'handlers': ['console'], - # 'propagate': False, - #}, - 'werkzeug': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': True, - }, - '': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': False, - }, - }, + #'django.db.backends': { + # 'level': 'DEBUG', + # 'handlers': ['console'], + # 'propagate': False, + #}, + 'werkzeug': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': True, + }, + '': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + }, } # set to 'DEBUG' for EXTRA verbose output diff --git a/mamweb/settings_prod.py b/mamweb/settings_prod.py index 6a20ff8c..3a81c8c4 100644 --- a/mamweb/settings_prod.py +++ b/mamweb/settings_prod.py @@ -16,8 +16,8 @@ from .settings_common import * # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ INSTALLED_APPS += ( - 'django_extensions', - ) + 'django_extensions', + ) # SECURITY WARNING: keep the secret key used in production secret! assert not SECRET_KEY.startswith('12345') @@ -34,14 +34,14 @@ ALLOWED_HOSTS = ['mam.mff.cuni.cz', 'www.mam.mff.cuni.cz', 'atrey.karlin.mff.cun # https://docs.djangoproject.com/en/1.7/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'mam_prod', - 'USER': 'mam-web', - 'TEST': { - 'NAME': 'mam-prod-testdb', - }, - }, + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'mam_prod', + 'USER': 'mam-web', + 'TEST': { + 'NAME': 'mam-prod-testdb', + }, + }, } import os diff --git a/mamweb/settings_test.py b/mamweb/settings_test.py index 365664d2..eac5a7b4 100644 --- a/mamweb/settings_test.py +++ b/mamweb/settings_test.py @@ -13,16 +13,16 @@ import os.path from .settings_common import * # zatim nutne, casem snad vyresime # noqa MIDDLEWARE += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', - ) + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ INSTALLED_APPS += ( - 'debug_toolbar', - 'django_extensions', - ) + 'debug_toolbar', + 'django_extensions', + ) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = ')^u=i65*zmr_k53a*@f4q_+ji^o@!pgpef*5&8c7zzv9l+zo)n' @@ -38,21 +38,21 @@ ALLOWED_HOSTS = ['*.mam.mff.cuni.cz', 'atrey.karlin.mff.cuni.cz', 'mam.mff.cuni. # https://docs.djangoproject.com/en/1.7/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'mam_test', - 'USER': 'mam-web', - 'TEST': { - 'NAME': 'mam-test-testdb', - }, - }, + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'mam_test', + 'USER': 'mam-web', + 'TEST': { + 'NAME': 'mam-test-testdb', + }, + }, } import os SERVER_EMAIL = 'mamweb-test-errors@mam.mff.cuni.cz' ADMINS = [ - ('M&M ERRORs', 'mam-errors@mam.mff.cuni.cz'), + ('M&M ERRORs', 'mam-errors@mam.mff.cuni.cz'), ] diff --git a/seminar/models/base.py b/seminar/models/base.py index 77c857a3..1069f165 100644 --- a/seminar/models/base.py +++ b/seminar/models/base.py @@ -4,18 +4,18 @@ from django.db import models class SeminarModelBase(models.Model): - class Meta: - abstract = True + class Meta: + abstract = True - def verejne(self): - return False + def verejne(self): + return False - # def get_absolute_url(self): - # return "https://" + str(get_current_site(None)) + self.verejne_url() + # def get_absolute_url(self): + # return "https://" + str(get_current_site(None)) + self.verejne_url() - def admin_url(self): - model_name = self.__class__.__name__.lower() - return reverse('admin:seminar_{}_change'.format(model_name), args=(self.id, )) + def admin_url(self): + model_name = self.__class__.__name__.lower() + return reverse('admin:seminar_{}_change'.format(model_name), args=(self.id, )) # def verejne_url(self): # return None diff --git a/seminar/models/novinky.py b/seminar/models/novinky.py index f6ce4161..cee674a8 100644 --- a/seminar/models/novinky.py +++ b/seminar/models/novinky.py @@ -9,30 +9,30 @@ from . import personalni as pm @reversion.register(ignore_duplicates=True) class Novinky(models.Model): - class Meta: - verbose_name = 'Novinka' - verbose_name_plural = 'Novinky' - ordering = ['-datum'] + class Meta: + verbose_name = 'Novinka' + verbose_name_plural = 'Novinky' + ordering = ['-datum'] - datum = models.DateField(auto_now_add=True) + datum = models.DateField(auto_now_add=True) - text = models.TextField('Text novinky', blank=True, null=True) - obrazek = models.ImageField('Obrázek', upload_to='image_novinky/%Y/%m/%d/', - null=True, blank=True) + text = models.TextField('Text novinky', blank=True, null=True) + obrazek = models.ImageField('Obrázek', upload_to='image_novinky/%Y/%m/%d/', + null=True, blank=True) - obrazek_maly = ImageSpecField(source='obrazek', - processors=[ - ResizeToFit(350, 200, upscale=False) - ], - options={'quality': 95}) + obrazek_maly = ImageSpecField(source='obrazek', + processors=[ + ResizeToFit(350, 200, upscale=False) + ], + options={'quality': 95}) - autor = models.ForeignKey(pm.Organizator, verbose_name='Autor novinky', null=True, - on_delete=models.SET_NULL) + autor = models.ForeignKey(pm.Organizator, verbose_name='Autor novinky', null=True, + on_delete=models.SET_NULL) - zverejneno = models.BooleanField('Zveřejněno', default=False) + zverejneno = models.BooleanField('Zveřejněno', default=False) - def __str__(self): - if self.text: - return '[' + str(self.datum) + '] ' + self.text[0:50] - else: - return '[' + str(self.datum) + '] ' + def __str__(self): + if self.text: + return '[' + str(self.datum) + '] ' + self.text[0:50] + else: + return '[' + str(self.datum) + '] ' diff --git a/seminar/models/odevzdavatko.py b/seminar/models/odevzdavatko.py index 9ae161c5..c286558c 100644 --- a/seminar/models/odevzdavatko.py +++ b/seminar/models/odevzdavatko.py @@ -18,68 +18,68 @@ from seminar.models import base as bm @reversion.register(ignore_duplicates=True) class Reseni(bm.SeminarModelBase): - class Meta: - db_table = 'seminar_reseni' - verbose_name = 'Řešení' - verbose_name_plural = 'Řešení' - #ordering = ['-problem', 'resitele'] # FIXME: Takhle to chceme, ale nefunguje to. - ordering = ['-cas_doruceni'] + class Meta: + db_table = 'seminar_reseni' + verbose_name = 'Řešení' + verbose_name_plural = 'Řešení' + #ordering = ['-problem', 'resitele'] # FIXME: Takhle to chceme, ale nefunguje to. + ordering = ['-cas_doruceni'] - # Interní ID - id = models.AutoField(primary_key = True) + # Interní ID + id = models.AutoField(primary_key = True) - # 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', - through='Hodnoceni') + # 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', + through='Hodnoceni') - resitele = models.ManyToManyField(pm.Resitel, verbose_name='autoři řešení', - help_text='Seznam autorů řešení', through='Reseni_Resitele') + resitele = models.ManyToManyField(pm.Resitel, verbose_name='autoři řešení', + help_text='Seznam autorů řešení', through='Reseni_Resitele') - 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_PAPIR = 'papir' - FORMA_EMAIL = 'email' - FORMA_UPLOAD = 'upload' - FORMA_CHOICES = [ - (FORMA_PAPIR, 'Papírové řešení'), - (FORMA_EMAIL, 'Emailem'), - (FORMA_UPLOAD, 'Upload přes web'), - ] - forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, - default=FORMA_EMAIL) + FORMA_PAPIR = 'papir' + FORMA_EMAIL = 'email' + FORMA_UPLOAD = 'upload' + FORMA_CHOICES = [ + (FORMA_PAPIR, 'Papírové řešení'), + (FORMA_EMAIL, 'Emailem'), + (FORMA_UPLOAD, 'Upload přes web'), + ] + forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, + default=FORMA_EMAIL) - text_cely = models.OneToOneField('ReseniNode', verbose_name='Plná verze textu řešení', - blank=True, null=True, related_name="reseni_cely_set", - on_delete=models.PROTECT) + text_cely = models.OneToOneField('ReseniNode', verbose_name='Plná verze textu řešení', + blank=True, null=True, related_name="reseni_cely_set", + on_delete=models.PROTECT) - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k řešení (plain text)') + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k řešení (plain text)') - zverejneno = models.BooleanField('řešení zveřejněno', default=False, - help_text='Udává, zda je řešení zveřejněno') + zverejneno = models.BooleanField('řešení zveřejněno', default=False, + help_text='Udává, zda je řešení zveřejněno') - def verejne_url(self): - return str(reverse_lazy('odevzdavatko_detail_reseni', args=[self.id])) + def verejne_url(self): + return str(reverse_lazy('odevzdavatko_detail_reseni', args=[self.id])) - def absolute_url(self): - return "https://" + str(get_current_site(None)) + self.verejne_url() + def absolute_url(self): + return "https://" + str(get_current_site(None)) + self.verejne_url() - # má OneToOneField s: - # Konfera + # má OneToOneField s: + # Konfera - # má ForeignKey s: - # Hodnoceni + # má ForeignKey s: + # Hodnoceni - def sum_body(self): - return self.hodnoceni_set.all().aggregate(Sum('body'))["body__sum"] + def sum_body(self): + return self.hodnoceni_set.all().aggregate(Sum('body'))["body__sum"] - def __str__(self): - return "{}({}): {}({})".format(self.resitele.first(),len(self.resitele.all()), self.problem.first() ,len(self.problem.all())) - # NOTE: Potenciální DB HOG (bez select_related) + def __str__(self): + return "{}({}): {}({})".format(self.resitele.first(),len(self.resitele.all()), self.problem.first() ,len(self.problem.all())) + # NOTE: Potenciální DB HOG (bez select_related) - def deadline_reseni(self): - return am.Deadline.objects.filter(deadline__gte=self.cas_doruceni).order_by("deadline").first() + def deadline_reseni(self): + return am.Deadline.objects.filter(deadline__gte=self.cas_doruceni).order_by("deadline").first() ## Pravdepodobne uz nebude potreba: # def save(self, *args, **kwargs): @@ -89,112 +89,112 @@ class Reseni(bm.SeminarModelBase): # super(Reseni, self).save(*args, **kwargs) class Hodnoceni(bm.SeminarModelBase): - class Meta: - db_table = 'seminar_hodnoceni' - verbose_name = 'Hodnocení' - verbose_name_plural = 'Hodnocení' + class Meta: + db_table = 'seminar_hodnoceni' + verbose_name = 'Hodnocení' + verbose_name_plural = 'Hodnocení' - # Interní ID - id = models.AutoField(primary_key = True) + # Interní ID + id = models.AutoField(primary_key = True) - body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='body', - blank=True, null=True) + body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='body', + blank=True, null=True) - cislo_body = models.ForeignKey(am.Cislo, verbose_name='číslo pro body', - related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT) + cislo_body = models.ForeignKey(am.Cislo, verbose_name='číslo pro body', + 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 - deadline_body = models.ForeignKey(am.Deadline, verbose_name='deadline pro body', - 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 + deadline_body = models.ForeignKey(am.Deadline, verbose_name='deadline pro body', + 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', - related_name='hodnoceni', on_delete=models.PROTECT) + problem = models.ForeignKey(am.Problem, verbose_name='problém', + 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)') - def __str__(self): - return "{}, {}, {}".format(self.problem, self.reseni, self.body) + def __str__(self): + return "{}, {}, {}".format(self.problem, self.reseni, self.body) def generate_filename(self, filename): - return os.path.join( - settings.SEMINAR_RESENI_DIR, - am.aux_generate_filename(self, filename) - ) + return os.path.join( + settings.SEMINAR_RESENI_DIR, + am.aux_generate_filename(self, filename) + ) @reversion.register(ignore_duplicates=True) class PrilohaReseni(bm.SeminarModelBase): - class Meta: - db_table = 'seminar_priloha_reseni' - verbose_name = 'Příloha řešení' - verbose_name_plural = 'Přílohy řešení' - ordering = ['reseni', 'vytvoreno'] + class Meta: + db_table = 'seminar_priloha_reseni' + verbose_name = 'Příloha řešení' + verbose_name_plural = 'Přílohy řešení' + ordering = ['reseni', 'vytvoreno'] - # Interní ID - id = models.AutoField(primary_key = True) + # Interní ID + id = models.AutoField(primary_key = True) - reseni = models.ForeignKey(Reseni, verbose_name='řešení', related_name='prilohy', - on_delete=models.CASCADE) + reseni = models.ForeignKey(Reseni, verbose_name='řešení', related_name='prilohy', + on_delete=models.CASCADE) - vytvoreno = models.DateTimeField('vytvořeno', default=timezone.now, blank=True, editable=False) + vytvoreno = models.DateTimeField('vytvořeno', default=timezone.now, blank=True, editable=False) - soubor = models.FileField('soubor', upload_to = generate_filename) + soubor = models.FileField('soubor', upload_to = generate_filename) - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k příloze řešení (plain text), např. o původu') + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k příloze řešení (plain text), např. o původu') - res_poznamka = models.TextField('poznámka řešitele', blank=True, - help_text='Poznámka k příloze řešení, např. co daný soubor obsahuje') + res_poznamka = models.TextField('poznámka řešitele', blank=True, + help_text='Poznámka k příloze řešení, např. co daný soubor obsahuje') - def __str__(self): - return str(self.soubor) + def __str__(self): + return str(self.soubor) - def split(self): - "Vrátí cestu rozsekanou po složkách. To se hodí v templatech" - # Věřím, že tohle funguje, případně použít os.path nebo pathlib. - return self.soubor.url.split('/') + def split(self): + "Vrátí cestu rozsekanou po složkách. To se hodí v templatech" + # Věřím, že tohle funguje, případně použít os.path nebo pathlib. + return self.soubor.url.split('/') # Vazebna tabulka. Mozna se generuje automaticky. @reversion.register(ignore_duplicates=True) class Reseni_Resitele(models.Model): - class Meta: - db_table = 'seminar_reseni_resitele' - verbose_name = 'Řešení řešitelů' - verbose_name_plural = 'Řešení řešitelů' - ordering = ['reseni', 'resitele'] + class Meta: + db_table = 'seminar_reseni_resitele' + verbose_name = 'Řešení řešitelů' + verbose_name_plural = 'Řešení řešitelů' + ordering = ['reseni', 'resitele'] - # Interní ID - id = models.AutoField(primary_key = True) + # Interní ID + id = models.AutoField(primary_key = True) - resitele = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + resitele = models.ForeignKey(pm.Resitel, verbose_name='řešitel', 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) - # podil - jakou merou se ktery resitel podilel na danem reseni - # - pouziti v budoucnu, pokud by resitele nemeli dostat vsichni stejne bodu za spolecne reseni + # podil - jakou merou se ktery resitel podilel na danem reseni + # - pouziti v budoucnu, pokud by resitele nemeli dostat vsichni stejne bodu za spolecne reseni - def __str__(self): - return '{} od {}'.format(self.reseni, self.resitel) - # NOTE: Poteciální DB HOG bez select_related + def __str__(self): + return '{} od {}'.format(self.reseni, self.resitel) + # NOTE: Poteciální DB HOG bez select_related class ReseniNode(tm.TreeNode): - class Meta: - db_table = 'seminar_nodes_otistene_reseni' - verbose_name = 'Otištěné řešení (Node)' - verbose_name_plural = 'Otištěná řešení (Node)' - reseni = models.ForeignKey(Reseni, - on_delete=models.PROTECT, - verbose_name = 'reseni') - - def aktualizuj_nazev(self): - self.nazev = "ReseniNode: "+str(self.reseni) - - def getOdkazStr(self): - return str(self.reseni) + class Meta: + db_table = 'seminar_nodes_otistene_reseni' + verbose_name = 'Otištěné řešení (Node)' + verbose_name_plural = 'Otištěná řešení (Node)' + reseni = models.ForeignKey(Reseni, + on_delete=models.PROTECT, + verbose_name = 'reseni') + + def aktualizuj_nazev(self): + self.nazev = "ReseniNode: "+str(self.reseni) + + def getOdkazStr(self): + return str(self.reseni) diff --git a/soustredeni/admin.py b/soustredeni/admin.py index 11cb8d1d..091f9c59 100644 --- a/soustredeni/admin.py +++ b/soustredeni/admin.py @@ -6,38 +6,38 @@ from seminar.models import soustredeni as m class SoustredeniUcastniciInline(admin.TabularInline): - model = m.Soustredeni_Ucastnici - extra = 1 - fields = ['resitel','poznamka'] - autocomplete_fields = ['resitel'] - ordering = ['resitel__osoba__jmeno', 'resitel__osoba__prijmeni'] - formfield_overrides = { - models.TextField: {'widget': widgets.TextInput} - } + model = m.Soustredeni_Ucastnici + extra = 1 + fields = ['resitel','poznamka'] + autocomplete_fields = ['resitel'] + ordering = ['resitel__osoba__jmeno', 'resitel__osoba__prijmeni'] + formfield_overrides = { + models.TextField: {'widget': widgets.TextInput} + } - def get_queryset(self,request): - qs = super().get_queryset(request) - return qs.select_related('resitel','soustredeni') + def get_queryset(self,request): + qs = super().get_queryset(request) + return qs.select_related('resitel','soustredeni') class SoustredeniOrganizatoriInline(admin.TabularInline): - model = m.Soustredeni.organizatori.through - extra = 1 - fields = ['organizator','poznamka'] - autocomplete_fields = ['organizator'] - ordering = ['organizator__osoba__jmeno','organizator__prijmeni'] - formfield_overrides = { - models.TextField: {'widget': widgets.TextInput} - } + model = m.Soustredeni.organizatori.through + extra = 1 + fields = ['organizator','poznamka'] + autocomplete_fields = ['organizator'] + ordering = ['organizator__osoba__jmeno','organizator__prijmeni'] + formfield_overrides = { + models.TextField: {'widget': widgets.TextInput} + } - def get_queryset(self,request): - qs = super().get_queryset(request) - return qs.select_related('organizator', 'soustredeni') + def get_queryset(self,request): + qs = super().get_queryset(request) + return qs.select_related('organizator', 'soustredeni') @admin.register(m.Soustredeni) class SoustredeniAdmin(admin.ModelAdmin): - model = m.Soustredeni - inline_type = 'tabular' - inlines = [SoustredeniUcastniciInline, SoustredeniOrganizatoriInline] + model = m.Soustredeni + inline_type = 'tabular' + inlines = [SoustredeniUcastniciInline, SoustredeniOrganizatoriInline] diff --git a/treenode/admin.py b/treenode/admin.py index d2ff4409..92c85cd5 100644 --- a/treenode/admin.py +++ b/treenode/admin.py @@ -9,80 +9,80 @@ import seminar.models as m @admin.register(m.TreeNode) class TreeNodeAdmin(PolymorphicParentModelAdmin): - base_model = m.TreeNode - child_models = [ - m.RocnikNode, - m.CisloNode, - m.MezicisloNode, - m.TemaVCisleNode, - m.UlohaZadaniNode, - m.PohadkaNode, - m.UlohaVzorakNode, - m.TextNode, - m.CastNode, - m.OrgTextNode, - ] - - actions = ['aktualizuj_nazvy'] - - # XXX: nejspíš je to totální DB HOG, nechcete to použít moc často. - def aktualizuj_nazvy(self, request, queryset): - newqs = queryset.get_real_instances() - for tn in newqs: - tn.aktualizuj_nazev() - tn.save() - self.message_user(request, "Názvy aktualizovány.") - aktualizuj_nazvy.short_description = "Aktualizuj vybraným TreeNodům názvy" + base_model = m.TreeNode + child_models = [ + m.RocnikNode, + m.CisloNode, + m.MezicisloNode, + m.TemaVCisleNode, + m.UlohaZadaniNode, + m.PohadkaNode, + m.UlohaVzorakNode, + m.TextNode, + m.CastNode, + m.OrgTextNode, + ] + + actions = ['aktualizuj_nazvy'] + + # XXX: nejspíš je to totální DB HOG, nechcete to použít moc často. + def aktualizuj_nazvy(self, request, queryset): + newqs = queryset.get_real_instances() + for tn in newqs: + tn.aktualizuj_nazev() + tn.save() + self.message_user(request, "Názvy aktualizovány.") + aktualizuj_nazvy.short_description = "Aktualizuj vybraným TreeNodům názvy" @admin.register(m.RocnikNode) class RocnikNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.RocnikNode - show_in_index = True + base_model = m.RocnikNode + show_in_index = True @admin.register(m.CisloNode) class CisloNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.CisloNode - show_in_index = True + base_model = m.CisloNode + show_in_index = True @admin.register(m.MezicisloNode) class MezicisloNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.MezicisloNode - show_in_index = True + base_model = m.MezicisloNode + show_in_index = True @admin.register(m.TemaVCisleNode) class TemaVCisleNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.TemaVCisleNode - show_in_index = True + base_model = m.TemaVCisleNode + show_in_index = True @admin.register(m.UlohaZadaniNode) class UlohaZadaniNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.UlohaZadaniNode - show_in_index = True + base_model = m.UlohaZadaniNode + show_in_index = True @admin.register(m.PohadkaNode) class PohadkaNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.PohadkaNode - show_in_index = True + base_model = m.PohadkaNode + show_in_index = True @admin.register(m.UlohaVzorakNode) class UlohaVzorakNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.UlohaVzorakNode - show_in_index = True + base_model = m.UlohaVzorakNode + show_in_index = True @admin.register(m.TextNode) class TextNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.TextNode - show_in_index = True + base_model = m.TextNode + show_in_index = True @admin.register(m.CastNode) class TextNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.CastNode - show_in_index = True - fields = ('nadpis',) + base_model = m.CastNode + show_in_index = True + fields = ('nadpis',) @admin.register(m.OrgTextNode) class TextNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.OrgTextNode - show_in_index = True + base_model = m.OrgTextNode + show_in_index = True diff --git a/treenode/permissions.py b/treenode/permissions.py index 5503832f..bc5c68a8 100644 --- a/treenode/permissions.py +++ b/treenode/permissions.py @@ -2,6 +2,6 @@ from rest_framework.permissions import BasePermission class AllowWrite(BasePermission): - def has_permission(self, request, view): - return request.user.has_perm('auth.org') + def has_permission(self, request, view): + return request.user.has_perm('auth.org') diff --git a/various/autentizace/utils.py b/various/autentizace/utils.py index 2341fbdd..d8bea060 100644 --- a/various/autentizace/utils.py +++ b/various/autentizace/utils.py @@ -6,16 +6,16 @@ from django.utils.http import urlsafe_base64_encode def posli_reset_hesla(u, request=None): - uid = urlsafe_base64_encode(force_bytes(u.pk)) - token = PasswordResetTokenGenerator().make_token(u) - url = "https://%s%s" % ( - str(get_current_site(request)), - str(reverse_lazy("reset_password_confirm", args=[uid, token])) - ) + uid = urlsafe_base64_encode(force_bytes(u.pk)) + token = PasswordResetTokenGenerator().make_token(u) + url = "https://%s%s" % ( + str(get_current_site(request)), + str(reverse_lazy("reset_password_confirm", args=[uid, token])) + ) - u.email_user( - subject="Vítej mezi řešiteli M&M!", - message="""Milý řešiteli, milá řešitelko, + u.email_user( + subject="Vítej mezi řešiteli M&M!", + message="""Milý řešiteli, milá řešitelko, tvůj e-mail byl právě zaregistrován na mam.matfyz.cz. Heslo si prosím nastav na: %s @@ -26,6 +26,6 @@ Organizátoři M&M Tento e-mail byl vygenerován automaticky, chceš-li nás kontaktovat, napiš nám na adresu mam@matfyz.cz. """ % url, - # TODO: templates/autentizace a django/contrib/auth/forms.py říkají, jak na to lépe - from_email="registrace@mam.mff.cuni.cz", # FIXME: Chceme to mít radši tady, nebo v nastavení? - ) \ No newline at end of file + # TODO: templates/autentizace a django/contrib/auth/forms.py říkají, jak na to lépe + from_email="registrace@mam.mff.cuni.cz", # FIXME: Chceme to mít radši tady, nebo v nastavení? + ) \ No newline at end of file diff --git a/various/log_filters.py b/various/log_filters.py index f20e032c..f037dcde 100644 --- a/various/log_filters.py +++ b/various/log_filters.py @@ -2,10 +2,10 @@ from logging import Filter, INFO from django.urls import reverse class Http404AsInfoFilter(Filter): - def filter(self, record): - if record.name == 'django.request' and record.status_code == 404: - record.levelno = INFO - return 1 # Keep the log record + def filter(self, record): + if record.name == 'django.request' and record.status_code == 404: + record.levelno = INFO + return 1 # Keep the log record class StripSensitiveFormDataFilter(Filter): def filter(self, record): From 4a0e8e61be8cdc529a5eb2e76faf990a56d41de4 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 1 Dec 2022 13:07:09 +0100 Subject: [PATCH 61/68] =?UTF-8?q?Druh=C3=A1=20v=C3=A1rka=20zarovn=C3=A1n?= =?UTF-8?q?=C3=AD=20tabul=C3=A1tory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/views/autocomplete.py | 2 +- seminar/testutils.py | 18 +++++++++--------- seminar/views/views_all.py | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/api/views/autocomplete.py b/api/views/autocomplete.py index 33e083eb..838c7dba 100644 --- a/api/views/autocomplete.py +++ b/api/views/autocomplete.py @@ -12,7 +12,7 @@ from .helpers import LoginRequiredAjaxMixin class SkolaAutocomplete(autocomplete.Select2QuerySetView): """ View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """ 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() if self.q: words = self.q.split(' ') #TODO re split podle bileho znaku diff --git a/seminar/testutils.py b/seminar/testutils.py index a13e82c8..7076d5f0 100644 --- a/seminar/testutils.py +++ b/seminar/testutils.py @@ -474,15 +474,15 @@ def get_text(): def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod): tema = Tema.objects.create( - nazev=nazev, - stav=Problem.STAV_ZADANY, - zamereni="M", - autor=rnd.choice(organizatori), - garant=rnd.choice(organizatori), - kod=str(kod), - tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0], - rocnik=rocnik, - abstrakt = lorem.paragraph() + nazev=nazev, + stav=Problem.STAV_ZADANY, + zamereni="M", + autor=rnd.choice(organizatori), + garant=rnd.choice(organizatori), + kod=str(kod), + tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0], + rocnik=rocnik, + abstrakt = lorem.paragraph() ) # Generování struktury k tématu diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index c5631430..3f2cdf01 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -686,7 +686,7 @@ def formularOKView(request, text=''): ] context = { 'odkazy': odkazy, - 'text': text, + 'text': text, } return render(request, template_name, context) From 5178d95a44c89a73ea20905da793afd8d0fb144c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sun, 4 Dec 2022 19:58:34 +0100 Subject: [PATCH 62/68] =?UTF-8?q?add:=20title=20u=20obr=C3=A1zkov=C3=BDch?= =?UTF-8?q?=20odkaz=C5=AF=20v=20detailu=20=C5=99e=C5=A1en=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- odevzdavatko/templates/odevzdavatko/detail.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/odevzdavatko/templates/odevzdavatko/detail.html b/odevzdavatko/templates/odevzdavatko/detail.html index 9f6d31ac..207e2976 100644 --- a/odevzdavatko/templates/odevzdavatko/detail.html +++ b/odevzdavatko/templates/odevzdavatko/detail.html @@ -109,14 +109,14 @@ $(document).ready(function(){ {{ subform.body }} {{ subform.deadline_body }} {{ subform.feedback }} - Smazat + Smazat {% endfor %} - Přidat hodnocení
+ Přidat hodnocení
@@ -125,7 +125,7 @@ $(document).ready(function(){ - + From 52904575b070667037507ff7404212bcc17dcbc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sun, 4 Dec 2022 20:14:59 +0100 Subject: [PATCH 63/68] =?UTF-8?q?hotfix:=20opraveno=20zobrazov=C3=A1n?= =?UTF-8?q?=C3=AD=20smazat=20hodnocen=C3=AD=20v=20detailu=20=C5=99e=C5=A1e?= =?UTF-8?q?n=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mamweb/static/css/mamweb.css | 7 +++++++ odevzdavatko/templates/odevzdavatko/detail.html | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mamweb/static/css/mamweb.css b/mamweb/static/css/mamweb.css index 236072f5..f4d8c0f8 100644 --- a/mamweb/static/css/mamweb.css +++ b/mamweb/static/css/mamweb.css @@ -425,6 +425,13 @@ textarea.feedback { margin: 5px; } +/* td obsahující křížek v detailu řešení se nesmí smrštit na 0 */ +/* FIXME až bude firefox příčetný, nahradit td:has(.smazat_hodnoceni) */ +.has_smazat_hodnoceni { + min-width: 20px; + padding: 3px; +} + /* titulni stranka */ diff --git a/odevzdavatko/templates/odevzdavatko/detail.html b/odevzdavatko/templates/odevzdavatko/detail.html index 207e2976..a3f986d5 100644 --- a/odevzdavatko/templates/odevzdavatko/detail.html +++ b/odevzdavatko/templates/odevzdavatko/detail.html @@ -109,7 +109,7 @@ $(document).ready(function(){ {{ subform.body }} {{ subform.deadline_body }} {{ subform.feedback }} - Smazat + Smazat {% endfor %} @@ -125,7 +125,7 @@ $(document).ready(function(){ {{ form.empty_form.body }} {{ form.empty_form.deadline_body }} {{ form.empty_form.feedback }} - Smazat + Smazat From baf08c4f0484c220ea3f6fc23b7ed14577cd8613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Mon, 5 Dec 2022 20:15:31 +0100 Subject: [PATCH 64/68] =?UTF-8?q?hotfix:=20n=C3=A1zev=20u=20korekturovan?= =?UTF-8?q?=C3=A9ho=20pdf=20mohl=20b=C3=BDt=20pr=C3=A1zdn=C3=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0019_auto_20221205_2014.py | 18 ++++++++++++++++++ korektury/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 korektury/migrations/0019_auto_20221205_2014.py diff --git a/korektury/migrations/0019_auto_20221205_2014.py b/korektury/migrations/0019_auto_20221205_2014.py new file mode 100644 index 00000000..6860e626 --- /dev/null +++ b/korektury/migrations/0019_auto_20221205_2014.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.28 on 2022-12-05 19:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0018_korekturovanepdf_poslat_mail'), + ] + + operations = [ + migrations.AlterField( + model_name='korekturovanepdf', + name='nazev', + field=models.CharField(help_text='Název (např. 22.1 verze 4) korekturovaného PDF', max_length=50, verbose_name='název PDF'), + ), + ] diff --git a/korektury/models.py b/korektury/models.py index 34caba9a..ac82c14e 100644 --- a/korektury/models.py +++ b/korektury/models.py @@ -55,7 +55,7 @@ class KorekturovanePDF(models.Model): cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF') - nazev = models.CharField(u'název PDF',blank = True,max_length=50, help_text='Název (např. 22.1 verze 4) korekturovaného PDF') + nazev = models.CharField(u'název PDF',blank = False,max_length=50, help_text='Název (např. 22.1 verze 4) korekturovaného PDF') komentar = models.TextField(u'komentář k PDF',blank = True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)') From 1b521049af6c8d98770da2508fe54f5c0f2b0477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Mon, 5 Dec 2022 20:53:22 +0100 Subject: [PATCH 65/68] =?UTF-8?q?hotfix:=20tabulka=20od.=20=C5=99e=C5=A1en?= =?UTF-8?q?=C3=AD=20na=20celou=20obrazovku?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mamweb/static/css/mamweb.css | 7 +++++++ odevzdavatko/templates/odevzdavatko/tabulka.html | 2 ++ 2 files changed, 9 insertions(+) diff --git a/mamweb/static/css/mamweb.css b/mamweb/static/css/mamweb.css index f4d8c0f8..0eef6964 100644 --- a/mamweb/static/css/mamweb.css +++ b/mamweb/static/css/mamweb.css @@ -1216,6 +1216,13 @@ div.gdpr { } /* tabulka odevzdaných a došlých řešení */ + +/* Roztáhne obsah z containeru na celou šířku obrazovky: */ +.full_width { + width: 100vw; + margin-left: calc(-50vw + 485px); +} + .dosla_reseni tr th, .dosla_reseni tr td { padding: 1px 10px 1px 10px; border-collapse: collapse; diff --git a/odevzdavatko/templates/odevzdavatko/tabulka.html b/odevzdavatko/templates/odevzdavatko/tabulka.html index 419b4473..6d1232d2 100644 --- a/odevzdavatko/templates/odevzdavatko/tabulka.html +++ b/odevzdavatko/templates/odevzdavatko/tabulka.html @@ -4,6 +4,7 @@ {% block content %} +
{{ filtr.resitele }} {{ filtr.problemy }} @@ -64,4 +65,5 @@ Do data (včetně): {{ filtr.reseni_do }} location.assign(redirect); } +
{% endblock %} From 2e06960f51406d7e658f6264e0e731aef1135066 Mon Sep 17 00:00:00 2001 From: Jonas Havelka Date: Tue, 6 Dec 2022 00:16:40 +0100 Subject: [PATCH 66/68] =?UTF-8?q?To=C5=BE=20jsme=20to=20upravili?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/vyvoj.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/vyvoj.rst b/docs/vyvoj.rst index 256f5eec..0d23972a 100644 --- a/docs/vyvoj.rst +++ b/docs/vyvoj.rst @@ -7,7 +7,7 @@ vlastních úpravách nezávisle na ostatních. Potřebné vybavení ------- -Tento soupis cílí na nějakého typického vývojáře webu – Linuxáka. Jistě je +Tento soupis cílí na Linuxáky. Jistě je spousta dalších možností, které zde nejsou postihnuty – poraď se s webaři, pokud si nejsi jistý. (Speciálně lze nějak vyvíjet na Windows, leč lze často narazit na odlišné chování od Linuxu.) @@ -27,7 +27,7 @@ Nutné - Ideálně ve verzi 3.9 (to je to, co je aktuálně (2022) na Gimlim) - Včetně pip-u (na Ubuntu balíček ``python3-pip``), venvu (``python3-venv``) a knihoven pro kompilaci Cčkových rozšíření (``python3-dev``) -- Knihovna pro práci s PostgreSQL (``libpq-dev``) +- Knihovna pro práci s PostgreSQL (``libpq-dev``, protože jsou potřeba všechny db backendy) - Webový prohlížeč - \*NIXový shell (typicky ``bash``) From 0e99cf286f6b1d3a10bee10d9b59d68f99e94581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Tue, 6 Dec 2022 01:02:38 +0100 Subject: [PATCH 67/68] =?UTF-8?q?fix:=20tohle=20p=C5=99ed=C4=9Bl=C3=A1n?= =?UTF-8?q?=C3=AD=20mezer=20na=20taby=20vypadalo=20podez=C5=99ele,=20tak?= =?UTF-8?q?=20jsem=20to=20upravil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/views/autocomplete.py | 2 +- treenode/permissions.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/views/autocomplete.py b/api/views/autocomplete.py index 838c7dba..4558ad4a 100644 --- a/api/views/autocomplete.py +++ b/api/views/autocomplete.py @@ -12,7 +12,7 @@ from .helpers import LoginRequiredAjaxMixin class SkolaAutocomplete(autocomplete.Select2QuerySetView): """ View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """ 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() if self.q: words = self.q.split(' ') #TODO re split podle bileho znaku diff --git a/treenode/permissions.py b/treenode/permissions.py index bc5c68a8..b4022e19 100644 --- a/treenode/permissions.py +++ b/treenode/permissions.py @@ -2,6 +2,6 @@ from rest_framework.permissions import BasePermission class AllowWrite(BasePermission): - def has_permission(self, request, view): - return request.user.has_perm('auth.org') + def has_permission(self, request, view): + return request.user.has_perm('auth.org') From 9a3f51ca6bfafd76282a709b7473b936a3094716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 14 Dec 2022 22:41:00 +0100 Subject: [PATCH 68/68] =?UTF-8?q?hotfix:=20tabulka=20do=C5=A1l=C3=BDch=20?= =?UTF-8?q?=C5=99e=C5=A1en=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- odevzdavatko/views.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/odevzdavatko/views.py b/odevzdavatko/views.py index 6c232172..1e27d4f1 100644 --- a/odevzdavatko/views.py +++ b/odevzdavatko/views.py @@ -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.... # 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) 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):