Compare commits
3 commits
master
...
export_sez
Author | SHA1 | Date | |
---|---|---|---|
![]() |
64bd360716 | ||
![]() |
350041c587 | ||
![]() |
3a8d5b2207 |
689 changed files with 103272 additions and 64440 deletions
|
@ -1,24 +0,0 @@
|
||||||
# Univerzální popis našich konvencí pro nastavení editorů.
|
|
||||||
# Vizte https://editorconfig.org pro detaily
|
|
||||||
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
# Unixové řádky
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.{py,css}]
|
|
||||||
indent_style = tab
|
|
||||||
# Nenařizujeme konkrétní šířku tabulátoru
|
|
||||||
indent_size = unset
|
|
||||||
|
|
||||||
# Automaticky generované migrace dodržují PEP-8, nemá smysl s tím moc bojovat.
|
|
||||||
[*/migrations/*.py]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[*.html]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -31,15 +31,5 @@ TODO
|
||||||
# reversion kvůli historii objektů v reversion
|
# reversion kvůli historii objektů v reversion
|
||||||
**/reversion
|
**/reversion
|
||||||
|
|
||||||
# dokumentace
|
|
||||||
docs/_build
|
|
||||||
docs/modules
|
|
||||||
|
|
||||||
# logy týracího skriptu (./checklinks.sh)
|
|
||||||
/wget.log.*
|
|
||||||
|
|
||||||
# pro lidi, co programují v nástrojích od JetBrains
|
# pro lidi, co programují v nástrojích od JetBrains
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
# Mac users
|
|
||||||
.DS_Store
|
|
||||||
|
|
158
Makefile
158
Makefile
|
@ -1,9 +1,153 @@
|
||||||
# Existence tohohle Makefile je tu jen proto, aby fungovala svalová paměť. Pokud můžete, použijte rovnou `make/…`
|
PYTHON ?= python3
|
||||||
%:
|
VENV ?= ${PYTHON} -m venv
|
||||||
# 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:
|
# Všechny flagy, které se s venvem/virtualenvem/... mají volat patří sem. Volá se "${VENV} cesta"
|
||||||
make/$*
|
VENV_PATH ?= env
|
||||||
|
# Musí být definovaná, i kdyby to měla být "."
|
||||||
|
|
||||||
default:
|
.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
|
||||||
@cat make/README.md
|
|
||||||
|
|
||||||
.PHONY: default
|
# 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 <Python.h>, 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
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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'
|
||||||
|
|
112
README.md
112
README.md
|
@ -1,58 +1,74 @@
|
||||||
Web M&M
|
Basic commands for web development
|
||||||
======
|
==================================
|
||||||
|
|
||||||
Tohle je repozitář s kódem M&Mího webu. Pokud zde hledáte web samotný nebo
|
After you clone this repository, run `make`. It will download, locally install
|
||||||
informace o semináři, najdete je na <https://mam.matfyz.cz> (a upřímně nechápu,
|
and setup virtualenv and pip, and then locally install all required packages
|
||||||
jak jste se dostali k tomuhle textu :-D)
|
from `requirements.txt`.
|
||||||
|
|
||||||
Pokud jste tu zůstali, tak vás beztak zajímá vývoj webu (a jestli ne, tak
|
When working with the code, always use the binaries in `./bin/`, such as
|
||||||
budeme rádi, když začne :-)).
|
`bin/pip`, `bin/python`, ... never the global python, pip, ...
|
||||||
|
Use `make` and `./manage.py` for most things.
|
||||||
|
|
||||||
Co je M&Mweb uvnitř
|
Use git :-)
|
||||||
------
|
|
||||||
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).
|
|
||||||
|
|
||||||
<!--TODO: Z odstavce výše by ideálně měla být zachována jen první věta a zbytek
|
Quickstart
|
||||||
by měl být někde v docs s podrobnějším popisem…-->
|
----------
|
||||||
|
Run the following commands:
|
||||||
|
make install_venv
|
||||||
|
. env/bin/activate
|
||||||
|
make install_web
|
||||||
|
|
||||||
Jak si web pořídit
|
After finishing development, run "deactivate".
|
||||||
------
|
|
||||||
Prosím přečti si podrobnější návod v <docs/vyvoj.rst> (tady by bylo zbytečné
|
|
||||||
ho duplikovat).
|
|
||||||
|
|
||||||
Jak web vyvíjet
|
Make commands
|
||||||
----
|
-------------
|
||||||
<!--TODO: Napsat obšírněji, asi zase do docs/-->
|
|
||||||
|
|
||||||
Na webu je mnoho věcí k dělání, některé ani nevyžadují kódění (třeba uhánění
|
* `make install` (or `make`) - locally install and setup virtualpy, install
|
||||||
orgů, aby si psali medailonky, aktualizace fotek, …), některé se naopak týkají
|
required packages. Ran again installs missing packages. Run after changing
|
||||||
infrastruktury pod kódem (Gitea, Gimli, …). Je proto těžké mít na to úplně
|
`requirements.txt`.
|
||||||
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 <docs/vyvoj.rst>).
|
* `make clean` - remove local python packages.
|
||||||
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.
|
* `make veryclean` - remove local packages and virtualpy enviroment and
|
||||||
1. Najdi místo, kde se to dá opravit a zkus to tam opravit. Uznávám, že tenhle
|
binaries.
|
||||||
bod je otravně obecný, pokud tápeš, zkus se zeptat zkušenějších webařů nebo
|
|
||||||
podívat do dokumentace.
|
* `make run` - runs "./manage.py runserver_plus"
|
||||||
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)
|
* `make push_test` - pushes the last commited version to test location.
|
||||||
1. Po dohodě s webaři to vyzkoušej na testwebu
|
Only git-commited changes are pushed! Rest is re-generated from scratch.
|
||||||
1. Pošli pull-request a případně zkus reagovat na komentáře
|
At test server, the media data and database are kept the same.
|
||||||
1. Až se změna začlení do hlavní větve (`master`) a nasadí se web na produkci,
|
Everything else not in .gitignore is deleted/overwritten on the test server.
|
||||||
můžeš mít radost, že se web bude používat lépe Tobě i ostatním orgům :-)
|
|
||||||
|
* `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`.
|
||||||
|
|
||||||
### Proč pull-requesty?
|
|
||||||
<!--FIXME: Tohle ale už úplně patří do docs a ne sem, jen je zatím nemám prozkoumané…-->
|
|
||||||
|
|
||||||
Úč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 :-))
|
|
||||||
|
|
16
_git_hooks/README.md
Normal file
16
_git_hooks/README.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
git hooks
|
||||||
|
=========
|
||||||
|
|
||||||
|
Kontrola stylu pythoních zdrojáků pomocí flake8. Kontrolujeme jen změny,
|
||||||
|
abychom nenutili lidi dělat nesouvisející úpravy, které by rozbíjely historii
|
||||||
|
(git blame).
|
||||||
|
|
||||||
|
pre-commit
|
||||||
|
----------
|
||||||
|
* kontrola změn před commitnutím
|
||||||
|
* instalace: lokálně zkopírovat do .git/hooks (musí být spustitelný)
|
||||||
|
|
||||||
|
update
|
||||||
|
------
|
||||||
|
* kontrola změn přicházejících s pushem
|
||||||
|
* instalace: na atreyi zkopírovat do /akce/MaM/MaMweb/mamweb.git/hooks
|
30
_git_hooks/pre-commit
Executable file
30
_git_hooks/pre-commit
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Git hook script to verify what is about to be committed.
|
||||||
|
# Checks that the changes don't introduce new flake8 errors.
|
||||||
|
|
||||||
|
TMPDIFF=`tempfile`
|
||||||
|
FLAKE8="`git rev-parse --show-toplevel`/bin/flake8"
|
||||||
|
|
||||||
|
status=0
|
||||||
|
|
||||||
|
# select only changed python files which are not migrations
|
||||||
|
changed=`git diff --cached --name-only | grep 'py$' | grep -v 'migrations/[0-9]'`
|
||||||
|
if [ -z $changed ] ; then
|
||||||
|
# Nothing to check. Note the exit is necessary -- we would not pass any
|
||||||
|
# paths to git diff below and it would output the diff unfiltered.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git diff --unified=1 --cached HEAD -- $changed > $TMPDIFF
|
||||||
|
|
||||||
|
# only do the check when there are some changes to be commited
|
||||||
|
# otherwise flake8 would hang waiting for input
|
||||||
|
if [ -s $TMPDIFF ] ; then
|
||||||
|
cat $TMPDIFF | $FLAKE8 --diff
|
||||||
|
status=$?
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f $TMPDIFF
|
||||||
|
|
||||||
|
exit $status
|
61
_git_hooks/update
Executable file
61
_git_hooks/update
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# git update hook to check that pushed changes don't introduce new flake8
|
||||||
|
# errors
|
||||||
|
|
||||||
|
# --- Command line
|
||||||
|
refname="$1"
|
||||||
|
oldrev="$2"
|
||||||
|
newrev="$3"
|
||||||
|
|
||||||
|
# --- Safety check
|
||||||
|
if [ -z "$GIT_DIR" ]; then
|
||||||
|
echo "Don't run this script from the command line." >&2
|
||||||
|
echo " (if you want, you could supply GIT_DIR then run" >&2
|
||||||
|
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
||||||
|
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
TMPDIR=`mktemp -d`
|
||||||
|
TMPDIFF=`tempfile`
|
||||||
|
|
||||||
|
[ $refname != "refs/heads/master" -a $refname != "refs/heads/stable" ] && exit 0
|
||||||
|
|
||||||
|
# select only changed python files which are not migrations
|
||||||
|
changed=`git diff --name-only $oldrev $newrev | grep 'py$' | grep -v 'migrations/[0-9]'`
|
||||||
|
if [ -z $changed ] ; then
|
||||||
|
# Nothing to check. Note the exit is necessary -- we would not pass any
|
||||||
|
# paths to git diff below and it would output the diff unfiltered.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git diff --unified=1 $oldrev $newrev -- $changed >${TMPDIFF}
|
||||||
|
|
||||||
|
# there is no working tree in bare git repository, so we recreate it for flake8
|
||||||
|
git archive $newrev | tar -x -C ${TMPDIR}
|
||||||
|
|
||||||
|
cd ${TMPDIR}
|
||||||
|
# report only errors on lines in diff
|
||||||
|
# (if threre was flake8 installed on atrey, we could just call flake8)
|
||||||
|
/akce/MaM/WWW/mamweb-test/bin/flake8 --diff <${TMPDIFF}
|
||||||
|
status=$?
|
||||||
|
if [ $status != 0 ] ; then
|
||||||
|
echo
|
||||||
|
echo -n "Změny, které se snažíte pushnout, obsahují kód v pythonu "
|
||||||
|
echo -n "nevyhovující flake8 (viz výše). Opravte je a zkuste to znovu. "
|
||||||
|
echo -n "Nezapomeňte, že můžete editovat historii (git commit --amend, "
|
||||||
|
echo -n "git rebase -i). Pokud byste chybu příště raději odhalili už při "
|
||||||
|
echo "commitu, zkopírujte si pre-commit hook z _git_hooks do .git/hooks."
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf ${TMPDIR}
|
||||||
|
rm -f ${TMPDIFF}
|
||||||
|
|
||||||
|
exit $status
|
|
@ -1,5 +1,5 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class AesopConfig(AppConfig):
|
class AesopConfig(AppConfig):
|
||||||
name = 'aesop'
|
name = 'aesop'
|
||||||
verbose_name = 'Export do AESOPa'
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
|
|
||||||
class OvvpFile:
|
class OvvpFile:
|
||||||
|
@ -20,7 +20,7 @@ class OvvpFile:
|
||||||
yield '\t'.join(self.columns) + '\n'
|
yield '\t'.join(self.columns) + '\n'
|
||||||
# rows
|
# rows
|
||||||
for r in self.rows:
|
for r in self.rows:
|
||||||
yield '\t'.join([force_str(r[c]) for c in self.columns]) + '\n'
|
yield '\t'.join([force_text(r[c]) for c in self.columns]) + '\n'
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
return ''.join(self.to_lines())
|
return ''.join(self.to_lines())
|
||||||
|
|
|
@ -5,16 +5,16 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
||||||
views.ExportRocnikView.as_view(),
|
views.ExportRocnikView.as_view(),
|
||||||
name='aesop_export_rocnik'
|
name='seminar_export_rocnik'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
||||||
views.ExportSousView.as_view(),
|
views.ExportSousView.as_view(),
|
||||||
name='aesop_export_sous'
|
name='seminar_export_sous'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'aesop-export/index.csv',
|
'aesop-export/index.csv',
|
||||||
views.ExportIndexView.as_view(),
|
views.ExportIndexView.as_view(),
|
||||||
name='aesop_export_index'
|
name='seminar_export_index'
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from aesop.ovvpfile import OvvpFile
|
from aesop.ovvpfile import OvvpFile
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ def default_ovvpfile(event, rocnik):
|
||||||
of = OvvpFile()
|
of = OvvpFile()
|
||||||
of.headers['version'] = '1'
|
of.headers['version'] = '1'
|
||||||
of.headers['event'] = event
|
of.headers['event'] = event
|
||||||
of.headers['year'] = force_str(rocnik.prvni_rok)
|
of.headers['year'] = force_text(rocnik.prvni_rok)
|
||||||
of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
of.headers['id-scope'] = 'mam'
|
of.headers['id-scope'] = 'mam'
|
||||||
of.headers['id-generation'] = '1'
|
of.headers['id-generation'] = '1'
|
||||||
|
|
|
@ -3,22 +3,21 @@ from django.shortcuts import get_object_or_404
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from .utils import default_ovvpfile
|
from .utils import default_ovvpfile
|
||||||
from soustredeni.models import Soustredeni
|
from seminar.models import Rocnik, Soustredeni
|
||||||
from tvorba.models import Rocnik
|
|
||||||
from vysledkovky import utils
|
from vysledkovky import utils
|
||||||
from tvorba.utils import aktivniResitele
|
from seminar.utils import aktivniResitele
|
||||||
|
|
||||||
class ExportIndexView(generic.View):
|
class ExportIndexView(generic.View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
ls = []
|
ls = []
|
||||||
for r in Rocnik.objects.filter(exportovat = True):
|
for r in Rocnik.objects.filter(exportovat = True):
|
||||||
url = reverse('aesop_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
||||||
ls.append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
for s in Soustredeni.objects.filter(exportovat = True):
|
for s in Soustredeni.objects.filter(exportovat = True):
|
||||||
url = reverse('aesop_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
url = reverse('seminar_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
||||||
ls.append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
|
|
||||||
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
||||||
|
|
|
@ -3,4 +3,3 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
class ApiConfig(AppConfig):
|
class ApiConfig(AppConfig):
|
||||||
name = 'api'
|
name = 'api'
|
||||||
verbose_name = 'Různá webová API'
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from django.test import TestCase, tag
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from personalni.models import Skola
|
import seminar.models as m
|
||||||
from personalni.utils import sync_skoly
|
import seminar.views as v
|
||||||
|
from seminar.utils import sync_skoly
|
||||||
|
|
||||||
@tag('stejny-model-na-produkci')
|
|
||||||
class OrgSkolyAutocompleteTestCase(TestCase):
|
class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
@ -11,20 +11,19 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
sync_skoly('https://mam.mff.cuni.cz/')
|
sync_skoly('https://mam.mff.cuni.cz/')
|
||||||
# Správné školy podle toho, co orgové poslali: (prefix, ID školy)
|
# Správné školy podle toho, co orgové poslali: (prefix, ID školy)
|
||||||
# NOTE: Pozor, jedná se o databázové indexy. Pokud se to někdy rozbije, bude potřeba je přepsat nebo předělat na IZO
|
# NOTE: Pozor, jedná se o databázové indexy. Pokud se to někdy rozbije, bude potřeba je přepsat nebo předělat na IZO
|
||||||
# TODO: Opravit zakomentované školy.
|
|
||||||
cls.spravna_data = [
|
cls.spravna_data = [
|
||||||
('gymnázium kolín', 53),
|
('gymnázium kolín', 53),
|
||||||
('kolín', 53),
|
('kolín', 53),
|
||||||
#('gasoš', 96),
|
('gasoš', 96),
|
||||||
('Rokycany', 96),
|
('Rokycany', 96),
|
||||||
#('gasoš Rokycany', 96),
|
('gasoš Rokycany', 96),
|
||||||
#('SPŠE Pardubice', 815),
|
('SPŠE Pardubice', 815),
|
||||||
('Jaroše', 164),
|
('Jaroše', 164),
|
||||||
#("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
|
("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
|
||||||
("Jírovcova", 157),
|
("Jírovcova", 157),
|
||||||
('České Budějovice', 157),
|
('České Budějovice', 157),
|
||||||
("Gymnázium, České Budějovice, Jírovcova 8", 157),
|
("Gymnázium, České Budějovice, Jírovcova 8", 157),
|
||||||
#("první soukromé", 2),
|
("první soukromé", 2),
|
||||||
("Gymnázium Elgartova", 147),
|
("Gymnázium Elgartova", 147),
|
||||||
("Jihlava", 45),
|
("Jihlava", 45),
|
||||||
('Milevsko', 223),
|
('Milevsko', 223),
|
||||||
|
@ -48,7 +47,7 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
||||||
for pfx, id in self.spravna_data:
|
for pfx, id in self.spravna_data:
|
||||||
with self.subTest(prefix=pfx, spravne_id=id):
|
with self.subTest(prefix=pfx, spravne_id=id):
|
||||||
spravna_skola = Skola.objects.get(id=id)
|
spravna_skola = m.Skola.objects.get(id=id)
|
||||||
# Zeptáme se view, co si myslí
|
# Zeptáme se view, co si myslí
|
||||||
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
||||||
ids = [int(x['id']) for x in resp['results']]
|
ids = [int(x['id']) for x in resp['results']]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from . import views
|
from . import views
|
||||||
from personalni.utils import org_required
|
from seminar.utils import org_required
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Export škol
|
# Export škol
|
||||||
|
@ -10,12 +10,10 @@ urlpatterns = [
|
||||||
# Autocomplete
|
# Autocomplete
|
||||||
path('api/autocomplete/skola/', views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
|
path('api/autocomplete/skola/', views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
|
||||||
path('api/autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'),
|
path('api/autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'),
|
||||||
path('api/autocomplete/resitel_public/', views.PublicResitelAutocomplete.as_view(), name='autocomplete_resitel_public'),
|
|
||||||
path('api/autocomplete/problem/odevzdatelny', views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
|
path('api/autocomplete/problem/odevzdatelny', views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
|
||||||
path('api/autocomplete/problem/vsechny', views.ProblemAutocomplete.as_view(), name='autocomplete_problem'),
|
|
||||||
|
|
||||||
# Ceka na autocomplete v3
|
# Ceka na autocomplete v3
|
||||||
# path('autocomplete/organizatori/',
|
# path('autocomplete/organizatori/',
|
||||||
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
||||||
# name='autocomplete_organizator')
|
# name='seminar_autocomplete_organizator')
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,21 +1,15 @@
|
||||||
"""
|
|
||||||
Views k :mod:`dal.autocomplete` pro vyhledávání objektů nějaké třídy v databázi.
|
|
||||||
"""
|
|
||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
from personalni.models import Skola, Resitel
|
import seminar.models as m
|
||||||
from tvorba.models import Problem
|
|
||||||
from various.models import Nastaveni
|
|
||||||
from .helpers import LoginRequiredAjaxMixin
|
from .helpers import LoginRequiredAjaxMixin
|
||||||
|
|
||||||
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
||||||
class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
# Don't forget to filter out results depending on the visitor !
|
# Don't forget to filter out results depending on the visitor !
|
||||||
qs = Skola.objects.all()
|
qs = m.Skola.objects.all()
|
||||||
if self.q:
|
if self.q:
|
||||||
words = self.q.split(' ') #TODO re split podle bileho znaku
|
words = self.q.split(' ') #TODO re split podle bileho znaku
|
||||||
partq = Q()
|
partq = Q()
|
||||||
|
@ -31,70 +25,36 @@ class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
class ResitelAutocomplete(LoginRequiredAjaxMixin,autocomplete.Select2QuerySetView):
|
class ResitelAutocomplete(LoginRequiredAjaxMixin,autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání řešitelů především v odevzdávátku. """
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = Resitel.objects.all()
|
qs = m.Resitel.objects.all()
|
||||||
if self.q:
|
if self.q:
|
||||||
parts = self.q.split()
|
parts = self.q.split()
|
||||||
query = Q()
|
query = Q()
|
||||||
for part in parts:
|
for part in parts:
|
||||||
query &= (
|
query &= (
|
||||||
Q(osoba__jmeno__istartswith=part)|
|
Q(osoba__jmeno__istartswith=self.q)|
|
||||||
Q(osoba__prijmeni__istartswith=part)|
|
Q(osoba__prijmeni__istartswith=self.q)|
|
||||||
Q(osoba__prezdivka__istartswith=part)
|
Q(osoba__prezdivka__istartswith=self.q)
|
||||||
)
|
)
|
||||||
qs = qs.filter(query)
|
qs = qs.filter(query)
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
class PublicResitelAutocomplete(LoginRequiredAjaxMixin, autocomplete.Select2QuerySetView):
|
|
||||||
"""
|
|
||||||
View k :mod:`dal.autocomplete` pro vyhledávání řešitelů podle přezdívky
|
|
||||||
především v odevzdávátku.
|
|
||||||
"""
|
|
||||||
def get_queryset(self):
|
|
||||||
letos = Nastaveni.get_solo().aktualni_rocnik
|
|
||||||
qs = Resitel.objects.filter(
|
|
||||||
rok_maturity__gte=letos.druhy_rok()
|
|
||||||
).filter(
|
|
||||||
prezdivka_resitele__isnull=False
|
|
||||||
).exclude(
|
|
||||||
prezdivka_resitele=""
|
|
||||||
).filter(
|
|
||||||
prezdivka_resitele__icontains=self.q
|
|
||||||
).all()
|
|
||||||
return qs
|
|
||||||
|
|
||||||
def get_result_label(self, result):
|
|
||||||
return result.prezdivka_resitele
|
|
||||||
|
|
||||||
|
|
||||||
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = Problem.objects.filter(stav=Problem.STAV_ZADANY)
|
nastaveni = get_object_or_404(m.Nastaveni)
|
||||||
if self.q:
|
|
||||||
qs = qs.filter(
|
|
||||||
Q(nazev__icontains=self.q))
|
|
||||||
|
|
||||||
nadproblem_id = int(self.forwarded.get("nadproblem_id", -1))
|
|
||||||
if nadproblem_id != -1:
|
|
||||||
# Seřadíme tak, aby ty s nadproblem==None byly dole (větší motivace tam naklikat konkrétní úlohy) a pak nějak rozumně.
|
|
||||||
# Tohle je řazení pro odevzdávátko, kde je definován nadproblém, proto je to v tomto ifu. (Jinde si to netroufám řadit)
|
|
||||||
qs = qs.order_by("nadproblem", "kod", "nazev")
|
|
||||||
qs = list(filter(lambda problem: problem.hlavni_problem.id == nadproblem_id, qs))
|
|
||||||
return qs
|
|
||||||
|
|
||||||
class ProblemAutocomplete(autocomplete.Select2QuerySetView):
|
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
|
||||||
def get_queryset(self):
|
|
||||||
# FIXME i starší úlohy
|
|
||||||
nastaveni = get_object_or_404(Nastaveni)
|
|
||||||
rocnik = nastaveni.aktualni_rocnik
|
rocnik = nastaveni.aktualni_rocnik
|
||||||
temaQ = Q(Tema___rocnik = rocnik)
|
# Od tohoto místa dál jsem zkoušel spoustu variací podle https://django-polymorphic.readthedocs.io/en/stable/advanced.html
|
||||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik=rocnik)
|
temaQ = Q(Tema___rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||||
clanekQ = Q(Clanek___cislo__rocnik=rocnik)
|
ulohaQ = Q(Uloha___cislo_zadani__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||||
qs = Problem.objects.filter(temaQ | ulohaQ | clanekQ).order_by("-stav", "nazev")
|
clanekQ = Q(Clanek___cislo__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||||
|
qs = m.Problem.objects.filter(temaQ | ulohaQ | clanekQ)
|
||||||
|
#print(temata, ulohy, clanky)
|
||||||
|
#ulohy.union(temata, all=True)
|
||||||
|
#print(ulohy)
|
||||||
|
#ulohy.union(clanky, all=True)
|
||||||
|
#print(ulohy)
|
||||||
|
#qs = ulohy
|
||||||
|
print(qs)
|
||||||
if self.q:
|
if self.q:
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(nazev__icontains=self.q))
|
Q(nazev__icontains=self.q))
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import personalni.models as m
|
import seminar.models as m
|
||||||
from django.core import serializers as ser
|
from django.core import serializers as ser
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
def exportSkolView(request):
|
def exportSkolView(request):
|
||||||
"""
|
|
||||||
„view“, který vrací json se seznamem škol, u kterých je uvedeno: 'id', 'izo', 'nazev', 'kratky_nazev', 'ulice', 'mesto', 'psc', 'stat', 'je_zs', 'je_ss'
|
|
||||||
"""
|
|
||||||
# Některé fieldy nechceme: Kontaktní osoby, AESOP ID, org poznámky.
|
# Některé fieldy nechceme: Kontaktní osoby, AESOP ID, org poznámky.
|
||||||
fields = ('id', 'izo', 'nazev', 'kratky_nazev', 'ulice', 'mesto', 'psc', 'stat', 'je_zs', 'je_ss')
|
fields = ('id', 'izo', 'nazev', 'kratky_nazev', 'ulice', 'mesto', 'psc', 'stat', 'je_zs', 'je_ss')
|
||||||
# TODO: Použít JSONL, aby protistrana mohla číst po řádkách a nesežralo to tunu paměti úplně hned
|
# TODO: Použít JSONL, aby protistrana mohla číst po řádkách a nesežralo to tunu paměti úplně hned
|
||||||
|
|
|
@ -2,9 +2,6 @@ from django.http import JsonResponse
|
||||||
|
|
||||||
|
|
||||||
class LoginRequiredAjaxMixin(object):
|
class LoginRequiredAjaxMixin(object):
|
||||||
"""
|
|
||||||
Objekt přidávající povinnost být přihlášený k zobrazení daného view.
|
|
||||||
"""
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
#if request.is_ajax() and not request.user.is_authenticated: # Pokud to otevřu jako stránku, tak se omezení neuplatní, takže to asi nechceme
|
#if request.is_ajax() and not request.user.is_authenticated: # Pokud to otevřu jako stránku, tak se omezení neuplatní, takže to asi nechceme
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
|
|
File diff suppressed because one or more lines are too long
655
data/groups.json
655
data/groups.json
|
@ -1,655 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"fields": {
|
|
||||||
"name": "org",
|
|
||||||
"permissions": [
|
|
||||||
[
|
|
||||||
"org",
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_flatpage",
|
|
||||||
"flatpages",
|
|
||||||
"flatpage"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_flatpage",
|
|
||||||
"flatpages",
|
|
||||||
"flatpage"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_flatpage",
|
|
||||||
"flatpages",
|
|
||||||
"flatpage"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_flatpage",
|
|
||||||
"flatpages",
|
|
||||||
"flatpage"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_galerie",
|
|
||||||
"galerie",
|
|
||||||
"galerie"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_galerie",
|
|
||||||
"galerie",
|
|
||||||
"galerie"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_galerie",
|
|
||||||
"galerie",
|
|
||||||
"galerie"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_galerie",
|
|
||||||
"galerie",
|
|
||||||
"galerie"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_obrazek",
|
|
||||||
"galerie",
|
|
||||||
"obrazek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_obrazek",
|
|
||||||
"galerie",
|
|
||||||
"obrazek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_obrazek",
|
|
||||||
"galerie",
|
|
||||||
"obrazek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_obrazek",
|
|
||||||
"galerie",
|
|
||||||
"obrazek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_fotkaheader",
|
|
||||||
"header_fotky",
|
|
||||||
"fotkaheader"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_fotkaheader",
|
|
||||||
"header_fotky",
|
|
||||||
"fotkaheader"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_fotkaheader",
|
|
||||||
"header_fotky",
|
|
||||||
"fotkaheader"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_fotkaurlvazba",
|
|
||||||
"header_fotky",
|
|
||||||
"fotkaurlvazba"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_fotkaurlvazba",
|
|
||||||
"header_fotky",
|
|
||||||
"fotkaurlvazba"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_fotkaurlvazba",
|
|
||||||
"header_fotky",
|
|
||||||
"fotkaurlvazba"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_komentar",
|
|
||||||
"korektury",
|
|
||||||
"komentar"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_komentar",
|
|
||||||
"korektury",
|
|
||||||
"komentar"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_komentar",
|
|
||||||
"korektury",
|
|
||||||
"komentar"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_komentar",
|
|
||||||
"korektury",
|
|
||||||
"komentar"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_korekturovanepdf",
|
|
||||||
"korektury",
|
|
||||||
"korekturovanepdf"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_korekturovanepdf",
|
|
||||||
"korektury",
|
|
||||||
"korekturovanepdf"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_korekturovanepdf",
|
|
||||||
"korektury",
|
|
||||||
"korekturovanepdf"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_korekturovanepdf",
|
|
||||||
"korektury",
|
|
||||||
"korekturovanepdf"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_oprava",
|
|
||||||
"korektury",
|
|
||||||
"oprava"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_oprava",
|
|
||||||
"korektury",
|
|
||||||
"oprava"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_oprava",
|
|
||||||
"korektury",
|
|
||||||
"oprava"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_oprava",
|
|
||||||
"korektury",
|
|
||||||
"oprava"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_novinky",
|
|
||||||
"novinky",
|
|
||||||
"novinky"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_novinky",
|
|
||||||
"novinky",
|
|
||||||
"novinky"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_novinky",
|
|
||||||
"novinky",
|
|
||||||
"novinky"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_novinky",
|
|
||||||
"novinky",
|
|
||||||
"novinky"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_organizator",
|
|
||||||
"personalni",
|
|
||||||
"organizator"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_organizator",
|
|
||||||
"personalni",
|
|
||||||
"organizator"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_osoba",
|
|
||||||
"personalni",
|
|
||||||
"osoba"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_osoba",
|
|
||||||
"personalni",
|
|
||||||
"osoba"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_prijemce",
|
|
||||||
"personalni",
|
|
||||||
"prijemce"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_prijemce",
|
|
||||||
"personalni",
|
|
||||||
"prijemce"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_prijemce",
|
|
||||||
"personalni",
|
|
||||||
"prijemce"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_prijemce",
|
|
||||||
"personalni",
|
|
||||||
"prijemce"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_resitel",
|
|
||||||
"personalni",
|
|
||||||
"resitel"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_resitel",
|
|
||||||
"personalni",
|
|
||||||
"resitel"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_skola",
|
|
||||||
"personalni",
|
|
||||||
"skola"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_skola",
|
|
||||||
"personalni",
|
|
||||||
"skola"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_skola",
|
|
||||||
"personalni",
|
|
||||||
"skola"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_skola",
|
|
||||||
"personalni",
|
|
||||||
"skola"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_hlasovani",
|
|
||||||
"prednasky",
|
|
||||||
"hlasovani"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_hlasovanioznalostech",
|
|
||||||
"prednasky",
|
|
||||||
"hlasovanioznalostech"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_prednaska",
|
|
||||||
"prednasky",
|
|
||||||
"prednaska"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_prednaska",
|
|
||||||
"prednasky",
|
|
||||||
"prednaska"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_prednaska",
|
|
||||||
"prednasky",
|
|
||||||
"prednaska"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_prednaska",
|
|
||||||
"prednasky",
|
|
||||||
"prednaska"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_seznam",
|
|
||||||
"prednasky",
|
|
||||||
"seznam"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_seznam",
|
|
||||||
"prednasky",
|
|
||||||
"seznam"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_seznam",
|
|
||||||
"prednasky",
|
|
||||||
"seznam"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_seznam",
|
|
||||||
"prednasky",
|
|
||||||
"seznam"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_znalost",
|
|
||||||
"prednasky",
|
|
||||||
"znalost"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_znalost",
|
|
||||||
"prednasky",
|
|
||||||
"znalost"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_znalost",
|
|
||||||
"prednasky",
|
|
||||||
"znalost"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_znalost",
|
|
||||||
"prednasky",
|
|
||||||
"znalost"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_konfera",
|
|
||||||
"soustredeni",
|
|
||||||
"konfera"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_konfera",
|
|
||||||
"soustredeni",
|
|
||||||
"konfera"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_konfera",
|
|
||||||
"soustredeni",
|
|
||||||
"konfera"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_konfera",
|
|
||||||
"soustredeni",
|
|
||||||
"konfera"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_konfery_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"konfery_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_konfery_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"konfery_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_konfery_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"konfery_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_konfery_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"konfery_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_soustredeni",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_soustredeni",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_soustredeni",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_soustredeni",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_soustredeni_organizatori",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_organizatori"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_soustredeni_organizatori",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_organizatori"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_soustredeni_organizatori",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_organizatori"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_soustredeni_organizatori",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_organizatori"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_soustredeni_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_soustredeni_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_soustredeni_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_soustredeni_ucastnici",
|
|
||||||
"soustredeni",
|
|
||||||
"soustredeni_ucastnici"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_tag",
|
|
||||||
"taggit",
|
|
||||||
"tag"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_tag",
|
|
||||||
"taggit",
|
|
||||||
"tag"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_tag",
|
|
||||||
"taggit",
|
|
||||||
"tag"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_tag",
|
|
||||||
"taggit",
|
|
||||||
"tag"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_taggeditem",
|
|
||||||
"taggit",
|
|
||||||
"taggeditem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_taggeditem",
|
|
||||||
"taggit",
|
|
||||||
"taggeditem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_taggeditem",
|
|
||||||
"taggit",
|
|
||||||
"taggeditem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_taggeditem",
|
|
||||||
"taggit",
|
|
||||||
"taggeditem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_cislo",
|
|
||||||
"tvorba",
|
|
||||||
"cislo"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_cislo",
|
|
||||||
"tvorba",
|
|
||||||
"cislo"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_cislo",
|
|
||||||
"tvorba",
|
|
||||||
"cislo"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_cislo",
|
|
||||||
"tvorba",
|
|
||||||
"cislo"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_clanek",
|
|
||||||
"tvorba",
|
|
||||||
"clanek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_clanek",
|
|
||||||
"tvorba",
|
|
||||||
"clanek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_clanek",
|
|
||||||
"tvorba",
|
|
||||||
"clanek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_clanek",
|
|
||||||
"tvorba",
|
|
||||||
"clanek"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_deadline",
|
|
||||||
"tvorba",
|
|
||||||
"deadline"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_deadline",
|
|
||||||
"tvorba",
|
|
||||||
"deadline"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_deadline",
|
|
||||||
"tvorba",
|
|
||||||
"deadline"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_pohadka",
|
|
||||||
"tvorba",
|
|
||||||
"pohadka"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_pohadka",
|
|
||||||
"tvorba",
|
|
||||||
"pohadka"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_pohadka",
|
|
||||||
"tvorba",
|
|
||||||
"pohadka"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_pohadka",
|
|
||||||
"tvorba",
|
|
||||||
"pohadka"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_problem",
|
|
||||||
"tvorba",
|
|
||||||
"problem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_problem",
|
|
||||||
"tvorba",
|
|
||||||
"problem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_problem",
|
|
||||||
"tvorba",
|
|
||||||
"problem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_problem",
|
|
||||||
"tvorba",
|
|
||||||
"problem"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_rocnik",
|
|
||||||
"tvorba",
|
|
||||||
"rocnik"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_rocnik",
|
|
||||||
"tvorba",
|
|
||||||
"rocnik"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_rocnik",
|
|
||||||
"tvorba",
|
|
||||||
"rocnik"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_rocnik",
|
|
||||||
"tvorba",
|
|
||||||
"rocnik"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_tema",
|
|
||||||
"tvorba",
|
|
||||||
"tema"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_tema",
|
|
||||||
"tvorba",
|
|
||||||
"tema"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_tema",
|
|
||||||
"tvorba",
|
|
||||||
"tema"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_tema",
|
|
||||||
"tvorba",
|
|
||||||
"tema"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_uloha",
|
|
||||||
"tvorba",
|
|
||||||
"uloha"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_uloha",
|
|
||||||
"tvorba",
|
|
||||||
"uloha"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_uloha",
|
|
||||||
"tvorba",
|
|
||||||
"uloha"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_uloha",
|
|
||||||
"tvorba",
|
|
||||||
"uloha"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"add_nastaveni",
|
|
||||||
"various",
|
|
||||||
"nastaveni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"change_nastaveni",
|
|
||||||
"various",
|
|
||||||
"nastaveni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"delete_nastaveni",
|
|
||||||
"various",
|
|
||||||
"nastaveni"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"view_nastaveni",
|
|
||||||
"various",
|
|
||||||
"nastaveni"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"model": "auth.group",
|
|
||||||
"pk": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fields": {
|
|
||||||
"name": "resitel",
|
|
||||||
"permissions": [
|
|
||||||
[
|
|
||||||
"resitel",
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"model": "auth.group",
|
|
||||||
"pk": 2
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -73,7 +73,7 @@
|
||||||
"sort_order": 3,
|
"sort_order": 3,
|
||||||
"title": "Aktuální<br/> ročník",
|
"title": "Aktuální<br/> ročník",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_aktualni_zadani",
|
"url": "seminar_aktualni_zadani",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
"sort_order": 5,
|
"sort_order": 5,
|
||||||
"title": "Archiv",
|
"title": "Archiv",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_archiv_rocniky",
|
"url": "seminar_archiv_rocniky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -289,7 +289,7 @@
|
||||||
"sort_order": 43,
|
"sort_order": 43,
|
||||||
"title": "Výsledková listina",
|
"title": "Výsledková listina",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_aktualni_vysledky",
|
"url": "seminar_aktualni_vysledky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -361,7 +361,7 @@
|
||||||
"sort_order": 20,
|
"sort_order": 20,
|
||||||
"title": "Proběhlo",
|
"title": "Proběhlo",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "soustredeni_seznam",
|
"url": "seminar_seznam_soustredeni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -409,7 +409,7 @@
|
||||||
"sort_order": 23,
|
"sort_order": 23,
|
||||||
"title": "Osobní údaje",
|
"title": "Osobní údaje",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "personalni_resitel_edit",
|
"url": "seminar_resitel_edit",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -437,9 +437,9 @@
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 21,
|
"parent": 21,
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Nahrát řešení",
|
"title": "Poslat řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "odevzdavatko_nahraj_reseni",
|
"url": "seminar_nahraj_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -463,7 +463,7 @@
|
||||||
"sort_order": 35,
|
"sort_order": 35,
|
||||||
"title": "Témata",
|
"title": "Témata",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_archiv_temata",
|
"url": "seminar_archiv_temata",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -476,9 +476,9 @@
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [
|
||||||
[
|
[
|
||||||
"org",
|
"change_hodnoceni",
|
||||||
"auth",
|
"seminar",
|
||||||
"user"
|
"hodnoceni"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
|
@ -589,7 +589,7 @@
|
||||||
"sort_order": 15,
|
"sort_order": 15,
|
||||||
"title": "Aktuální číslo",
|
"title": "Aktuální číslo",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_aktualni_zadani",
|
"url": "seminar_aktualni_zadani",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -613,7 +613,7 @@
|
||||||
"sort_order": 24,
|
"sort_order": 24,
|
||||||
"title": "Čísla",
|
"title": "Čísla",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_archiv_rocniky",
|
"url": "seminar_archiv_rocniky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -719,9 +719,9 @@
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 21,
|
"parent": 21,
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Vložit řešení",
|
"title": "Nahrát řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "odevzdavatko_vloz_reseni",
|
"url": "seminar_vloz_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -804,7 +804,7 @@
|
||||||
"sort_order": 37,
|
"sort_order": 37,
|
||||||
"title": "Moje řešení",
|
"title": "Moje řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "odevzdavatko_resitel_odevzdana_reseni",
|
"url": "seminar_resitel_odevzdana_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -828,7 +828,7 @@
|
||||||
"sort_order": 33,
|
"sort_order": 33,
|
||||||
"title": "Aktuální ročník",
|
"title": "Aktuální ročník",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_aktualni_rocnik",
|
"url": "seminar_aktualni_rocnik",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -900,7 +900,7 @@
|
||||||
"sort_order": 46,
|
"sort_order": 46,
|
||||||
"title": "Ročník {{rocnik.rocnik}}",
|
"title": "Ročník {{rocnik.rocnik}}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_rocnik rocnik.rocnik",
|
"url": "seminar_rocnik rocnik.rocnik",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -924,7 +924,7 @@
|
||||||
"sort_order": 47,
|
"sort_order": 47,
|
||||||
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "tvorba_cislo cislo.rocnik.rocnik cislo.poradi",
|
"url": "seminar_cislo cislo.rocnik.rocnik cislo.poradi",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -1007,18 +1007,7 @@
|
||||||
"access_guest": false,
|
"access_guest": false,
|
||||||
"access_loggedin": false,
|
"access_loggedin": false,
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [],
|
||||||
[
|
|
||||||
"org",
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"resitel",
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"description": "",
|
"description": "",
|
||||||
|
@ -1036,83 +1025,5 @@
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
"pk": 51
|
"pk": 51
|
||||||
},
|
|
||||||
{
|
|
||||||
"fields": {
|
|
||||||
"access_guest": false,
|
|
||||||
"access_loggedin": false,
|
|
||||||
"access_perm_type": 1,
|
|
||||||
"access_permissions": [
|
|
||||||
[
|
|
||||||
"resitel",
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"access_restricted": true,
|
|
||||||
"alias": null,
|
|
||||||
"description": "",
|
|
||||||
"hidden": false,
|
|
||||||
"hint": "",
|
|
||||||
"inbreadcrumbs": true,
|
|
||||||
"inmenu": true,
|
|
||||||
"insitetree": true,
|
|
||||||
"parent": 23,
|
|
||||||
"sort_order": 52,
|
|
||||||
"title": "Nahrát řešení k nadproblému {{nadproblem_id}}",
|
|
||||||
"tree": 1,
|
|
||||||
"url": "odevzdavatko_nahraj_reseni nadproblem_id",
|
|
||||||
"urlaspattern": true
|
|
||||||
},
|
|
||||||
"model": "sitetree.treeitem",
|
|
||||||
"pk": 52
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fields": {
|
|
||||||
"access_guest": false,
|
|
||||||
"access_loggedin": false,
|
|
||||||
"access_perm_type": 1,
|
|
||||||
"access_permissions": [],
|
|
||||||
"access_restricted": false,
|
|
||||||
"alias": null,
|
|
||||||
"description": "",
|
|
||||||
"hidden": false,
|
|
||||||
"hint": "",
|
|
||||||
"inbreadcrumbs": true,
|
|
||||||
"inmenu": true,
|
|
||||||
"insitetree": true,
|
|
||||||
"parent": 28,
|
|
||||||
"sort_order": 53,
|
|
||||||
"title": "Přidat PDF",
|
|
||||||
"tree": 1,
|
|
||||||
"url": "/admin/korektury/korekturovanepdf/add/",
|
|
||||||
"urlaspattern": false
|
|
||||||
},
|
|
||||||
"model": "sitetree.treeitem",
|
|
||||||
"pk": 53
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fields": {
|
|
||||||
"access_guest": false,
|
|
||||||
"access_loggedin": false,
|
|
||||||
"access_perm_type": 1,
|
|
||||||
"access_permissions": [],
|
|
||||||
"access_restricted": false,
|
|
||||||
"alias": null,
|
|
||||||
"description": "",
|
|
||||||
"hidden": false,
|
|
||||||
"hint": "",
|
|
||||||
"inbreadcrumbs": true,
|
|
||||||
"inmenu": true,
|
|
||||||
"insitetree": true,
|
|
||||||
"parent": 20,
|
|
||||||
"sort_order": 54,
|
|
||||||
"title": "Export do abstraktů sousu {{ soustredeni.id }}",
|
|
||||||
"tree": 1,
|
|
||||||
"url": "soustredeni_abstrakty soustredeni.id",
|
|
||||||
"urlaspattern": true
|
|
||||||
},
|
|
||||||
"model": "sitetree.treeitem",
|
|
||||||
"pk": 54
|
|
||||||
}
|
}
|
||||||
]
|
]
|
637
deploy_v2/admin_org_prava.json
Normal file
637
deploy_v2/admin_org_prava.json
Normal file
|
@ -0,0 +1,637 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"codename": "org",
|
||||||
|
"ct_app_label": "auth",
|
||||||
|
"ct_model": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_flatpage",
|
||||||
|
"ct_app_label": "flatpages",
|
||||||
|
"ct_model": "flatpage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_flatpage",
|
||||||
|
"ct_app_label": "flatpages",
|
||||||
|
"ct_model": "flatpage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_flatpage",
|
||||||
|
"ct_app_label": "flatpages",
|
||||||
|
"ct_model": "flatpage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_flatpage",
|
||||||
|
"ct_app_label": "flatpages",
|
||||||
|
"ct_model": "flatpage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_galerie",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "galerie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_galerie",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "galerie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_galerie",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "galerie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_galerie",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "galerie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_obrazek",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "obrazek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_obrazek",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "obrazek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_obrazek",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "obrazek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_obrazek",
|
||||||
|
"ct_app_label": "galerie",
|
||||||
|
"ct_model": "obrazek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_komentar",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "komentar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_komentar",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "komentar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_komentar",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "komentar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_komentar",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "komentar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_korekturovanepdf",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "korekturovanepdf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_korekturovanepdf",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "korekturovanepdf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_korekturovanepdf",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "korekturovanepdf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_korekturovanepdf",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "korekturovanepdf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_oprava",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "oprava"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_oprava",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "oprava"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_oprava",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "oprava"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_oprava",
|
||||||
|
"ct_app_label": "korektury",
|
||||||
|
"ct_model": "oprava"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_hlasovani",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "hlasovani"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_hlasovani",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "hlasovani"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_hlasovani",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "hlasovani"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_hlasovani",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "hlasovani"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_prednaska",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "prednaska"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_prednaska",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "prednaska"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_prednaska",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "prednaska"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_prednaska",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "prednaska"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_seznam",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "seznam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_seznam",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "seznam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_seznam",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "seznam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_seznam",
|
||||||
|
"ct_app_label": "prednasky",
|
||||||
|
"ct_model": "seznam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_cislo",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "cislo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_cislo",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "cislo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_cislo",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "cislo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_cislo",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "cislo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_clanek",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "clanek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_clanek",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "clanek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_clanek",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "clanek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_clanek",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "clanek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_konfera",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfera"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_konfera",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfera"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_konfera",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfera"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_konfera",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfera"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_konfery_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfery_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_konfery_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfery_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_konfery_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfery_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_konfery_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "konfery_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_nastaveni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "nastaveni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_nastaveni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "nastaveni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_nastaveni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "nastaveni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_nastaveni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "nastaveni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_novinky",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "novinky"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_novinky",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "novinky"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_novinky",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "novinky"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_novinky",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "novinky"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_organizator",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "organizator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_organizator",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "organizator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_organizator",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "organizator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_organizator",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "organizator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_osoba",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "osoba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_osoba",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "osoba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_osoba",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "osoba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_osoba",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "osoba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_pohadka",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "pohadka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_pohadka",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "pohadka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_pohadka",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "pohadka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_pohadka",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "pohadka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_prijemce",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "prijemce"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_prijemce",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "prijemce"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_prijemce",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "prijemce"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_prijemce",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "prijemce"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_problem",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "problem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_problem",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "problem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_problem",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "problem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_problem",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "problem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_resitel",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "resitel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_resitel",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "resitel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_resitel",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "resitel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_resitel",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "resitel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_rocnik",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "rocnik"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_rocnik",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "rocnik"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_rocnik",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "rocnik"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_rocnik",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "rocnik"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_skola",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "skola"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_skola",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "skola"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_skola",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "skola"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_skola",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "skola"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_soustredeni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_soustredeni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_soustredeni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_soustredeni",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_soustredeni_organizatori",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_organizatori"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_soustredeni_organizatori",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_organizatori"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_soustredeni_organizatori",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_organizatori"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_soustredeni_organizatori",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_organizatori"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_soustredeni_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_soustredeni_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_soustredeni_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_soustredeni_ucastnici",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "soustredeni_ucastnici"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_tema",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "tema"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_tema",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "tema"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_tema",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "tema"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_tema",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "tema"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_uloha",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "uloha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_uloha",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "uloha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_uloha",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "uloha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_uloha",
|
||||||
|
"ct_app_label": "seminar",
|
||||||
|
"ct_model": "uloha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_tag",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "tag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_tag",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "tag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_tag",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "tag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_tag",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "tag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_taggeditem",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "taggeditem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_taggeditem",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "taggeditem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "delete_taggeditem",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "taggeditem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_taggeditem",
|
||||||
|
"ct_app_label": "taggit",
|
||||||
|
"ct_model": "taggeditem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_fotkaheader",
|
||||||
|
"ct_app_label": "header_fotky",
|
||||||
|
"ct_model": "fotkaheader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_fotkaheader",
|
||||||
|
"ct_app_label": "header_fotky",
|
||||||
|
"ct_model": "fotkaheader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_fotkaheader",
|
||||||
|
"ct_app_label": "header_fotky",
|
||||||
|
"ct_model": "fotkaheader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "add_fotkaurlvazba",
|
||||||
|
"ct_app_label": "header_fotky",
|
||||||
|
"ct_model": "fotkaurlvazba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "change_fotkaurlvazba",
|
||||||
|
"ct_app_label": "header_fotky",
|
||||||
|
"ct_model": "fotkaurlvazba"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"codename": "view_fotkaurlvazba",
|
||||||
|
"ct_app_label": "header_fotky",
|
||||||
|
"ct_model": "fotkaurlvazba"
|
||||||
|
}
|
||||||
|
]
|
|
@ -13,6 +13,7 @@ make install_venv
|
||||||
make install
|
make install
|
||||||
deploy_v2/pre_migration.py
|
deploy_v2/pre_migration.py
|
||||||
make deploy_test
|
make deploy_test
|
||||||
|
./manage.py load_org_permissions admin_org_prava.json
|
||||||
./manage.py loaddata data/*
|
./manage.py loaddata data/*
|
||||||
systemctl --user start mamweb-test.service
|
systemctl --user start mamweb-test.service
|
||||||
./manage.py generate_thumbnails
|
./manage.py generate_thumbnails
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Minimal makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line, and also
|
|
||||||
# from the environment for the first two.
|
|
||||||
SPHINXOPTS ?=
|
|
||||||
SPHINXBUILD ?= sphinx-build
|
|
||||||
SOURCEDIR = .
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
|
||||||
help:
|
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
||||||
|
|
||||||
.PHONY: help Makefile
|
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
||||||
%: Makefile
|
|
||||||
sphinx-apidoc --module-first -o modules .. ../*/migrations --templatedir _templates -f
|
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
8
docs/_templates/module.rst_t
vendored
8
docs/_templates/module.rst_t
vendored
|
@ -1,8 +0,0 @@
|
||||||
{%- if show_headings %}
|
|
||||||
{{- [basename, ".py"] | join('') | e | heading }}
|
|
||||||
|
|
||||||
{% endif -%}
|
|
||||||
.. automodule:: {{ qualname }}
|
|
||||||
{%- for option in automodule_options %}
|
|
||||||
:{{ option }}:
|
|
||||||
{%- endfor %}
|
|
57
docs/_templates/package.rst_t
vendored
57
docs/_templates/package.rst_t
vendored
|
@ -1,57 +0,0 @@
|
||||||
{%- macro automodule(modname, options) -%}
|
|
||||||
.. automodule:: {{ modname }}
|
|
||||||
{%- for option in options %}
|
|
||||||
:{{ option }}:
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endmacro %}
|
|
||||||
|
|
||||||
{%- macro toctree(docnames) -%}
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: {{ maxdepth }}
|
|
||||||
{% for docname in docnames %}
|
|
||||||
{{ docname }}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endmacro %}
|
|
||||||
|
|
||||||
{%- if is_namespace %}
|
|
||||||
{{- pkgname | e | heading }}
|
|
||||||
{% else %}
|
|
||||||
{{- pkgname | e | heading }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{%- if is_namespace %}
|
|
||||||
.. py:module:: {{ pkgname }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{%- if modulefirst and not is_namespace %}
|
|
||||||
{{ automodule(pkgname, automodule_options) }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{%- if subpackages %}
|
|
||||||
{# Subpackages #}
|
|
||||||
{# ----------- #}
|
|
||||||
|
|
||||||
{{ toctree(subpackages) }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{%- if submodules %}
|
|
||||||
{# Submodules #}
|
|
||||||
{# ---------- #}
|
|
||||||
{% if separatemodules %}
|
|
||||||
{{ toctree(submodules) }}
|
|
||||||
{% else %}
|
|
||||||
{%- for submodule in submodules %}
|
|
||||||
{% if show_headings %}
|
|
||||||
{{- submodule | e | heading(2) }}
|
|
||||||
{% endif %}
|
|
||||||
{{ automodule(submodule, automodule_options) }}
|
|
||||||
{% endfor %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
{%- if not modulefirst and not is_namespace %}
|
|
||||||
Module contents
|
|
||||||
---------------
|
|
||||||
|
|
||||||
{{ automodule(pkgname, automodule_options) }}
|
|
||||||
{% endif %}
|
|
7
docs/_templates/toc.rst_t
vendored
7
docs/_templates/toc.rst_t
vendored
|
@ -1,7 +0,0 @@
|
||||||
{{ "Seznam aplikací" | heading }}
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: {{ maxdepth }}
|
|
||||||
{% for docname in docnames %}
|
|
||||||
{{ docname }}
|
|
||||||
{%- endfor %}
|
|
|
@ -1,5 +0,0 @@
|
||||||
Aprílové nápad
|
|
||||||
==============
|
|
||||||
|
|
||||||
* aprílový easter-egg pro řešitele - vytvořit nějakou vtipnou testovací databázi a nasadit ji místo produkce
|
|
||||||
* změnit veškerý text na oranžovo
|
|
103
docs/conf.py
103
docs/conf.py
|
@ -1,103 +0,0 @@
|
||||||
# Configuration file for the Sphinx documentation builder.
|
|
||||||
#
|
|
||||||
# This file only contains a selection of the most common options. For a full
|
|
||||||
# list see the documentation:
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
||||||
|
|
||||||
# -- Path setup --------------------------------------------------------------
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import django
|
|
||||||
from django.utils.version import get_docs_version
|
|
||||||
sys.path.insert(0, os.path.abspath('..'))
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'mamweb.settings'
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
|
||||||
|
|
||||||
project = 'Web M&M'
|
|
||||||
copyright = '2022, Orgové'
|
|
||||||
author = 'Orgové'
|
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
||||||
# ones.
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.autodoc',
|
|
||||||
'sphinx.ext.viewcode',
|
|
||||||
'sphinx.ext.intersphinx',
|
|
||||||
'sphinx.ext.autosectionlabel',
|
|
||||||
'myst_parser',
|
|
||||||
'sphinxcontrib_django',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#
|
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
|
||||||
# Usually you set "language" from the command line for these cases.
|
|
||||||
language = 'cs'
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
# This pattern also affects html_static_path and html_extra_path.
|
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
#
|
|
||||||
import sphinx_rtd_theme
|
|
||||||
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
|
||||||
|
|
||||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# Provázání s jinými dokumentacemi
|
|
||||||
intersphinx_mapping = {'python': ('https://docs.python.org/3', None),
|
|
||||||
'django': (f'http://docs.djangoproject.com/en/{get_docs_version()}/',
|
|
||||||
f'http://docs.djangoproject.com/en/{get_docs_version()}/_objects/'),}
|
|
||||||
|
|
||||||
# Generování tříd/funkcí/atributů v pořádí jak jsou naprogramované
|
|
||||||
autodoc_member_order = "bysource"
|
|
||||||
|
|
||||||
# Nezobrazování zděděné (ze super tříd) dokumentace TODO nefunguje?
|
|
||||||
autodoc_inherit_docstrings = False
|
|
||||||
|
|
||||||
source_suffix = {
|
|
||||||
'.rst': 'restructuredtext',
|
|
||||||
'.md': 'markdown',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Autodoc má ignorovat některé moduly
|
|
||||||
# Ref: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#event-autodoc-skip-member
|
|
||||||
# Kudos: https://stackoverflow.com/a/21449475/
|
|
||||||
def ignorovat(app, what, name, obj, skip, options):
|
|
||||||
blacklist = (
|
|
||||||
# typ (what), name
|
|
||||||
('module', 'settings.mamweb_prod'),
|
|
||||||
)
|
|
||||||
ignore = (what, name) in blacklist
|
|
||||||
return True if ignore else None
|
|
||||||
|
|
||||||
def setup(app):
|
|
||||||
app.connect('autodoc-skip-member', ignorovat)
|
|
27
docs/css.rst
27
docs/css.rst
|
@ -1,27 +0,0 @@
|
||||||
CSS (a další styly na webu)
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Inspirován `css-trick článkem <https://css-tricks.com/methods-organize-css/>`_ jsem se rozhodl rozdělit
|
|
||||||
CSSka do
|
|
||||||
|
|
||||||
- Konstant (``constants.css``), které jsou využívány na mnoha místech CSSek
|
|
||||||
- Nastylování html tagů (``base.css``)
|
|
||||||
- Layoutu (``layout.css``), což je to, co určuje celkové rozložení stránky
|
|
||||||
- Jednotlivých prvků (``modules.css``)
|
|
||||||
|
|
||||||
Dále jsem separoval CSSka pro **galerii** (potřebuje hodně specifických stylů). Stejně tak **korekturovátko** má styly separátně.
|
|
||||||
|
|
||||||
Dále web (asi) používá externí frameworky (v separátních složkách – mají k sobě i JS a podobné věci):
|
|
||||||
|
|
||||||
- bootstrap: dělá nějaké basic stylování, *web je na něm hodně závislý* (například jsem zjistil, že bootstrap kdysi přidával ``font-size:14px``, bez čehož se web úplně rozpadnul) (také na něm běží mobilní meníčko, které navíc vyžaduje Popper, tedy bootstrap.bundle.js místo bootstrap.js)
|
|
||||||
|
|
||||||
Pak jsou tu ``mamweb-dev.css`` a ``printtable.css``, co jsem si ještě nerozmyslel, co s tím.
|
|
||||||
|
|
||||||
Pár myšlenek
|
|
||||||
------------
|
|
||||||
|
|
||||||
- Až na pár výjimek (galerii a korekturovátko) bych styly držel v jedné složce a málo souborech,
|
|
||||||
protože CSS šíleně dědí všechno možné
|
|
||||||
- Chce to dobře pojmenovávat třídy (speciálně aby bylo vidět, co ta třída dělá nebo kde se používá)
|
|
||||||
- Chce to hodně komentovat kód (speciálně tam, kde není splněn předchozí bod)
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
Další soubory/složky v kořenovém adresáři
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
media
|
|
||||||
-----
|
|
||||||
Složka, kam django nahrává soubory „jako by je nahrávalo do databáze“.
|
|
||||||
|
|
||||||
static
|
|
||||||
------
|
|
||||||
Složka, kam django nakopíruje všechno ze složek static a pak na to z templatů / kódu jde ukazovat pomocí ``static``.
|
|
||||||
|
|
||||||
data
|
|
||||||
----
|
|
||||||
Obsahuje data, která patří do databáze, ale jsou přímo součástí webu jako
|
|
||||||
takového. Aktuálně jsou to statické stránky, meníčko a rozložení obrázků
|
|
||||||
v pozadí meníčka.
|
|
||||||
|
|
||||||
Generuje se za pomocí::
|
|
||||||
|
|
||||||
./manage.py dumpdata flatpages > data/flat_new.json
|
|
||||||
./fix_json.py data/flat_new.json data/flat.json
|
|
||||||
|
|
||||||
nebo (v případě meníčka)::
|
|
||||||
|
|
||||||
./manage.py dumpdata sitetree --natural-foreign > data/sitetree_new.json
|
|
||||||
./fix_json.py data/sitetree_new.json data/sitetree.json
|
|
||||||
|
|
||||||
deploy_v2
|
|
||||||
---------
|
|
||||||
Věci, které byly potřeba při nasazování nového (2021) webu.
|
|
||||||
|
|
||||||
docs
|
|
||||||
----
|
|
||||||
Zde je dokumentace webu. Viz :ref:`Sphinx na našem webu`.
|
|
||||||
|
|
||||||
setup
|
|
||||||
-----
|
|
||||||
Tato složka obsahuje různé konfiguráky potřebné k rozběhnutí webu na serveru.
|
|
||||||
|
|
||||||
vue_frontend
|
|
||||||
------------
|
|
||||||
Obsahuje první pokusy o editory treenodů ve vue.
|
|
||||||
|
|
||||||
.gitignore
|
|
||||||
----------
|
|
||||||
Klasické `.gitignore`_
|
|
||||||
|
|
||||||
.. _.gitignore: https://git-scm.com/docs/gitignore
|
|
||||||
|
|
||||||
checklinks.sh
|
|
||||||
-------------
|
|
||||||
„Týrací“ skript na kontrolu, že nic, kam se lze proklikat na webu, nehází chybu.
|
|
||||||
|
|
||||||
constraints.txt
|
|
||||||
---------------
|
|
||||||
Obsahuje omezení na :ref:`requirements.txt`.
|
|
||||||
|
|
||||||
convert_spaces_to_tabs.sh
|
|
||||||
-------------------------
|
|
||||||
Skript na změnu odsazování.
|
|
||||||
|
|
||||||
db-local.sqlite3
|
|
||||||
----------------
|
|
||||||
Lokální databáze (na serveru není).
|
|
||||||
|
|
||||||
diff_db_backup.sh
|
|
||||||
-----------------
|
|
||||||
Nevím. Typoval bych skript na diff záloh (resp. dumpů) databáze.
|
|
||||||
|
|
||||||
Makefile
|
|
||||||
--------
|
|
||||||
Klasické `Makefile`_. Obsahuje například vytvoření virtual_env, instalaci a nasazování webu.
|
|
||||||
|
|
||||||
.. _Makefile: https://www.gnu.org/software/make/manual/make.html
|
|
||||||
|
|
||||||
manage.py
|
|
||||||
---------
|
|
||||||
Základní soubor djanga.
|
|
||||||
|
|
||||||
README.md
|
|
||||||
---------
|
|
||||||
Většina je spíš zbytek po bývalých webařích.
|
|
||||||
|
|
||||||
requirements.txt
|
|
||||||
----------------
|
|
||||||
Seznam balíčků, které jsou potřeba pro běh mamwebu. (Cílem je vytvoření virtualenvu se všemi těmito balíčky, např. pomocí daného příkazu v :ref:`Makefile`.)
|
|
|
@ -1,55 +0,0 @@
|
||||||
Defaultní dokumentace speciálních souborů
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
Drobná nápověda k běžným django souborům. (Do nich jsem to vkládal copy-paste.)
|
|
||||||
|
|
||||||
admin.py
|
|
||||||
--------
|
|
||||||
Soubor sloužící k definici toho, co bude v adminu. Většinou pouhým zavoláním
|
|
||||||
funkce :func:`django.contrib.admin.site.register`, v případě, že chceme něco
|
|
||||||
upravit, tak jako třída rozšiřující :class:`django.contrib.admin.ModelAdmin`
|
|
||||||
s dekorátorem :func:`django.contrib.admin.register`.
|
|
||||||
|
|
||||||
Zde se definuje admin pro:
|
|
||||||
|
|
||||||
apps.py
|
|
||||||
-------
|
|
||||||
Soubor sloužící k pojmenování a jiným nastavením djangovské aplikace.
|
|
||||||
|
|
||||||
forms.py
|
|
||||||
--------
|
|
||||||
Formuláře (:class:`django.forms.Form`) umožňují jednoduchou tvorbu formulářů,
|
|
||||||
které lze pak jednoduše dát do frontendu i zpracovat na backendu.
|
|
||||||
|
|
||||||
Pro přidání políčka do formuláře je potřeba
|
|
||||||
- mít v modelu tu položku, kterou chci upravovat
|
|
||||||
- přidat do views (prihlaskaView, resitelEditView)
|
|
||||||
- přidat do forms
|
|
||||||
- includovat do html
|
|
||||||
|
|
||||||
models.py
|
|
||||||
---------
|
|
||||||
Tento soubor slouží k definici databázového modelu.
|
|
||||||
|
|
||||||
Třídy rozšiřují většinou :class:`django.db.models.Model` a jejich atributy jsou
|
|
||||||
většinou sloupce v databázi (tj. nastaví se na hodnotu něčeho z :mod:`django.db.models`).
|
|
||||||
Na výběr jsou:
|
|
||||||
|
|
||||||
- :class:`django.db.models.TextField`
|
|
||||||
- :class:`django.db.models.ForeignKey`
|
|
||||||
- :class:`django.db.models.DateField`
|
|
||||||
- :class:`django.db.models.DateTimeField`
|
|
||||||
- :class:`django.db.models.ImageField`
|
|
||||||
- :class:`django.db.models.CharField`
|
|
||||||
|
|
||||||
testutils.py
|
|
||||||
------------
|
|
||||||
Soubor sloužící ke generování testdat.
|
|
||||||
|
|
||||||
urls.py
|
|
||||||
-------
|
|
||||||
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují:
|
|
||||||
|
|
||||||
views.py
|
|
||||||
--------
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
.. Web M&M documentation master file, created by
|
|
||||||
sphinx-quickstart on Mon Jan 31 21:56:04 2022.
|
|
||||||
You can adapt this file completely to your liking, but it should at least
|
|
||||||
contain the root `toctree` directive.
|
|
||||||
|
|
||||||
Vítejte v dokumentaci M&Mího webu!
|
|
||||||
===================================
|
|
||||||
|
|
||||||
Tzv. produkce (tedy to, co vidí uživatelé) běží na `<mam.mff.cuni.cz>`_ (resp.
|
|
||||||
`<mam.matfyz.cz>`_), menu, obrázky v pozadí menu a spousta stránek (ty pouze se
|
|
||||||
statickým textem/obrázky) se mění přímo na produkci. Testovací verze běží na
|
|
||||||
`<https://mam-test.ks.matfyz.cz/>`_.
|
|
||||||
|
|
||||||
Abychom uměli web vyvíjet, musíme ho většinou nejdřív umět
|
|
||||||
:doc:`naklonovat a spustit lokálně <vyvoj>`.
|
|
||||||
|
|
||||||
:doc:`struktura mamwebu <struktura>` se řídí hlavně djangem, ale snažíme se
|
|
||||||
také o oddělení jednotlivých částí do :doc:`samostatných aplikací
|
|
||||||
<modules/modules>`.
|
|
||||||
|
|
||||||
Dokumentace (jak v ``docs/``, tak přímo v kódu) je psaná ve
|
|
||||||
:doc:`sphinxu <sphinx>`.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:caption: M&M web
|
|
||||||
:maxdepth: 2
|
|
||||||
:titlesonly:
|
|
||||||
|
|
||||||
vyvoj
|
|
||||||
zavislosti
|
|
||||||
sphinx
|
|
||||||
skripty
|
|
||||||
zkratky
|
|
||||||
modules/modules
|
|
||||||
dalsi_soubory
|
|
||||||
zapisy/zapisy
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Rejstříky a vyhledávání
|
|
||||||
==================
|
|
||||||
|
|
||||||
* :ref:`genindex`
|
|
||||||
* :ref:`modindex`
|
|
||||||
* :ref:`search`
|
|
108
docs/skripty.rst
108
docs/skripty.rst
|
@ -1,108 +0,0 @@
|
||||||
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
|
|
||||||
``<aplikace>/management/commands/``, případně vestavěné, a volají se pomocí
|
|
||||||
``./manage.py <příkaz>``. 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/<příkaz>``.
|
|
||||||
|
|
||||||
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ě.
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
<skript>``, 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 <složka>``
|
|
||||||
Otestuje, že skript běží z konkrétní složky. Zejména použitelné s ``gimli_only`` a ``$TESTWEB``
|
|
||||||
``safe_checkout_branch <větev>``
|
|
||||||
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 <https://mam-test.ks.matfyz.cz/docs>`_.
|
|
||||||
``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``.
|
|
|
@ -1,41 +0,0 @@
|
||||||
Sphinx na našem webu
|
|
||||||
====================
|
|
||||||
|
|
||||||
Dokumentace se zkompiluje příkazem ``make html`` ve složce ``docs``. (Musíte mít zapnutý virtualenv)
|
|
||||||
|
|
||||||
Složka ``modules`` je automaticiky generována a přegenerovávána. (**Nic v ní neupravovat!**)
|
|
||||||
Jinak všechny rst, co jsou ve složce ``docs`` a jejích podsložkách nezačínajících podtržítkem, budou v dokumentaci a to je přesně to, co editovat pro změnu dokumentace (kromě dokumentace přímo v Pythonu).
|
|
||||||
|
|
||||||
Sphinx se píše v rst: `Návod na syntaxi rst`_ `Cheat sheet`_
|
|
||||||
|
|
||||||
Pokud něco chcete protlačit do bočního meníčka, je potřeba to připsat do souboru ``docs/index.rst`` (Zatím není úplně konsensus nad tím, co tam má a nemá být, takže pokud si nejste jistí, cpěte tam *všechno* ☺)
|
|
||||||
|
|
||||||
To je snad vše, co je potřeba vědět k dokumentaci mamwebu. Následující sekce jsou o tom, co jsem provedl Sphinxu, aby to fungovalo:
|
|
||||||
|
|
||||||
.. _Návod na syntaxi rst: https://sphinx-tutorial.readthedocs.io/step-1/#sections
|
|
||||||
.. _Cheat sheet: https://sphinx-tutorial.readthedocs.io/cheatsheet/
|
|
||||||
|
|
||||||
make html
|
|
||||||
---------
|
|
||||||
``make html`` dělá následující: Vygenerují se rst soubory do modules z pythoní dokumentace pomocí::
|
|
||||||
|
|
||||||
sphinx-apidoc --module-first -o modules .. ../*/migrations --templatedir _templates -f
|
|
||||||
|
|
||||||
- ``--module-first`` říká, že dokumentace modulu má být dřív než to, co obsahuje,
|
|
||||||
- ``-o`` je výstupní složka příkazu,
|
|
||||||
- ``..`` prochází složku mamweb,
|
|
||||||
- ``../*/migrations`` ignoruje migrace
|
|
||||||
- ``--templatedir _templates`` určuje templaty, podle kterých se vyrábí rst z Pythoní dokumentace a struktury složek a souborů,
|
|
||||||
- ``-f`` donutí phinx znovu přegenerovat soubory, protože nepozná, že se nějaká dokumentace změnila)
|
|
||||||
|
|
||||||
Poté se spustí „samotný sphinx“ a vygenerují se soubory v ``_build/html``.
|
|
||||||
|
|
||||||
Templates
|
|
||||||
---------
|
|
||||||
Templaty jsou originální s pár změnami:
|
|
||||||
|
|
||||||
- Změnil jsem nadpisy
|
|
||||||
- Odstranil jsem některá slova v nadpisech (module, package, …)
|
|
||||||
- Odstranil jsem nadpis Subpackages
|
|
||||||
|
|
||||||
přišlo mi to takhle lepší. Ale stále nejsem moc spokojen, protože je to pořád nepřehledné.
|
|
|
@ -1,32 +0,0 @@
|
||||||
Co kde najít (mamweb + django)
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Nejdůležitější aplikace z pohledu djanga je ``mamweb``. Tu totiž django pouští
|
|
||||||
a obsahuje tedy nastavení (tam se přidávají ostatní aplikace, včetně těch
|
|
||||||
importovaných z djanga, a nastavují se tam různé věci jak v djangu, tak i naše,
|
|
||||||
například složky, kam se budou věci přidané uživateli ukládat). Dále obsahuje
|
|
||||||
základní urls, udávající, „na jaké adrese co je“. A nakonec obsahuje obecné
|
|
||||||
věci jako chybové hlášky a vzhled M&M stránek (menu, patička, atd.). Aktuálně
|
|
||||||
i veškeré csv.
|
|
||||||
|
|
||||||
Další jsou pak jednotlivé aplikace (pokud něco hledáte, tak zřejmě chcete najít
|
|
||||||
tu aplikaci, která tomu odpovídá, respektive se k ní dostat přes url).
|
|
||||||
|
|
||||||
**TLDR: Nevšímejte si složek data/ seminar/ a souborů přímo v kořenové složce.**
|
|
||||||
Kromě věcí potřebných ke gitu, :doc:`ke spuštění <vyvoj>` a fukci djanga,
|
|
||||||
dalších drobností, lokální databáze a již zmíněných aplikací jsou tu ``data``,
|
|
||||||
kde je takový ten obsah webu, co by se měl dát snadno měnit (tudíž musí být v
|
|
||||||
databázi), tj. statické stránky, menu a obrázky v pozadí menu. Ten je třeba
|
|
||||||
měnit hlavně na produkci a sekundárně tady (může to dělat i newebař a nechcete
|
|
||||||
přepsat jeho práci). Vše, co nejsou aplikace je popsáno :doc:`tady <dalsi_soubory>`.
|
|
||||||
|
|
||||||
Ještě je tu aplikace ``seminar/``, kde bylo původně skoro všechno, a tak nám
|
|
||||||
tam zbývá spoustu historických migrací (čehož se jen tak nezbavíme).
|
|
||||||
|
|
||||||
Základy djanga
|
|
||||||
--------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mamweb je psaný téměř čistě v djangu. Což znamená, že to „co je vidět na stránkách“
|
|
||||||
jsou views.
|
|
184
docs/vyvoj.rst
184
docs/vyvoj.rst
|
@ -1,184 +0,0 @@
|
||||||
Lokální vývoj mamwebu
|
|
||||||
=====================
|
|
||||||
|
|
||||||
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 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.)
|
|
||||||
|
|
||||||
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 <https://git-scm.com>`_
|
|
||||||
- `Python <https://python.org>`_
|
|
||||||
|
|
||||||
- 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``, protože jsou potřeba všechny db backendy)
|
|
||||||
- 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 <https://gitea.ks.matfyz.cz>`_, kde
|
|
||||||
bydlí gitový repozitář s kódem.
|
|
||||||
|
|
||||||
.. tip:: Potřebné balíčky v různých distribucích jsou sepsané v :ref:`tabulce
|
|
||||||
prerekvizit <Alternativní jména balíčků>`.
|
|
||||||
|
|
||||||
Doporučené
|
|
||||||
^^^^^^^^^^
|
|
||||||
|
|
||||||
- Python wheel (možná řeší problémy s potřebou ``-dev`` balíčků…)
|
|
||||||
- Editor / IDE podporující `Editorconfig <https://editorconfig.org/>`_
|
|
||||||
- Uživatelská zkušenost s `produkční verzí webu <https://mam.matfyz.cz>`_
|
|
||||||
- Účet v `Kanci <https://kanboard.ledoian.cz>`_
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
<https://gitea.ks.matfyz.cz/mam/mamweb>`_.) 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 `<http://127.0.0.1:8000>`_.
|
|
||||||
|
|
||||||
Časté problémy
|
|
||||||
^^^^^^
|
|
||||||
|
|
||||||
- ``make/install_web`` vypíše ``Error: pg_config executable not found.``:
|
|
||||||
Chybí ``libpq-dev``
|
|
||||||
- Chybová hláška obsahuje ``#include <Python.h>``: 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 :-)
|
|
||||||
|
|
||||||
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é, ostatní najdeš v :ref:`Skripty pro práci s repozitářem`.
|
|
||||||
|
|
||||||
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í
|
|
||||||
|
|
||||||
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 <soubor/y>`` nahraje data ze souborů do databáze
|
|
||||||
- ``./manage.py dumpdata <model>`` 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
|
|
||||||
<https://docs.djangoproject.com/en/3.2/ref/django-admin/#available-commands>`_
|
|
||||||
|
|
||||||
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: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 :-)
|
|
||||||
|
|
||||||
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, …)
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ Aktuálně: Jakýsi coding style zhruba existuje, není popsaný, šíří se li
|
||||||
- Nesmí být striktně vynucovaný
|
- Nesmí být striktně vynucovaný
|
||||||
- Musel by být hodně nastavitelný
|
- Musel by být hodně nastavitelný
|
||||||
- Nechceme mít kód plný `#NOQA: WTF42`
|
- Nechceme mít kód plný `#NOQA: WTF42`
|
||||||
- Nejspíš vždycky bude mít false positives (`tvorba.utils.roman_numerals`) i false negatives (`tvorba.models.Cislo.posli_cislo_mailem`)
|
- Nejspíš vždycky bude mít false positives (`seminar.utils.roman_numerals`) i false negatives (`seminar.models.tvorba.Cislo.posli_cislo_mailem`)
|
||||||
- Možná dobrý sluha, ale určitě špatný pán (also: špatná zkušenost ☺)
|
- Možná dobrý sluha, ale určitě špatný pán (also: špatná zkušenost ☺)
|
||||||
- __Důsledek:__ Hrozí, že těch falešných varování bude moc, čímž to ztratí smysl úplně
|
- __Důsledek:__ Hrozí, že těch falešných varování bude moc, čímž to ztratí smysl úplně
|
||||||
- Potenciálně by šlo aplikovat jen lokálně na změny?
|
- Potenciálně by šlo aplikovat jen lokálně na změny?
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
Zápisy
|
|
||||||
======
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:caption: Importy zápisů z Markdownu
|
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
2021-12-06-testovani_dokumentace_codereview
|
|
|
@ -1,97 +0,0 @@
|
||||||
Závislosti webu
|
|
||||||
@@@@@@@@@@@@@@@
|
|
||||||
|
|
||||||
Web ke svému běhu potřebuje různé další programy. Tahle stránka se snaží je pokrýt.
|
|
||||||
|
|
||||||
Stránka je koncipována jako odrážkový seznam balíčků pro Ubuntu s případnými
|
|
||||||
komentáři, na konci stránky jsou uvedena :ref:`jména balíčků <Alternativní jména
|
|
||||||
balíčků>` v různých dalších distribucích. (Seznam mj. cílí na lokální
|
|
||||||
rozchození, proto popisuji Ubuntu a ne Debian. I tak se ale snažíme popsat web
|
|
||||||
v úplnosti.)
|
|
||||||
|
|
||||||
.. I use Arch, btw.
|
|
||||||
|
|
||||||
|
|
||||||
Základ webu
|
|
||||||
===========
|
|
||||||
|
|
||||||
- ``python3`` – Ideálně Python 3.9, jenž je na Gimlim
|
|
||||||
- ``python3-pip`` pro instalaci dalších Pythoních balíčků podle ``requirements.txt``
|
|
||||||
- ``python3-venv``
|
|
||||||
- ``gcc`` – kompilace Pythoních knihoven ze zdrojových distribucí (sdist), možná (neotestováno) jde jako alternativu použít ``python3-wheel`` a stahovat bdists
|
|
||||||
- ``python3-dev`` – taktéž
|
|
||||||
- ``libpq-dev`` do třetice…
|
|
||||||
- ``ghostscript`` TODO konverze PDF v korekturovátku
|
|
||||||
- ``pdflatex`` FIXME! generování obálek a stvrzenek
|
|
||||||
- ``git`` – používán :ref:`Make skripty`
|
|
||||||
- ``locales`` pro české formáty
|
|
||||||
|
|
||||||
Nasazení na produkci / testweb
|
|
||||||
==============================
|
|
||||||
|
|
||||||
(nejsou nutně potřeba k provozu lokální instance)
|
|
||||||
|
|
||||||
- ``rsync``
|
|
||||||
- ``pg_utils`` FIXME
|
|
||||||
- ``htpasswd`` FIXME – aby testweb nepoužívali náhodní kolemjdoucí
|
|
||||||
- ``postgresql-server`` TODO
|
|
||||||
- ``acl`` pro nastavování práv přes ``setfacl``
|
|
||||||
|
|
||||||
Pro testweb je potřeba i všechno pro :ref:`dokumentaci <Dokumentace>`, vizte níž.
|
|
||||||
|
|
||||||
Předpokládá se nasazení v uWSGI pod Nginxem a služba běžící pod systemd, nicméně to už je spíš záležitost infrastruktury a ne specifikum mamwebu.
|
|
||||||
|
|
||||||
Dokumentace
|
|
||||||
===========
|
|
||||||
|
|
||||||
- ``make`` pro zbuildění
|
|
||||||
- Pythoní balíčky podle příslušné části ``requirements.txt``
|
|
||||||
|
|
||||||
Vývojové nástroje
|
|
||||||
=================
|
|
||||||
|
|
||||||
(Nejsou nezbytně nutné, ale předpokládáme jejich užitečnost. Mohou se hodit i na produkci.)
|
|
||||||
|
|
||||||
- ``psql`` TODO pro manuální dotazy do PostgreSQL
|
|
||||||
- ``sqlite3`` TODO totéž pro SQLite3
|
|
||||||
- ``ssh``
|
|
||||||
- ``graphviz`` pro vygenerování schématu
|
|
||||||
- ``rsync``
|
|
||||||
- ``ipython3`` – hezčí interaktivní shell (stačí z ``requirements.txt``)
|
|
||||||
|
|
||||||
Potenciální usnadnění života
|
|
||||||
============================
|
|
||||||
|
|
||||||
(Úplně zbytečné, ale sdílíme pozitivní zkušenosti :-))
|
|
||||||
|
|
||||||
- ``tea`` – CLI klient pro Giteu, aby člověk nepotřeboval otevírat web pro založení PR
|
|
||||||
|
|
||||||
|
|
||||||
Alternativní jména balíčků
|
|
||||||
==========================
|
|
||||||
|
|
||||||
Různé distribuce balí SW různě, takže to, co je v jedné distribuci jeden
|
|
||||||
balíček může být v jiné rozděleno do víc. Pro usnadnění nasazení je tady
|
|
||||||
přehled známých alternativních jmen.
|
|
||||||
|
|
||||||
TODO: tabulka není úplná. Pokud na něco narazíte, tak ji prosím doplňte.
|
|
||||||
|
|
||||||
.. admonition:: Jak se pozná, že web funguje, pro účely tabulky?
|
|
||||||
|
|
||||||
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 nefunguje synchronizace flatpages (nemáme SSH klíč),
|
|
||||||
``make/init_local`` sestřelíme při pokusu o synchronizaci 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."
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
Zkratky aplikací ve zdrojácích
|
|
||||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
|
||||||
|
|
||||||
Ve zdrojácích (zejména různé ``models.py``, ``views.py`` ap.) používáme spoustu
|
|
||||||
modelů. Někdy je praktičtější / někdo preferuje importovat celou aplikaci jako
|
|
||||||
jedno jméno a používat modely bez explicitních importů, tj::
|
|
||||||
|
|
||||||
# „hromadné“ importy:
|
|
||||||
import personalni.models as p
|
|
||||||
...
|
|
||||||
p.Organizator.objects.all()
|
|
||||||
|
|
||||||
# „explicitní“ importy:
|
|
||||||
from personalni.models import Organizator
|
|
||||||
...
|
|
||||||
Organizator.objects.all()
|
|
||||||
|
|
||||||
Na webschůzce 2024-11-05 jsme na toto téma otevřeli diskusi, tady je její závěr.
|
|
||||||
|
|
||||||
.. admonition:: Historické okénko
|
|
||||||
:class: note
|
|
||||||
|
|
||||||
Kdysi jsme měli (prakticky) všechny modely v jedné aplikaci, ``seminar``. Na
|
|
||||||
různých místech se pak ``seminar.models`` importovalo typicky jako ``s``
|
|
||||||
nebo jako ``m``.
|
|
||||||
|
|
||||||
Přirozeně, toto už nejde tak snadno, protože už neexistuje jedno místo, ze
|
|
||||||
kterého chceme tahat modely v kódu.
|
|
||||||
|
|
||||||
Konvence
|
|
||||||
========
|
|
||||||
|
|
||||||
Shodli jsme se, že nám rozhodně nevadí explicitní importy a z pohledu
|
|
||||||
čitelnosti je preferujeme. Nicméně při psaní kódu to některým webařům přijde
|
|
||||||
nepohodlné, takže očekáváme, že bude existovat spousta kódu, která bude chtít
|
|
||||||
importovat hromadně. Usnesli jsme se proto na následujících kanonických
|
|
||||||
zkratkách, aby se aplikace alespoň zkracovaly konzistentně.
|
|
||||||
|
|
||||||
V závorkách je uvedené případné jméno, ale nepředpokládáme, že někdo bude danou
|
|
||||||
aplikaci chtít importovat hromadně. Některé aplikace zkratku nemají, ty se
|
|
||||||
importují vždy pod plným jménem nebo explicitně.
|
|
||||||
|
|
||||||
.. list-table::
|
|
||||||
:header-rows: 1
|
|
||||||
|
|
||||||
* - Model
|
|
||||||
- Zkratka
|
|
||||||
* - ``aesop``
|
|
||||||
- ---
|
|
||||||
* - ``api``
|
|
||||||
- --- (``api``)
|
|
||||||
* - ``galerie``
|
|
||||||
- ``g``
|
|
||||||
* - ``header_fotky``
|
|
||||||
- --- (``hdr``)
|
|
||||||
* - ``korektury``
|
|
||||||
- ``kor``
|
|
||||||
* - ``novinky``
|
|
||||||
- ``nov``
|
|
||||||
* - ``odevzdavatko``
|
|
||||||
- ``odev``
|
|
||||||
* - ``personální``
|
|
||||||
- ``pers``/``p``
|
|
||||||
* - ``sifrovacka``
|
|
||||||
- (``sifr``)
|
|
||||||
* - ``soustredeni``
|
|
||||||
- ``sou``
|
|
||||||
* - ``treenode``
|
|
||||||
- ``tn``
|
|
||||||
* - ``tvorba``
|
|
||||||
- ``tv``
|
|
||||||
* - ``various``
|
|
||||||
- ``v``/``var``
|
|
||||||
* - ``vyroci``
|
|
||||||
- ---
|
|
||||||
* - ``vysledkovky``
|
|
||||||
- ``vysl``
|
|
||||||
|
|
||||||
|
|
||||||
.. admonition:: O všech modelech pod jedním jménem
|
|
||||||
:class: warning
|
|
||||||
|
|
||||||
Historické okénko výš zatajuje jeden detail: Při práci v shellu se hodí mít
|
|
||||||
modely k dispozici a nemuset přemýšlet nad dělením do aplikací, takže ve
|
|
||||||
skutečnosti existuje ``mamweb.vsechno``, jenž všechny modely obsahuje.
|
|
||||||
Z čitelnostních důvodů je ale *zakázáno* tento modul používat v kódu.
|
|
25
galerie/TODO
Normal file
25
galerie/TODO
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
========
|
||||||
|
| TODO |
|
||||||
|
|======|
|
||||||
|
|
||||||
|
Aktualni
|
||||||
|
* co s titulni fotkou
|
||||||
|
* do CSS
|
||||||
|
* nahledy
|
||||||
|
* nastylovat tabulku s nahledy
|
||||||
|
* komentare uz na nahledy?
|
||||||
|
* detail
|
||||||
|
* nahledy pred a po
|
||||||
|
* opravit prechodove sipky
|
||||||
|
* vyrobit prechodove sipky ve M&M-stylu
|
||||||
|
|
||||||
|
Dlouhodobe
|
||||||
|
* sipky na prechazeni mezi fotkami
|
||||||
|
* hromadne PRIDANI fotek do jiz existujici galerie
|
||||||
|
|
||||||
|
Fylozoficke
|
||||||
|
* zvolit velikosti velke a male fotky
|
||||||
|
* je potreba i jine razeni nez automaticky podle casu nebo staci podgalerie?
|
||||||
|
* napr. dve hry na dvou ruznych mistech ve stejny cas
|
||||||
|
* fotky od ucastniku ze hry (skupinky se pohybuji ve stejny cas, ale maji sled fotek) -- nestaci to pripadne vrazit do podgalerii?
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#coding: utf-8
|
||||||
|
|
||||||
from galerie.models import Obrazek, Galerie
|
from galerie.models import Obrazek, Galerie
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
|
47
galerie/autocomplete_light_registry.py.old
Normal file
47
galerie/autocomplete_light_registry.py.old
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from autocomplete_light import shortcuts as autocomplete_light
|
||||||
|
|
||||||
|
from .models import Obrazek, Galerie
|
||||||
|
from .views import cesta_od_korene
|
||||||
|
|
||||||
|
|
||||||
|
class ObrazekAutocomplete(autocomplete_light.AutocompleteModelBase):
|
||||||
|
|
||||||
|
model = Obrazek
|
||||||
|
search_fields = ['nazev', 'popis']
|
||||||
|
split_words = True
|
||||||
|
limit_choices = 15
|
||||||
|
attrs = {
|
||||||
|
# This will set the input placeholder attribute:
|
||||||
|
'placeholder': u'Obrázek',
|
||||||
|
# This will set the yourlabs.Autocomplete.minimumCharacters
|
||||||
|
# options, the naming conversion is handled by jQuery
|
||||||
|
'data-autocomplete-minimum-characters': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
choice_html_format = '''
|
||||||
|
<span class="block" data-value="{}">
|
||||||
|
<span class="block">
|
||||||
|
{}
|
||||||
|
<span class="block">{}</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
'''
|
||||||
|
|
||||||
|
def choice_label(self, obrazek):
|
||||||
|
cesta = "/".join(g.nazev for g in cesta_od_korene(obrazek.galerie))
|
||||||
|
popis = "{}<br>".format(obrazek.popis) if obrazek.popis else ""
|
||||||
|
return '{}<br>{}{}'.format(obrazek.nazev, popis, cesta)
|
||||||
|
|
||||||
|
def choice_html(self, obrazek):
|
||||||
|
"""Vrátí kus html i s obrázkem, které se pak ukazuje v nabídce"""
|
||||||
|
return self.choice_html_format.format(self.choice_value(obrazek),
|
||||||
|
obrazek.obrazek_maly_tag(), self.choice_label(obrazek))
|
||||||
|
|
||||||
|
widget_attrs={
|
||||||
|
'data-widget-maximum-values': 15,
|
||||||
|
'class': 'modern-style',
|
||||||
|
}
|
||||||
|
|
||||||
|
autocomplete_light.register(ObrazekAutocomplete)
|
|
@ -1,4 +1,7 @@
|
||||||
|
#coding: utf-8
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from seminar.models import Soustredeni
|
||||||
|
|
||||||
class KomentarForm(forms.Form):
|
class KomentarForm(forms.Form):
|
||||||
komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False)
|
komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Generated by Django 4.2.11 on 2024-04-30 21:53
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('galerie', '0010_auto_20200819_0947'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Generated by Django 4.2.11 on 2024-05-01 13:07
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('soustredeni', '0001_split_from_seminar'),
|
|
||||||
('galerie', '0011_pre_split_soustredeni'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='galerie',
|
|
||||||
name='soustredeni',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='soustredeni.soustredeni'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Generated by Django 4.2.11 on 2024-05-01 13:35
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('galerie', '0012_soustredeni_relink'),
|
|
||||||
('soustredeni', '0003_post_split_soustredeni'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
]
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
#from django.db.models import Q
|
#from django.db.models import Q
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from imagekit.models import ImageSpecField
|
from imagekit.models import ImageSpecField
|
||||||
from imagekit.processors import ResizeToFit, Transpose
|
from imagekit.processors import ResizeToFit, Transpose
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from soustredeni.models import Soustredeni
|
from seminar.models import Soustredeni
|
||||||
|
|
||||||
VZDY=0
|
VZDY=0
|
||||||
ORG=1
|
ORG=1
|
||||||
|
|
|
@ -1,186 +0,0 @@
|
||||||
@charset "utf-8"; /* vynuť utf-8 */
|
|
||||||
|
|
||||||
/* Galerie */
|
|
||||||
|
|
||||||
|
|
||||||
/* velká fotka */
|
|
||||||
/* zmenšování spolu s oknem prohlížeče */
|
|
||||||
.galerie .obrazek, .titulni_obrazek {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
width: auto\9; /* ie8 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.predchozi_obrazek{
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
width: 33%;
|
|
||||||
height: 100%;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
.predchozi_obrazek:hover{
|
|
||||||
background-image: url("/static/galerie/prvky/predchozi.svg");
|
|
||||||
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
|
||||||
background-position: left center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.dalsi_obrazek{
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
width: 33%;
|
|
||||||
height: 100%;
|
|
||||||
left: 67%;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
.dalsi_obrazek:hover{
|
|
||||||
background-image: url("/static/galerie/prvky/dalsi.svg");
|
|
||||||
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
|
||||||
background-position: right center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie {
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
margin: 20px auto 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie h1 {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_hlavicka {
|
|
||||||
margin: 30px auto 30px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popis {
|
|
||||||
margin: 10px 10px 30px 0px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nahoru {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* titulní obrázek hlavní galerie soustředění */
|
|
||||||
|
|
||||||
.galerie_nahledy{
|
|
||||||
/*margin: 1em 0;*/
|
|
||||||
margin: auto;
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_nahledy img {
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_nahledy div.navigace {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_nahled, .podgalerie_nahled { /* frame */
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
float: left;
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
text-align: center;
|
|
||||||
border: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 4px;
|
|
||||||
border-color: var(--svetla-oranzova);
|
|
||||||
background-color: var(--barva-pozadi);
|
|
||||||
white-space: nowrap;
|
|
||||||
margin: 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_nahled:hover, .podgalerie_nahled:hover {
|
|
||||||
background-color: var(--svetla-oranzova);
|
|
||||||
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
|
||||||
color: var(--tmava-oranzova);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vystredeno{ /* helper */
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_nahled img {
|
|
||||||
vertical-align: middle;
|
|
||||||
max-height: 180px;
|
|
||||||
max-width: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_nahled div {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0px;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.podgalerie_nahled img {
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
max-height: 125px;
|
|
||||||
max-width: 167px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.podgalerie_nahled .nazev_galerie {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
top: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Odkazy na předchozí a následující podgalerii */
|
|
||||||
.galerie_predchozi_nasledujici {
|
|
||||||
overflow: auto;
|
|
||||||
margin: 10px auto 10px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_predchozi_nasledujici .predchozi {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.galerie_predchozi_nasledujici .nasledujici {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 {
|
|
||||||
position: absolute;
|
|
||||||
width: 0;
|
|
||||||
height: 55px; /* viz #title */
|
|
||||||
margin-top: -55px; /* viz #title */
|
|
||||||
}
|
|
||||||
@media(max-width: 860px) {
|
|
||||||
.kotva_obrazku {
|
|
||||||
height: 3em; /* #FIXME nemám páru, jak zjistit výšku toho elementu */
|
|
||||||
margin-top: -3em; /* #FIXME */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* plus a minus tlacitka */
|
|
||||||
.mam-org-only-galerie {
|
|
||||||
background: var(--orgovska-svetla-fialova);
|
|
||||||
padding: 10px;
|
|
||||||
margin: 10px 10px 10px -20px;
|
|
||||||
border: #333 2px dashed;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mam-org-only-galerie a{
|
|
||||||
padding: 3px 5px;
|
|
||||||
margin: 5px;
|
|
||||||
border-radius: 20px;
|
|
||||||
background-color: var(--tmava-oranzova);;
|
|
||||||
color: var(--barva-pozadi);
|
|
||||||
float: left;
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "galerie/base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
|
||||||
{% block nadpis1a %}
|
{% block nadpis1a %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "galerie/base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block nadpis1a %}
|
{% block nadpis1a %}
|
||||||
Galerie {{galerie.nazev}}
|
Galerie {{galerie.nazev}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "galerie/base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block custom_css %}
|
|
||||||
<link href="{% static 'css/galerie.css' %}?version=1" rel="stylesheet">
|
|
||||||
{% endblock %}
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from personalni.utils import org_required
|
from seminar.utils import org_required
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
|
@ -6,7 +8,7 @@ from django.template import RequestContext
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from galerie.models import Obrazek, Galerie
|
from galerie.models import Obrazek, Galerie
|
||||||
from soustredeni.models import Soustredeni
|
from seminar.models import Soustredeni
|
||||||
from galerie.forms import KomentarForm, NewGalerieForm
|
from galerie.forms import KomentarForm, NewGalerieForm
|
||||||
|
|
||||||
def zobrazit(galerie, request):
|
def zobrazit(galerie, request):
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
"""
|
|
||||||
Aplikace umožňující „na uživatelské úrovni“ měnit obrázek v pozadí meníčka.
|
|
||||||
|
|
||||||
Umožňuje uložit obrázek a následně popsat, na kterých stránkách (podle url)
|
|
||||||
a v který čas (den/noc) se má zobrazovat.
|
|
||||||
"""
|
|
|
@ -4,11 +4,7 @@ import header_fotky.models as m
|
||||||
|
|
||||||
|
|
||||||
class FotkaPozadiAdmin(ModelAdmin):
|
class FotkaPozadiAdmin(ModelAdmin):
|
||||||
"""
|
|
||||||
Nastaví čas vložení (:attr:`~header_fotky.models.FotkaHeader.cas`) jako
|
|
||||||
readonly = neměnitelný
|
|
||||||
"""
|
|
||||||
readonly_fields = ['cas']
|
readonly_fields = ['cas']
|
||||||
|
|
||||||
admin.site.register(m.FotkaHeader, FotkaPozadiAdmin)
|
admin.site.register(m.FotkaHeader, FotkaPozadiAdmin)
|
||||||
admin.site.register(m.FotkaUrlVazba)
|
admin.site.register(m.FotkaUrlVazba)
|
|
@ -3,4 +3,3 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
class HeaderFotkyConfig(AppConfig):
|
class HeaderFotkyConfig(AppConfig):
|
||||||
name = 'header_fotky'
|
name = 'header_fotky'
|
||||||
verbose_name = 'Fotky v záhlaví'
|
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
"""
|
|
||||||
Context processory lze přidat do djanga v :mod:`~mamweb.settings` a dělají to,
|
|
||||||
že do contextu (tj. to, z čeho se např. berou proměnné v templatech) libovolné
|
|
||||||
stránky přidají další věci.
|
|
||||||
"""
|
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
@ -12,46 +8,38 @@ from header_fotky.models import FotkaUrlVazba
|
||||||
|
|
||||||
|
|
||||||
def vzhled(request):
|
def vzhled(request):
|
||||||
"""
|
''' Podle casu prida do templatu, zdali je nebo neni noc '''
|
||||||
Podle času přidá do contextu, zdali je nebo není noc. Dále podle dení
|
hodin = datetime.now().hour
|
||||||
doby a url přidá do contextu správnou fotku.
|
if (hodin <= 6) or (hodin >= 20):
|
||||||
|
noc = True
|
||||||
|
nedoba = 'den'
|
||||||
|
doba = 'noc'
|
||||||
|
else:
|
||||||
|
noc = False
|
||||||
|
nedoba = 'noc'
|
||||||
|
doba = 'den'
|
||||||
|
url = request.path
|
||||||
|
|
||||||
url adresu nejprve vyzkouší celou, pak postupně odřezává věci za
|
fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba)
|
||||||
lomítkem, dokud nenajde url, pro kterou existuje alespoň jedna fotka.
|
fotka = None
|
||||||
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)
|
# TODO rychlejší patternmatch?
|
||||||
fotka = None
|
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()
|
||||||
|
|
||||||
# TODO rychlejší patternmatch?
|
url = url[:-1]
|
||||||
while (fotka is None) and (url != ''):
|
index = url.rfind('/')
|
||||||
presne = fotky.filter(url__exact=url)
|
if index != -1:
|
||||||
if presne.count() > 0:
|
url = url[:index+1]
|
||||||
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]
|
if fotka is None:
|
||||||
index = url.rfind('/')
|
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
|
||||||
if index != -1:
|
|
||||||
url = url[:index+1]
|
|
||||||
|
|
||||||
if fotka is None:
|
return {'noc': noc, 'fotka': fotka}
|
||||||
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
|
|
||||||
|
|
||||||
return {'noc': noc, 'fotka': fotka}
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
class FotkaHeader(models.Model):
|
class FotkaHeader(models.Model):
|
||||||
""" fotka pro :mod:`fotka_header`, konkrétně :class:`~fotka_header.models.FotkaUrlVazba` """
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-cas']
|
ordering = ['-cas']
|
||||||
db_table = 'fotky_header'
|
db_table = 'fotky_header'
|
||||||
|
@ -12,34 +11,27 @@ class FotkaHeader(models.Model):
|
||||||
verbose_name_plural = u'fotky do pozadí menu'
|
verbose_name_plural = u'fotky do pozadí menu'
|
||||||
|
|
||||||
cas = models.DateTimeField(u'čas vložení fotky', default=timezone.now, help_text='Čas vložení fotky')
|
cas = models.DateTimeField(u'čas vložení fotky', default=timezone.now, help_text='Čas vložení fotky')
|
||||||
""" čas vložení fotky """
|
|
||||||
|
|
||||||
nazev = models.CharField(
|
nazev = models.CharField(
|
||||||
u'název fotky', null=False, blank=False, unique=True, primary_key=True,
|
u'název fotky', null=False, blank=False, unique=True, primary_key=True,
|
||||||
max_length=50, help_text='Název např. archiv_noc'
|
max_length=50, help_text='Název např. archiv_noc'
|
||||||
)
|
)
|
||||||
""" jméno fotky na webu """
|
|
||||||
|
|
||||||
fotka = models.ImageField(upload_to='header', null=False, blank=False)
|
fotka = models.ImageField(upload_to='header', null=False, blank=False)
|
||||||
""" soubor fotky (Nahrává se automaticky do složky ``media``.) """
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.nazev
|
return self.nazev
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
""" kontroluje, zda sedí poměr stran """
|
|
||||||
if not self.fotka:
|
if not self.fotka:
|
||||||
raise ValidationError("Chybí obrázek")
|
raise ValidationError("Chybí obrázek")
|
||||||
|
""" Kontroluje, zda sedí poměr stran """
|
||||||
if abs(self.fotka.width - (self.fotka.height * 970 / 350)) > 2:
|
if abs(self.fotka.width - (self.fotka.height * 970 / 350)) > 2:
|
||||||
raise ValidationError("Obrázek by měl mít rozměry 970w na 350h, nebo alespoň podobný poměr stran.")
|
raise ValidationError("Obrázek by měl mít rozměry 970w na 350h, nebo alespoň podobný poměr stran.")
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
|
|
||||||
class FotkaUrlVazba(models.Model):
|
class FotkaUrlVazba(models.Model):
|
||||||
"""
|
|
||||||
spojení :class:`~fotka_header.models.FotkaHeader` a url
|
|
||||||
(resp. „prefixu“ url), na které má být zobrazována
|
|
||||||
"""
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['url']
|
ordering = ['url']
|
||||||
db_table = 'fotky_url_vazby'
|
db_table = 'fotky_url_vazby'
|
||||||
|
@ -50,13 +42,11 @@ class FotkaUrlVazba(models.Model):
|
||||||
u'URL', blank=True, null=False, max_length=100,
|
u'URL', blank=True, null=False, max_length=100,
|
||||||
help_text='url prefix stránek např: /archiv/ nebo /'
|
help_text='url prefix stránek např: /archiv/ nebo /'
|
||||||
)
|
)
|
||||||
""" url prefix stránek, kde má být fotka zobrazena, např: /archiv/ nebo / """
|
|
||||||
|
|
||||||
fotka = models.ForeignKey(
|
fotka = models.ForeignKey(
|
||||||
FotkaHeader, blank=False, null=False, verbose_name='fotka',
|
FotkaHeader, blank=False, null=False, verbose_name='fotka',
|
||||||
on_delete=models.CASCADE
|
on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
""" :class:`~fotka_header.models.FotkaHeader`, která má být zobrazována """
|
|
||||||
|
|
||||||
DOBA_DEN = 'den'
|
DOBA_DEN = 'den'
|
||||||
DOBA_NOC = 'noc'
|
DOBA_NOC = 'noc'
|
||||||
|
@ -67,11 +57,9 @@ class FotkaUrlVazba(models.Model):
|
||||||
(DOBA_OBOJI, 'Zobrazovat pořád')]
|
(DOBA_OBOJI, 'Zobrazovat pořád')]
|
||||||
|
|
||||||
denni_doba = models.CharField('denní doba', max_length=16, choices=DOBA_CHOICES, blank=False, default=DOBA_OBOJI)
|
denni_doba = models.CharField('denní doba', max_length=16, choices=DOBA_CHOICES, blank=False, default=DOBA_OBOJI)
|
||||||
""" dení doba, kdy tam má být zobrazována """
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.url
|
return self.url
|
||||||
|
|
||||||
def url_fotky(self):
|
def url_fotky(self):
|
||||||
""" vrací url fotky (tj. url, kde reálně získám soubor fotky) """
|
|
||||||
return self.fotka.fotka.url
|
return self.fotka.fotka.url
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
FIXME přepsat do rst, přidat i další věci a případně přesunout na wiki
|
|
||||||
Přidání obrázků do odměn:
|
Přidání obrázků do odměn:
|
||||||
admin -> flatpage odměn -> ikona přidat obrázek
|
admin -> flatpage odměn -> ikona přidat obrázek
|
||||||
záložka odeslat, vybrat obrázek, odeslat
|
záložka odeslat, vybrat obrázek, odeslat
|
11
korektury/TODO
Normal file
11
korektury/TODO
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
- korektura potrebuje reakci
|
||||||
|
+ komentáře fixně na username
|
||||||
|
- používat skutečné jméno?
|
||||||
|
- vyžádat pozornost autora obsahu
|
||||||
|
- zvednout upload limit na 5MB
|
||||||
|
- sbalit a rozbalit korekturu
|
||||||
|
- nahrávání jiných věcí než PDF - kontrolovat?
|
||||||
|
- stylování
|
||||||
|
- seznam PDF - co zobrazovat?
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
"""
|
|
||||||
Seznam pdf k opravě a `opraf`_ v djangu místo PHP.
|
|
||||||
|
|
||||||
.. _opraf: https://github.com/vitstradal/opraf
|
|
||||||
"""
|
|
|
@ -1,23 +1,16 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
from korektury.models import KorekturovanePDF, Oprava, KorekturaTag
|
from korektury.models import KorekturovanePDF
|
||||||
|
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import send_mail
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
class KorekturovanePDFAdmin(VersionAdmin):
|
class KorekturovanePDFAdmin(VersionAdmin):
|
||||||
"""
|
|
||||||
nastaví čas vložení (:attr:`~koretkury.models.KorekturovanePDF.cas`) a počet
|
|
||||||
stran (:attr:`~koretkury.models.KorekturovanePDF.stran`) jako readonly =
|
|
||||||
neměnitelný
|
|
||||||
|
|
||||||
Při prvním uložení pošle e-mail.
|
|
||||||
"""
|
|
||||||
|
|
||||||
readonly_fields = ['cas', 'stran']
|
readonly_fields = ['cas', 'stran']
|
||||||
|
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
""" Když pdf existuje, tak nedovolím měnit ani pdf."""
|
|
||||||
if obj:
|
if obj:
|
||||||
return self.readonly_fields + ['pdf']
|
return self.readonly_fields + ['pdf']
|
||||||
return self.readonly_fields
|
return self.readonly_fields
|
||||||
|
@ -25,18 +18,14 @@ class KorekturovanePDFAdmin(VersionAdmin):
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(None,
|
(None,
|
||||||
{'fields':
|
{'fields':
|
||||||
['pdf', 'cas', 'stran', 'nazev', 'orgove', 'komentar', 'poslat_mail']}),
|
['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar', 'poslat_mail']}),
|
||||||
# (u'PDF', {'fields': ['pdf']}),
|
# (u'PDF', {'fields': ['pdf']}),
|
||||||
]
|
]
|
||||||
list_display = ['nazev', 'cas', 'stran']
|
list_display = ['nazev', 'cas', 'stran', 'org']
|
||||||
list_filter = []
|
list_filter = []
|
||||||
search_fields = []
|
search_fields = []
|
||||||
autocomplete_fields = ['orgove']
|
|
||||||
|
|
||||||
def save_model(self, request, obj, form, change):
|
def save_model(self, request, obj, form, change):
|
||||||
"""
|
|
||||||
Pokud je soubor nový a má se poslat e-mail, tak pošle e-mail o novém pdf.
|
|
||||||
"""
|
|
||||||
super().save_model(request, obj, form, change)
|
super().save_model(request, obj, form, change)
|
||||||
if not change and obj.poslat_mail: # Je nový a má se poslat mail
|
if not change and obj.poslat_mail: # Je nový a má se poslat mail
|
||||||
odkaz = request.build_absolute_uri(reverse('korektury', kwargs={'pdf': obj.id}))
|
odkaz = request.build_absolute_uri(reverse('korektury', kwargs={'pdf': obj.id}))
|
||||||
|
@ -54,19 +43,6 @@ Popis souboru:
|
||||||
S pozdravem a korekturám zdar!
|
S pozdravem a korekturám zdar!
|
||||||
Korekturovátko
|
Korekturovátko
|
||||||
'''
|
'''
|
||||||
EmailMessage(
|
send_mail(predmet,text,odesilatel,[prijemce])
|
||||||
subject=predmet,
|
|
||||||
body=text,
|
|
||||||
from_email=odesilatel,
|
|
||||||
to=[prijemce],
|
|
||||||
).send()
|
|
||||||
|
|
||||||
admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin)
|
admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin)
|
||||||
|
|
||||||
|
|
||||||
class OpravaAdmin(admin.ModelAdmin):
|
|
||||||
model = Oprava
|
|
||||||
filter_horizontal = ("informovani_orgove", "tagy",)
|
|
||||||
|
|
||||||
admin.site.register(Oprava, OpravaAdmin)
|
|
||||||
admin.site.register(KorekturaTag)
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class ApiConfig(AppConfig):
|
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
|
||||||
name = 'korektury.api'
|
|
||||||
label = 'korektury_api' # Protože jedno api už máme.
|
|
|
@ -1,11 +0,0 @@
|
||||||
from django.urls import path
|
|
||||||
from personalni.utils import org_required
|
|
||||||
from . import views
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path('<int:pdf_id>/stav', org_required(views.korektury_stav_view), name='korektury_api_pdf_stav'),
|
|
||||||
path('oprava/stav', org_required(views.oprava_stav_view), name='korektury_api_oprava_stav'),
|
|
||||||
path('<int:pdf_id>/opravy_a_komentare', org_required(views.opravy_a_komentare_view), name='korektury_api_opravy_a_komentare'),
|
|
||||||
path('oprava/smaz', org_required(views.oprava_smaz_view), name='korektury_api_oprava_smaz'),
|
|
||||||
path('komentar/smaz', org_required(views.komentar_smaz_view), name='korektury_api_komentar_smaz'),
|
|
||||||
]
|
|
|
@ -1,129 +0,0 @@
|
||||||
from http import HTTPStatus
|
|
||||||
|
|
||||||
from django.http import JsonResponse, HttpResponse
|
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
from django.utils.html import linebreaks
|
|
||||||
|
|
||||||
from rest_framework import serializers
|
|
||||||
|
|
||||||
from korektury.utils import send_email_notification_komentar
|
|
||||||
from korektury.models import Oprava, KorekturovanePDF, Komentar, KorekturaTag
|
|
||||||
from personalni.models import Organizator
|
|
||||||
|
|
||||||
|
|
||||||
def korektury_stav_view(request, pdf_id: int, **kwargs):
|
|
||||||
q = request.POST
|
|
||||||
pdf = get_object_or_404(KorekturovanePDF, id=pdf_id)
|
|
||||||
status = q.get('state')
|
|
||||||
if status is not None:
|
|
||||||
assert status in KorekturovanePDF.STATUS.values
|
|
||||||
pdf.status = status
|
|
||||||
pdf.save()
|
|
||||||
return JsonResponse({'status': pdf.status})
|
|
||||||
|
|
||||||
|
|
||||||
def oprava_stav_view(request, **kwargs):
|
|
||||||
q = request.POST
|
|
||||||
op_id_str = q.get('id')
|
|
||||||
assert op_id_str is not None
|
|
||||||
op_id = int(op_id_str)
|
|
||||||
op = get_object_or_404(Oprava, id=op_id)
|
|
||||||
status = q.get('action')
|
|
||||||
if status is not None:
|
|
||||||
assert status in Oprava.STATUS.values
|
|
||||||
op.status = status
|
|
||||||
op.save()
|
|
||||||
return JsonResponse({'status': op.status})
|
|
||||||
|
|
||||||
def oprava_smaz_view(request, **kwargs):
|
|
||||||
q = request.POST
|
|
||||||
op_id_str = q.get('oprava_id')
|
|
||||||
assert op_id_str is not None
|
|
||||||
op_id = int(op_id_str)
|
|
||||||
oprava = get_object_or_404(Oprava, id=op_id)
|
|
||||||
oprava.delete()
|
|
||||||
return HttpResponse(status=HTTPStatus.NO_CONTENT)
|
|
||||||
|
|
||||||
def komentar_smaz_view(request, **kwargs):
|
|
||||||
q = request.POST
|
|
||||||
kom_id_str = q.get('komentar_id')
|
|
||||||
assert kom_id_str is not None
|
|
||||||
kom_id = int(kom_id_str)
|
|
||||||
komentar = get_object_or_404(Komentar, id=kom_id)
|
|
||||||
komentar.delete()
|
|
||||||
return HttpResponse(status=HTTPStatus.NO_CONTENT)
|
|
||||||
|
|
||||||
class KomentarSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Komentar
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
def to_representation(self, instance):
|
|
||||||
ret = super().to_representation(instance)
|
|
||||||
ret["autor"] = str(instance.autor)
|
|
||||||
ret["text"] = linebreaks(ret["text"], autoescape=True) # Autora není třeba escapovat, ten se vkládá jako text.
|
|
||||||
return ret
|
|
||||||
|
|
||||||
class KorekturaTagSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = KorekturaTag
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
|
|
||||||
class OpravaSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Oprava
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
def to_representation(self, instance):
|
|
||||||
ret = super().to_representation(instance)
|
|
||||||
ret["komentare"] = [KomentarSerializer(komentar).data for komentar in instance.komentar_set.all()]
|
|
||||||
ret["tagy"] = [KorekturaTagSerializer(tag).data for tag in instance.tagy.all()]
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# komentar_set = serializers.ListField(child=KomentarSerializer())
|
|
||||||
|
|
||||||
def opravy_a_komentare_view(request, pdf_id: int, **kwargs):
|
|
||||||
if request.method == 'POST':
|
|
||||||
q = request.POST
|
|
||||||
|
|
||||||
x = int(q.get('x'))
|
|
||||||
y = int(q.get('y'))
|
|
||||||
img_id = int(q.get('img_id'))
|
|
||||||
oprava_id = int(q.get('oprava_id'))
|
|
||||||
komentar_id = int(q.get('komentar_id'))
|
|
||||||
text = q.get('text')
|
|
||||||
|
|
||||||
# prirazeni autora podle prihlaseni
|
|
||||||
autor_user = request.user
|
|
||||||
# pokud existuje ucet (user), ale neni to organizator = 403
|
|
||||||
autor = Organizator.objects.filter(osoba__user=autor_user).first()
|
|
||||||
|
|
||||||
if komentar_id != -1:
|
|
||||||
komentar = get_object_or_404(Komentar, id=komentar_id)
|
|
||||||
komentar.text = text
|
|
||||||
komentar.autor = autor
|
|
||||||
komentar.save()
|
|
||||||
else:
|
|
||||||
if oprava_id != -1:
|
|
||||||
oprava = get_object_or_404(Oprava, id=oprava_id)
|
|
||||||
else:
|
|
||||||
pdf = get_object_or_404(KorekturovanePDF, id=pdf_id)
|
|
||||||
oprava = Oprava.objects.create(
|
|
||||||
pdf=pdf,
|
|
||||||
strana=img_id,
|
|
||||||
x=x,
|
|
||||||
y=y,
|
|
||||||
)
|
|
||||||
|
|
||||||
tagy_raw = q.get('tagy')
|
|
||||||
if tagy_raw != "":
|
|
||||||
tagy = list(map(int, tagy_raw.split(",")))
|
|
||||||
oprava.tagy.add(*KorekturaTag.objects.filter(id__in=tagy))
|
|
||||||
Komentar.objects.create(oprava=oprava, autor=autor, text=text)
|
|
||||||
send_email_notification_komentar(oprava, autor, request)
|
|
||||||
|
|
||||||
|
|
||||||
opravy = Oprava.objects.filter(pdf=pdf_id).all()
|
|
||||||
# Serializovat list je prý security vulnerability, tedy je přidán slovník pro bezpečnost
|
|
||||||
return JsonResponse({"context": [OpravaSerializer(oprava).data for oprava in opravy]})
|
|
13
korektury/forms.py
Normal file
13
korektury/forms.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
class OpravaForm(forms.Form):
|
||||||
|
text = forms.CharField(max_length=256)
|
||||||
|
autor = forms.CharField(max_length=20)
|
||||||
|
x = forms.IntegerField()
|
||||||
|
y = forms.IntegerField()
|
||||||
|
scroll = forms.CharField(max_length=256)
|
||||||
|
pdf = forms.CharField(max_length=256)
|
||||||
|
img_id = forms.CharField(max_length=256)
|
||||||
|
id = forms.CharField(max_length=256)
|
||||||
|
action = forms.CharField(max_length=256)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# 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'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 2.2.28 on 2023-06-19 19:38
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('korektury', '0019_auto_20221205_2014'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='korekturovanepdf',
|
|
||||||
name='nazev',
|
|
||||||
field=models.CharField(help_text='Název (např. `22.1 | analyza v4` nebo `propagace | letacek v0`) korekturovaného PDF', max_length=50, verbose_name='název PDF'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Generated by Django 4.2.8 on 2024-03-12 20:24
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('korektury', '0020_lepsi_popis_nazvu_PDF_v_adminu'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
]
|
|
|
@ -1,30 +0,0 @@
|
||||||
# Generated by Django 4.2.11 on 2024-03-19 21:35
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('personalni', '0003_initial'),
|
|
||||||
('korektury', '0021_auto_20240312_2124'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='komentar',
|
|
||||||
name='autor',
|
|
||||||
field=models.ForeignKey(blank=True, help_text='Autor komentáře', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='korekturovanepdf',
|
|
||||||
name='org',
|
|
||||||
field=models.ForeignKey(blank=True, default=None, help_text='Zodpovědný organizátor za obsah', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='oprava',
|
|
||||||
name='autor',
|
|
||||||
field=models.ForeignKey(blank=True, help_text='Autor opravy', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Generated by Django 4.2.11 on 2024-03-26 21:25
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'),
|
|
||||||
('personalni', '0005_personalni_post_migrate'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
]
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue