diff --git a/.gitignore b/.gitignore index a61902a0..36b0b565 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,5 @@ # virtual env -/bin/ -/include/ -/lib/ -/local/ -/share/ -/virtualenv/ -/pip-selfcheck.json +/env/ # transient files /db-test.sqlite3* @@ -16,7 +10,7 @@ # aux files *.pyc -*.swp +*.sw[mnop] # secrets /django.secret diff --git a/MIGRATIONS b/MIGRATIONS new file mode 100644 index 00000000..2bfd0dca --- /dev/null +++ b/MIGRATIONS @@ -0,0 +1,3 @@ +Jak zvládnout migrace na nový model: + +- V mojí verzi databáze mají úlohy-Problémy typ "b'uloha'" diff --git a/Makefile b/Makefile index 33e1f229..a9d2e082 100644 --- a/Makefile +++ b/Makefile @@ -1,68 +1,69 @@ -.PHONY: clean_env init_env clean_virtualenv install_packages clean install run all schema_seminar.pdf schema_all.pdf sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local -PYTHON=python2.7 -VE_VER=16.0.0 -LOCAL_PYTHON=bin/python - -all: install - -clean: clean_env - -veryclean: clean clean_virtualenv - -install: virtualenv bin/python install_packages - - -# phony, but depends on file -make_env: ${LOCAL_PYTHON} - -# phony, but fast repeated execution -install_packages: make_env - bin/pip install -r requirements.txt --upgrade - -# phony -clean_env: - rm -rf bin/ include/ lib/ local/ share/ +PYTHON ?= python3 +VENV ?= ${PYTHON} -m venv +# Všechny flagy, které se s venvem/virtualenvem/... mají volat patří sem. Volá se "${VENV} cesta" +VENV_PATH ?= env +# Musí být definovaná, i kdyby to měla být "." + +.PHONY: all venv_check clean install install_web install_venv clean_venv clean_schema run test deploy_test deploy_prod sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local + +# activate by mělo být předpokladem ke všemu, co volá webový python (i.e. python nasazený do ${VENV}u kvůli webu, např. manage.py) +all: + @# Just echo: + # Install je trochu magický: + # Spusť následující posloupnost příkazů: + # make install_venv + # . ${VENV_PATH}/bin/activate + # make install_web + # + # Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev + # Pokud chybová hláška obsahuje #include , nainstaluj si python3-dev + # + # Až skončíš s vývojem webu, spusť "deactivate". Tím zmizí '(${VENV_PATH})' ze začátku promptu. + +venv_check: + @# Pokud org nemá zapnutý venv, poradíme mu, aby si ho zapnul a spadneme. Jinak nic. + @expr $$PATH : ".*:*$(shell pwd)/${VENV_PATH}/bin" > /dev/null && exit 0 || echo 'Není zapnutý venv, spusť ". ${VENV_PATH}/bin/activate".\nPokud není venv nainstalovaný, spusť "make install_venv"' && false + +clean: clean_venv clean_schema + +install: install_web + +install_web: venv_check + @# venv může být příšerně starý, takže nejdříve upgradujeme venvové věci + pip install --upgrade pip + pip install --upgrade setuptools + # Instalace závislostí webu + pip install -r requirements.txt --upgrade + +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 -# binary name representing set-up env -${LOCAL_PYTHON}: virtualenv - ${PYTHON} virtualenv/virtualenv.py . - - - -# directory name -virtualenv: - # I could not find a link without hash anymore. This will probably break in - # the future. - curl -O https://files.pythonhosted.org/packages/33/bc/fa0b5347139cd9564f0d44ebd2b147ac97c36b2403943dbee8a25fd74012/virtualenv-16.0.0.tar.gz - tar xvfz virtualenv-${VE_VER}.tar.gz - mv -T virtualenv-${VE_VER} virtualenv - rm virtualenv-${VE_VER}.tar.gz - -# phony -clean_virtualenv: - rm -rf virtualenv/ - rm -rf virtualenv-*.tar.gz - -run: +run: venv_check ./manage.py runserver -test: +test: venv_check ./manage.py test -v2 seminar mamweb # DB schemata schema: schema_seminar.pdf schema_all.pdf -schema_seminar.pdf: +schema_seminar.pdf: venv_check ./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf -schema_all.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: +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 ..." @@ -78,7 +79,7 @@ deploy_test: @echo Done. # Deploy to current *mamweb-prod* directory -deploy_prod: +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 ..." @@ -96,6 +97,15 @@ deploy_prod: @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; ./manage.py dumpdata flatpages --indent=2 > flat.json" + rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat.json ./flat.json + @echo "Applying downloaded flatpages." + ./manage.py loaddata 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 @@ -128,4 +138,4 @@ sync_local_db: pg_restore -c -d mam-prod last.pgdump # Sync database and media. See above lines -sync_local: sync_media sync_db +sync_local: sync_local_media sync_local_db diff --git a/README.md b/README.md index 057de635..4c69c825 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,12 @@ Use git :-) Quickstart ---------- +Run the following commands: + make install_venv + . env/bin/activate + make install_web -Install the following packages in Debian/Ubuntu: `libpq-dev python-dev python-setuptools python2.7 libjpeg-dev libpng12-dev`. Then run: - - make - ./manage.py testdata - make run +After finishing development, run "deactivate". Make commands ------------- @@ -41,6 +41,8 @@ Make commands * `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 -------------------- @@ -56,6 +58,8 @@ Make commands * `./manage.py test` - run the tests. +* `./manage.py shell` - run commands, list elemements of database, check syntax + by importing files, etc. Configurations -------------- diff --git a/Schema_new.dia b/Schema_new.dia new file mode 100644 index 00000000..c212ec3b Binary files /dev/null and b/Schema_new.dia differ diff --git a/convert_spaces_to_tabs.sh b/convert_spaces_to_tabs.sh new file mode 100755 index 00000000..8f98f6ae --- /dev/null +++ b/convert_spaces_to_tabs.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if test "$#" -lt 1 +then + echo "Usage: $0 file ..." + exit 2 +fi + +for file in "$@" +do + # Do the sed magic: keep replacing 4 spaces at the begining of line + sed -i -re ' + : loop + s/^( *) /\1 / + t loop + ' "$file" +done diff --git a/flat.json b/flat.json new file mode 100644 index 00000000..db13ba78 --- /dev/null +++ b/flat.json @@ -0,0 +1,332 @@ +[ +{ + "model": "flatpages.flatpage", + "pk": 1, + "fields": { + "url": "/o-seminari/", + "title": "O semin\u00e1\u0159i", + "content": "

Pro\u010d \u0159ešit práv\u011b M&M?

\r\n\r\n\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 2, + "fields": { + "url": "/", + "title": "Semin\u00e1\u0159 M&M", + "content": "

Vítejte na stránce seminá\u0159e MaM!

\r\n", + "enable_comments": false, + "template_name": "home.html", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 3, + "fields": { + "url": "/co-je-MaM/uvod/", + "title": "Co je M&M?", + "content": "

M&M je mezioborov\u00fd koresponden\u010dn\u00ed semin\u00e1\u0159 pro studenty st\u0159edn\u00edch \u0161kol zam\u011b\u0159en\u00fd na matematiku, fyziku a informatiku. Ro\u010dn\u011b vyd\u00e1v\u00e1me p\u0159ibli\u017en\u011b sedm \u010d\u00edsel \u010dasopisu, ve kter\u00e9m najde\u0161 t\u00e9mata k b\u00e1d\u00e1n\u00ed, dopln\u011bn\u00e9 o zaj\u00edmav\u00e9 \u00falohy a o \u010dl\u00e1nky jak od n\u00e1s, organiz\u00e1tor\u016f, tak od v\u00e1s, \u0159e\u0161itel\u016f. \u010casopis je zdarma.

\r\n\r\n

M&M je taky sout\u011b\u017e. Za v\u0161echny p\u0159\u00edsp\u011bvky k t\u00e9mat\u016fm, \u0159e\u0161en\u00ed \u00faloh i \u010dl\u00e1nky ud\u011blujeme body. Na z\u00e1klad\u011b z\u00edskan\u00fdch bod\u016f sestavujeme v\u00fdsledkovou listinu. Na nejlep\u0161\u00ed \u0159e\u0161itele \u010dekaj\u00ed knihy a deskovky. Autor nejlep\u0161\u00edho p\u0159\u00edsp\u011bvku do t\u00e9m\u00e1tka si bude moci smlsnout na dortu. Taky se m\u016f\u017ee\u0161 dostat na Matfyz bez p\u0159ij\u00edma\u010dek (viz n\u00ed\u017ee). A hlavn\u011b, p\u0159ibli\u017en\u011b dvacet p\u011bt nej\u00fasp\u011b\u0161n\u011bj\u0161\u00edch \u0159e\u0161itel\u016f zveme dvakr\u00e1t do roka na soust\u0159ed\u011bn\u00ed.

\r\n\r\n

Jak se zapojit

\r\n\r\n

V pr\u016fb\u011bhu \u0161koln\u00edho roku vych\u00e1z\u00ed zpravidla sedm \u010d\u00edsel \u010dasopisu. V nich jsou zadan\u00e9 r\u016fzn\u00e9 podn\u011bty k p\u0159em\u00fd\u0161len\u00ed. Pokud t\u011b n\u011bkter\u00fd zaujme, pokus se k n\u011bmu n\u011bco napsat a poslat n\u00e1m to \u2013 podrobnosti najde\u0161 v sekci Jak \u0159e\u0161it.

\r\n\r\n

Soust\u0159ed\u011bn\u00ed

\r\n\r\n

V\u017edy na podzim a na ja\u0159e p\u0159ipravujeme pro na\u0161e nejlep\u0161\u00ed \u0159e\u0161itele t\u00fddenn\u00ed soust\u0159ed\u011bn\u00ed. To se obvykle kon\u00e1 n\u011bkde v bl\u00edzkosti p\u011bkn\u00e9 p\u0159\u00edrody. Soust\u0159ed\u011bn\u00ed je \u010d\u00e1ste\u010dn\u011b odborn\u00e9, m\u00e1me pro v\u00e1s p\u0159ipraveny p\u0159edn\u00e1\u0161ky ze v\u0161elijak\u00fdch tradi\u010dn\u00edch i netradi\u010dn\u00edch z\u00e1kout\u00ed nejen matematiky, fyziky i informatiky. Dost \u010dasu je v\u011bnov\u00e1no i zaj\u00edmav\u00fdm a z\u00e1bavn\u00fdm hr\u00e1m, venku i uvnit\u0159. P\u0159edev\u0161\u00edm je ale soust\u0159ed\u011bn\u00ed p\u0159\u00edle\u017eitost, jak potkat fajn lidi s podobn\u00fdmi z\u00e1jmy! M\u016f\u017ee\u0161 si prohl\u00e9dnout fotky z p\u0159ede\u0161l\u00fdch soust\u0159ed\u011bn\u00ed.

\r\n\r\n

\r\n\r\n

P\u0159ij\u00edmac\u00ed zkou\u0161ky na MFF

\r\n\r\n

Matematicko-fyzik\u00e1ln\u00ed fakulta Univerzity Karlovy se rozhodla \u00fasp\u011b\u0161n\u00fdm \u0159e\u0161itel\u016fm na\u0161eho koresponden\u010dn\u00edho semin\u00e1\u0159e odpustit p\u0159ij\u00edmac\u00ed zkou\u0161ky. Konkr\u00e9tn\u011b se to t\u00fdk\u00e1 t\u011bch \u0159e\u0161itel\u016f, kte\u0159\u00ed z\u00edskaj\u00ed za rok alespo\u0148 65 bod\u016f. Ti od n\u00e1s dostanou \u201eosv\u011bd\u010den\u00ed \u00fasp\u011b\u0161n\u00e9ho \u0159e\u0161itele\u201c, kter\u00e9 pak mohou p\u0159edlo\u017eit fakult\u011b.

", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 4, + "fields": { + "url": "/clanky/uvod/", + "title": "\u010cl\u00e1nky", + "content": "

V M&M publikujeme \u010dlánky – stejn\u011b jako v opravdovém v\u011bdeckém \u010dasopise. Setkat se u nás m\u016f\u017eeš jednak s \u010dlánky od organizátor\u016f (v rámci n\u011bjakého seriálu, nebo jen tak), jednak nám m\u016f\u017eeš poslat \u010dlánek ty sám.

\r\n\r\n

Organizátorské \u010dlánky

\r\n\r\n

Organizáto\u0159i t\u011b ve svých \u010dláncích obvykle cht\u011bjí nau\u010dit n\u011bco, co by se ti mohlo hodit nebo líbit.

\r\n\r\n

\u010clánky od \u0159ešitel\u016f

\r\n\r\n

Ty sám nám také m\u016f\u017eeš zaslat \u010dlánek k publikování. Krom \u010dlánku k tématu (který spadá do jiné sekce) to nej\u010dast\u011bji bude nejspíš \u010dlánek o tvé konfe\u0159e ze soust\u0159ed\u011bní. M\u016f\u017eeš nám ale poslat i pojednání o \u010demkoli jiném, o \u010dem si myslíš, \u017ee by to mohlo ostatní \u0159ešitele zajímat. My pak tvoji práci zredigujeme a otiskneme. 

\r\n\r\n

Proto\u017ee víc hlav víc ví, m\u016f\u017eete na \u010dláncích pracovat i ve skupinách – stejn\u011b jako p\u0159i \u0159ešení témat!

\r\n\r\n

P\u0159i psaní \u010dlánku do M&M je dobré mít na pam\u011bti základní zásady pro psaní v\u011bdeckého \u010dlánku.

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 5, + "fields": { + "url": "/archiv/temata/", + "title": "T\u00e9mata", + "content": "

Tady se pracuje

\r\n

\r\n Na t\u00e9to str\u00e1nce velmi intenzivn\u011b pracujeme.\r\n Za do\u010dasnou nedostupnost se omlouv\u00e1me.\r\n Zkuste p\u0159ej\u00edt na tituln\u00ed str\u00e1nku\r\n nebo se pod\u00edvat na aktu\u00e1ln\u00ed zad\u00e1n\u00ed.\r\n

\r\n ", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 6, + "fields": { + "url": "/archiv/ulohy/", + "title": "\u00dalohy", + "content": "

Tady se pracuje

\r\n

\r\n Na t\u00e9to str\u00e1nce velmi intenzivn\u011b pracujeme.\r\n Za do\u010dasnou nedostupnost se omlouv\u00e1me.\r\n Zkuste p\u0159ej\u00edt na tituln\u00ed str\u00e1nku\r\n nebo se pod\u00edvat na aktu\u00e1ln\u00ed zad\u00e1n\u00ed.\r\n

\r\n ", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 7, + "fields": { + "url": "/jak-resit/", + "title": "Jak \u0159e\u0161it?", + "content": "

\u010c\u00edm se n\u00e1\u0161 semin\u00e1\u0159 li\u0161\u00ed od v\u011bt\u0161iny ostatn\u00edch sout\u011b\u017e\u00ed, jsou p\u0159\u00edsp\u011bvkov\u00e1 t\u00e9mata. Jedn\u00e1 se o simulaci v\u011bdeck\u00e9 pr\u00e1ce ve smyslu, \u017ee zad\u00e1me jist\u00fd okruh probl\u00e9m\u016f, nad kter\u00fdm m\u016f\u017ee\u0161 n\u00e1sleduj\u00edc\u00ed rok b\u00e1dat. O v\u00fdsledky sv\u00e9 pr\u00e1ce se pak pod\u011bl\u00ed\u0161 s n\u00e1mi a s ostatn\u00edmi \u0159e\u0161iteli a my tvou pr\u00e1ci ohodnot\u00edme. V ka\u017ed\u00e9 s\u00e9rii b\u00fdvaj\u00ed t\u00e9mata roz\u0161i\u0159ov\u00e1na, nav\u00edc jsou n\u011bkter\u00e9 zadan\u00e9 probl\u00e9my omezeny term\u00ednem odesl\u00e1n\u00ed, proto je pot\u0159eba sv\u00e9 v\u00fdsledky pos\u00edlat u\u017e pr\u016fb\u011b\u017en\u011b. Na ka\u017ed\u00fd ro\u010dn\u00edk t\u00e9mat vypisujeme p\u011bt a\u017e \u0161est.

\r\n\r\n

\u0158e\u0161en\u00ed, kter\u00e9 n\u00e1m po\u0161le\u0161, m\u016f\u017ee b\u00fdt dvou r\u016fzn\u00fdch typ\u016f:

\r\n\r\n

\u00dalohy

\r\n\r\n

V r\u00e1mci ka\u017ed\u00e9ho t\u00e9matu b\u00fdv\u00e1 zad\u00e1na jedna nebo dv\u011b men\u0161\u00ed \u00falohy, kter\u00e9 dan\u00fd probl\u00e9m ur\u010dit\u00fdm zp\u016fsobem rozv\u00edj\u00ed. Tyto \u00falohy b\u00fdvaj\u00ed trochu t\u011b\u017e\u0161\u00ed ne\u017e obvykl\u00e9 \u0161koln\u00ed, jejich \u0159e\u0161en\u00ed \u010dasto vy\u017eaduje bu\u010f hlub\u0161\u00ed zamy\u0161len\u00ed nebo n\u011bjak\u00fd trik. St\u0159edo\u0161kolsk\u00e9 znalosti by na n\u011b ale m\u011bly sta\u010dit. Odevzd\u00e1v\u00e1n\u00ed \u00faloh se omezuje term\u00ednem odesl\u00e1n\u00ed, pot\u00e9 b\u00fdv\u00e1 zve\u0159ejn\u011bno vzorov\u00e9 \u0159e\u0161en\u00ed. U ka\u017ed\u00e9 \u00falohy je uveden po\u010det bod\u016f za spr\u00e1vn\u00e9 \u0159e\u0161en\u00ed. P\u0159im\u011b\u0159enou \u010d\u00e1st z t\u011bchto bod\u016f lze z\u00edskat i za ne\u00fapln\u00e9 \u0159e\u0161en\u00ed. A naopak za velmi zaj\u00edmav\u00e9 nebo elegantn\u00ed \u0159e\u0161en\u00ed m\u016f\u017ee\u0161 dostat i bodovou pr\u00e9mii.

\r\n\r\n

\u010cl\u00e1nky

\r\n\r\n

Syst\u00e9m t\u00e9mat poskytuje p\u0159\u00edle\u017eitost pro podrobn\u011bj\u0161\u00ed rozbor dan\u00e9ho okruhu probl\u00e9m\u016f. V\u00fdsledek takov\u00e9 pr\u00e1ce v\u0161ak vy\u017eaduje o n\u011bco v\u00edc prostoru ne\u017eli klasick\u00e9 \u0159e\u0161en\u00ed, proto je tv\u00fdm \u00fakolem napsat \u010dl\u00e1nek zab\u00fdvaj\u00edc\u00ed se probl\u00e9mem, kter\u00fd sis vybral. M\u016f\u017ee to b\u00fdt z\u00e1znam o proveden\u00e9m experimentu, teoretick\u00e9m v\u00fdpo\u010dtu \u010di \u00favaze, napsan\u00e9m programu \u010di o dal\u0161\u00edch (podle tebe zaj\u00edmav\u00fdch) ot\u00e1zk\u00e1ch z dan\u00e9ho okruhu. 

\r\n\r\n

Jak na to?

\r\n\r\n

Vy\u0159e\u0161 podprobl\u00e9m

\r\n\r\n

Vyber si n\u011bkter\u00fd z navrhovan\u00fdch podprobl\u00e9m\u016f, kter\u00fdm se chce\u0161 zab\u00fdvat, p\u0159\u00edpadn\u011b si navrhni podprobl\u00e9m vlastn\u00ed (to b\u00fdv\u00e1 ohodnoceno bodov\u00fdm bonusem). Podprobl\u00e9m pak vy\u0159e\u0161 podobn\u011b jako \u00falohu z \u010d\u00edsla. Podrobn\u00e9 \u0159e\u0161en\u00ed n\u011bkter\u00e9ho z podprobl\u00e9m\u016f bude bodov\u011b hodnoceno v\u00fdrazn\u011b l\u00e9pe ne\u017e souhrnn\u00fd \u010dl\u00e1nek kr\u00e1tce zmi\u0148uj\u00edc\u00ed kdeco. I \u010d\u00e1ste\u010dn\u00e9 \u0159e\u0161en\u00ed je lep\u0161\u00ed ne\u017e \u017e\u00e1dn\u00e9. Sv\u00e9 \u0159e\u0161en\u00ed pak hezky sepi\u0161, aby m\u011blo formu \u010dl\u00e1nku, a \u010dl\u00e1nek n\u00e1m po\u0161li. Vedouc\u00ed t\u00e9matu ho pak ohodnot\u00ed, p\u0159\u00edpadn\u011b zkoriguje a publikuje na webu \u010di dokonce v \u010d\u00edsle. \u010c\u00edm bl\u00ed\u017ee bude forma tv\u00e9ho p\u0159\u00edsp\u011bvku publikovateln\u00e9mu \u010dl\u00e1nku, t\u00edm lep\u0161\u00edho bodov\u00e9ho ohodnocen\u00ed dos\u00e1hne\u0161. Moder\u00e1tor t\u00e9matu ho pak ohodnot\u00ed, p\u0159\u00edpadn\u011b zkoriguje a publikuje na webu \u010di dokonce v \u010d\u00edsle. \u010c\u00edm bl\u00ed\u017ee bude forma tv\u00e9ho p\u0159\u00edsp\u011bvku publikovateln\u00e9mu \u010dl\u00e1nku, t\u00edm lep\u0161\u00edho bodov\u00e9ho ohodnocen\u00ed dos\u00e1hne\u0161.

\r\n\r\n

Inspiruj se

\r\n\r\n

Velmi d\u016fle\u017eitou vlastnost\u00ed t\u00e9mat je, \u017ee m\u016f\u017ee\u0161 na \u010dl\u00e1nky ostatn\u00edch reagovat \u2013 rozv\u00edjet je, nebo naopak bo\u0159it jejich p\u0159edstavy. Proto se hod\u00ed poslat tak\u00e9 \u010d\u00e1ste\u010dn\u00e1 \u0159e\u0161en\u00ed, post\u0159ehy, nebo n\u00e1pady na dal\u0161\u00ed podprobl\u00e9my, kter\u00e9 t\u0159eba nezvl\u00e1dne\u0161 vy\u0159e\u0161it s\u00e1m. Takov\u00e9to p\u0159\u00edsp\u011bvky d\u00e1vaj\u00ed prostor ostatn\u00edm a mohou je d\u00e1l inspirovat \u2013 ostatn\u00ed zase sv\u00fdmi p\u0159\u00edsp\u011bvky mohou inspirovat tebe.

\r\n\r\n

Proto\u017ee v\u00edc hlav v\u00edc v\u00ed, m\u016f\u017eete na t\u00e9matech pracovat i ve skupin\u00e1ch.

\r\n\r\n\r\n

Nad n\u00e1pady k t\u00e9mat\u016fm m\u016f\u017ee\u0161 p\u0159em\u00fd\u0161let cel\u00fd rok a\u017e do term\u00ednu odevzd\u00e1n\u00ed posledn\u00ed s\u00e9rie \u00faloh. Samoz\u0159ejm\u011b, \u010d\u00edm d\u0159\u00edve n\u00e1m \u010dl\u00e1nek po\u0161le\u0161, t\u00edm d\u0159\u00edve na n\u011bj ostatn\u00ed budou moci zareagovat.

\r\n\r\n

Pi\u0161 hezk\u00e9 \u010dl\u00e1nky

\r\n\r\n

\u010cl\u00e1nek k t\u00e9matu by m\u011bl po obsahov\u00e9 a form\u00e1ln\u00ed str\u00e1nce odpov\u00eddat v\u011bdeck\u00e9mu \u010dl\u00e1nku. M\u016f\u017ee\u0161 se pod\u00edvat na stru\u010dn\u00fd p\u0159ehled toho, jak by m\u011bl takov\u00fd v\u011bdeck\u00fd \u010dl\u00e1nek vypadat.

\r\n\r\n

Pro\u010d t\u00e9mata?

\r\n\r\n

T\u00e9mata vytv\u00e1\u0159ej\u00ed prostor pro vlastn\u00ed tv\u016fr\u010d\u00ed (\u010dasto v\u011bdeckou) \u010dinnost, jej\u00edm\u017e smyslem je krom jin\u00e9ho p\u0159in\u00e9st ostatn\u00edm \u0159e\u0161itel\u016fm nov\u00e9 podn\u011bty a inspirovat je k dal\u0161\u00edm n\u00e1pad\u016fm. Krom\u011b samotn\u00e9ho b\u00e1d\u00e1n\u00ed je d\u016fle\u017eit\u00e1 i komunikace mezi lidmi, kter\u00e1 je obvykle zprost\u0159edkov\u00e1na odborn\u00fdmi \u010dasopisy a v\u011bdeck\u00fdmi konferencemi. \u010casopis M&M je ur\u010den pr\u00e1v\u011b pro p\u00edsemnou komunikaci. \u00dastn\u00ed formu prezentace si m\u016f\u017ee\u0161 vyzkou\u0161et na na\u0161em soust\u0159ed\u011bn\u00ed, kde se tradi\u010dn\u011b kon\u00e1 mal\u00e1 v\u011bdeck\u00e1 konference.

\r\n\r\n

Jak poslat \u0159e\u0161en\u00ed

\r\n\r\n

Sv\u00e1 \u0159e\u0161en\u00ed m\u016f\u017ee\u0161 poslat bu\u010f elektronicky na n\u00e1\u0161 e-mail mam@matfyz.cz, nebo po\u0161tou na na\u0161i adresu. Pokud pot\u0159ebuje\u0161 k \u0159e\u0161en\u00ed p\u0159ilo\u017eit n\u011bjak\u00fd hodn\u011b velk\u00fd soubor, pou\u017eij n\u011bkterou voln\u011b dostupnou slu\u017ebu pro sd\u00edlen\u00ed soubor\u016f (DropboxGoogle Drive, \u2026) nebo n\u00e1s kontaktuj na e-mailu mam@matfyz.cz a p\u0159ed\u00e1n\u00ed domluv\u00edme.

\r\n\r\n

Pokud pos\u00edl\u00e1\u0161 \u0159e\u0161en\u00ed elektronicky, v\u011bz, \u017ee n\u00e1s daleko v\u00edce pot\u011b\u0161\u00ed pdfko s textem ne\u017e vyfocen\u00e9 ru\u010dn\u011b psan\u00e9 \u0159e\u0161en\u00ed. Ka\u017edou \u00falohu pros\u00edm po\u0161li v samostatn\u00e9m souboru resp. na samostatn\u00e9m list\u011b A4, aby si \u00falohy mohli rozd\u011blit r\u016fzn\u00ed opravuj\u00edc\u00ed. Na ka\u017ed\u00fd list uve\u010f svoje jm\u00e9no a \u010d\u00edslo \u00falohy \u010di t\u00e9matu. Na tvou po\u0161tovn\u00ed adresu ti pak budou zdarma chodit dal\u0161\u00ed \u010d\u00edsla na\u0161eho \u010dasopisu.

\r\n\r\n

Ke sv\u00e9mu prvn\u00edmu \u0159e\u0161en\u00ed p\u0159ilo\u017e pros\u00edm tak\u00e9 sv\u00e9 jm\u00e9no, adresu, e-mail, \u0161kolu a rok maturity. Pokud chce\u0161 jet na soust\u0159ed\u011bn\u00ed, uve\u010f pros\u00edm i telefon. A neboj, tyto \u00fadaje budeme vyu\u017e\u00edvat pouze pro pot\u0159eby M&M. Mimo \u00fadaj\u016f na v\u00fdsledkov\u00e9 listin\u011b (jm\u00e9no, \u0161kola, ro\u010dn\u00edk) je nebudeme nikde zve\u0159ej\u0148ovat.

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 8, + "fields": { + "url": "/co-je-MaM/FAQ/", + "title": "\u010casto kladen\u00e9 dotazy", + "content": "

Jaký je smysl M&M?

\r\n\r\n

Smyslem M&M je pomáhat student\u016fm s nadáním na matematiku, fyziku \u010di informatiku rozvíjet jejich schopnosti a zprost\u0159edkovávat jejich setkávání a navazování p\u0159átelství.

\r\n\r\n

Jsem student st\u0159ední školy, posledních ro\u010dník\u016f základní školy \u010di ekvivalentních ro\u010dník\u016f víceletého gymnázia: Co mi M&M m\u016f\u017ee p\u0159inést?

\r\n\r\n

Pokud t\u011b zajímá matematika, fyzika nebo informatika, m\u016f\u017eeme ti nabídnout zajímavé podn\u011bty k p\u0159emýšlení. A pokud se zú\u010dastníš n\u011bkterého z našich soust\u0159ed\u011bní, pak i p\u0159átelský kolektiv fajn lidí podobných tob\u011b.

\r\n\r\n

Jsem u\u010ditel matematiky, fyziky \u010di informatiky na st\u0159ední škole: K \u010demu mi M&M m\u016f\u017ee být dobré?

\r\n\r\n

Jestli\u017ee nabídnete svým student\u016fm M&M k \u0159ešení, m\u016f\u017ee je náš \u010dasopis motivovat k dalšímu rozvoji. Náš archiv úloh a témat m\u016f\u017eete pou\u017eít jako zdroj náro\u010dn\u011bjších úloh pro nadané \u017eáky. Naše úlohy jsou \u0159ešitelné se st\u0159edoškolskými znalostmi – s trochou p\u0159emýšlení.

\r\n\r\n

Jsem rodi\u010d studenta nadaného na matematiku, fyziku \u010di informatiku: Je M&M pro moje dít\u011b dobré?

\r\n\r\n

Jednozna\u010dn\u011b ano – pokud o nás samo bude stát. Primárn\u011b m\u016f\u017eeme Vaše dít\u011b odborn\u011b rozvíjet. Náš kolektiv je navíc velmi otev\u0159ený a dovede p\u0159ijmout i mláde\u017e, která má problém s integrací do b\u011b\u017eného školního kolektivu.

\r\n\r\n

Ješt\u011b n\u011bjaké dotazy?

\r\n\r\n

Sem s nimi!

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 9, + "fields": { + "url": "/soustredeni/", + "title": "Informace", + "content": "

Pro na\u0161e nejlep\u0161\u00ed \u0159e\u0161itele po\u0159\u00e1d\u00e1me dvakr\u00e1t do roka t\u00fddenn\u00ed soust\u0159ed\u011bn\u00ed pln\u00e9 odborn\u00e9ho programu i nejr\u016fzn\u011bj\u0161\u00ed z\u00e1bavy.

\r\n\r\n\r\n

Pro\u010d jet na soust\u0159ed\u011bn\u00ed?

\r\n\r\n

P\u0159edn\u00e1\u0161ky

\r\n\r\n

V\u011bt\u0161inou t\u011b ka\u017ed\u00fd den \u010dekaj\u00ed dv\u011b devades\u00e1timinutov\u00e9 p\u0159edn\u00e1\u0161ky. Vybrat si obvykle m\u016f\u017ee\u0161 mezi matematikou, fyzikou a informatikou, proto\u017ee se konaj\u00ed t\u0159i p\u0159edn\u00e1\u0161ky z\u00e1rove\u0148. N\u011bkter\u00e9 p\u0159edn\u00e1\u0161ky jsou leh\u010d\u00ed, jin\u00e9 t\u011b\u017e\u0161\u00ed, obecn\u011b je ale jejich \u00farove\u0148 vhodn\u00e1 pr\u00e1v\u011b pro zv\u00eddav\u00e9 st\u0159edo\u0161kol\u00e1ky. P\u0159edn\u00e1\u0161\u00edme jak klasick\u00e1 t\u00e9mata, tak t\u00e9mata nev\u0161edn\u00ed, z\u00e1kulisn\u00ed \u010di dokonce obskurn\u00ed. Kdy\u017e bude\u0161 organiz\u00e1tory hodn\u011b prosit, mo\u017en\u00e1 se dostane i na n\u011bjakou \u010dernou magii!

\r\n\r\n

Krom toho p\u0159edn\u00e1\u0161\u00edme i na po\u017e\u00e1d\u00e1n\u00ed \u2013 sta\u010d\u00ed, kdy\u017e si vybere\u0161 t\u00e9ma, kter\u00e9 t\u011b zaj\u00edm\u00e1, a oslov\u00ed\u0161 toho spr\u00e1vn\u00e9ho organiz\u00e1tora.

\r\n\r\n

Lid\u00e9

\r\n\r\n

Pozn\u00e1\u0161 lidi, pro kter\u00e9 je p\u0159em\u00fd\u0161len\u00ed obl\u00edbenou \u010dinnost\u00ed a pro kter\u00e9 matematika nen\u00ed sprost\u00e9 slovo. P\u0159edev\u0161\u00edm to jsou ale lidi, kte\u0159\u00ed se r\u00e1di bav\u00ed a se kter\u00fdmi si u\u017eije\u0161 mnoho legrace u j\u00eddla, b\u011bhem her, na v\u00fdlet\u011b, jen tak, p\u0159i hran\u00ed na kytaru nebo p\u0159i \u0161ar\u00e1d\u011bn\u00ed (pokud nev\u00ed\u0161, co tohle slovo znamen\u00e1, je na \u010dase to zjistit!).

\r\n\r\n

Konfery

\r\n\r\n

Konfery jsou na\u0161\u00ed specialitou. Ve skupin\u011b \u00fa\u010dastn\u00edk\u016f a pod veden\u00edm zku\u0161en\u00e9ho organiz\u00e1tora m\u016f\u017ee\u0161 zkusit pracovat na zadan\u00e9m probl\u00e9mu a v\u00fdsledky pak ostatn\u00edm prezentovat na mal\u00e9 v\u011bdeck\u00e9 konferenci. Pr\u00e1ce na konfe\u0159e je velmi podobn\u00e1 skute\u010dn\u00e9 v\u011bdeck\u00e9 pr\u00e1ci. M\u00e1me za sebou nap\u0159\u00edklad stavbu katapultu, po\u010d\u00edta\u010dovou synt\u00e9zu zvuku \u010di tropickou geometrii.

\r\n\r\n

Hry

\r\n\r\n

M\u00e1me pro tebe p\u0159ipravenou celou \u0159adu denn\u00edch i no\u010dn\u00edch her, uvnit\u0159 i venku, strategick\u00fdch i ak\u010dn\u00edch. A n\u011bkdy tohle v\u0161echno dohromady. Chceme, aby sis mohl/a zkusit \u010dinnosti, ke kter\u00fdm se b\u011b\u017en\u011b nedostane\u0161. St\u0159elba z luku, lezen\u00ed po skal\u00e1ch, slackline \u010di celono\u010dn\u00ed \u0161ifrova\u010dka? Nen\u00ed probl\u00e9m!

\r\n\r\n

Legenda

\r\n\r\n

Ka\u017ed\u00e9 soust\u0159ed\u011bn\u00ed m\u00e1 sv\u00e9 vlastn\u00ed prost\u0159ed\u00ed \u010di p\u0159\u00edb\u011bh, kter\u00fd j\u00edm prov\u00e1z\u00ed. U\u017e jsme byli ve starov\u011bk\u00e9m \u0158ecku \u010di pod podlahou obcho\u010f\u00e1ku, cestovali jsme \u010dasem a tak\u00e9 jsme bojovali s krvela\u010dn\u00fdmi zmutovan\u00fdmi tule\u0148\u00e1tky, kter\u00e1 se nakonec uk\u00e1zala b\u00fdt filma\u0159sk\u00fdm trikem. Co n\u00e1s \u010dek\u00e1 p\u0159\u00ed\u0161t\u011b?

\r\n\r\n

Absence ve \u0161kole

\r\n\r\n

Ne\u017e pojede\u0161 na soust\u0159ed\u011bn\u00ed, po\u0161leme ti ofici\u00e1ln\u00ed omluvenku od MFF UK. Jeliko\u017e je soust\u0159ed\u011bn\u00ed pln\u00e9 odborn\u00e9ho programu, v\u011bt\u0161ina \u0161kol na\u0161e \u0159e\u0161itele bez probl\u00e9mu uvol\u0148uje. N\u011bkter\u00e9 \u0161koly dokonce \u00fa\u010dast na soust\u0159ed\u011bn\u00ed nezapo\u010d\u00edt\u00e1vaj\u00ed do absence. V\u017edy je ale dobr\u00e9 se informovat, jak \u00fa\u010dast na podobn\u00fdch akc\u00edch \u0159e\u0161\u00ed tvoje \u0161kola, a p\u0159\u00edpadn\u011b se osobn\u011b domluvit s \u0159editelem \u010di \u0159editelkou.

\r\n\r\n

Kapacita soust\u0159ed\u011bn\u00ed

\r\n\r\n

Proto\u017ee chceme zachovat p\u0159\u00e1telskou a komorn\u00ed atmosf\u00e9ru soust\u0159ed\u011bn\u00ed, zveme na soust\u0159ed\u011bn\u00ed zhruba dvacet nej\u00fasp\u011b\u0161n\u011bj\u0161\u00edch \u0159e\u0161itel\u016f koresponden\u010dn\u00edho semin\u00e1\u0159e. N\u011bkolik dal\u0161\u00edch \u0159e\u0161itel\u016f zveme jako n\u00e1hradn\u00edky pro p\u0159\u00edpad, \u017ee by n\u011bkte\u0159\u00ed pozvan\u00ed nemohli. Pokud t\u011b na soust\u0159ed\u011bn\u00ed nepozveme, nezoufej a zkus v p\u0159\u00ed\u0161t\u00edm p\u016flroce v\u00edc \u0159e\u0161it t\u00e9mata. Dostat se mezi nejlep\u0161\u00edch dvacet \u0159e\u0161itel\u016f je s trochou p\u00edle hra\u010dka.

\r\n\r\n

 

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 11, + "fields": { + "url": "/soustredeni/pripravujeme/", + "title": "P\u0159ipravujeme", + "content": "

Pozdimn\u00ed soust\u0159ed\u011bn\u00ed

\r\n\r\n

se bude konat v term\u00ednu od 12. do 20. \u0159\u00edjna 2019.

", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 12, + "fields": { + "url": "/soustredeni/probehlo/", + "title": "Prob\u011bhlo", + "content": "

Tady se pracuje

\r\n\r\n

Na této stránce velmi intenzivn\u011b pracujeme. Za do\u010dasnou nedostupnost se omlouváme. Zkuste p\u0159ejít na titulní stránku nebo se podívat na aktuální zadání.

\r\n\r\n

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 16, + "fields": { + "url": "/zadani/temata/", + "title": "T\u00e9mata", + "content": "

T\u00e9mata jsou texty nejen z oblasti matematiky, fyziky a informatiky, kter\u00e9 popisuj\u00ed n\u011bjak\u00fd probl\u00e9m a jsou doprov\u00e1zeny n\u00e1vodn\u00fdmi \u00falohami. Va\u0161\u00edm \u00fakolem je zamyslet se nad dan\u00fdm probl\u00e9mem a sepsat va\u0161e \u00favahy ve form\u011b kr\u00e1tk\u00e9ho textu.

\r\n\r\n

Jak \u0159e\u0161it t\u00e9ma?

\r\n\r\n

 

\r\n\r\n

AKTU\u00c1LN\u00cd T\u00c9MATA

", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 17, + "fields": { + "url": "/zadani/aktualni-cislo/", + "title": "Aktu\u00e1ln\u00ed \u010d\u00edslo", + "content": "

Tady pat\u0159í aktuální \u010díslo.

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 18, + "fields": { + "url": "/zadani/vysledkova-listina/", + "title": "V\u00fdsledkov\u00e1 listina", + "content": "

Tady se pracuje

\r\n\r\n

Na této stránce velmi intenzivn\u011b pracujeme. Za do\u010dasnou nedostupnost se omlouváme. Zkuste p\u0159ejít na titulní stránku nebo se podívat na aktuální zadání.

\r\n\r\n

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 19, + "fields": { + "url": "/clanky/org/", + "title": "Organiz\u00e1torsk\u00e9 \u010dl\u00e1nky", + "content": "

Tady se pracuje

\r\n

\r\n Na t\u00e9to str\u00e1nce velmi intenzivn\u011b pracujeme.\r\n Za do\u010dasnou nedostupnost se omlouv\u00e1me.\r\n Zkuste p\u0159ej\u00edt na tituln\u00ed str\u00e1nku\r\n nebo se pod\u00edvat na aktu\u00e1ln\u00ed zad\u00e1n\u00ed.\r\n

\r\n ", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 20, + "fields": { + "url": "/clanky/resitel/", + "title": "\u0158e\u0161itelsk\u00e9 \u010dl\u00e1nky", + "content": "

\u0158e\u0161itelsk\u00e9 \u010dl\u00e1nky

\r\n\r\n

Na t\u00e9to str\u00e1nce se budou postupn\u011b objevovat r\u016fznorod\u00e9 \u010dl\u00e1nky od na\u0161ich \u0159e\u0161itel\u016f.

\r\n\r\n

Obsah:

\r\n\r\n

Ond\u0159ej Knopp: Flatland (ji\u017e brzy)

\r\n\r\n

 

\r\n\r\n

 

\r\n\r\n
\r\n

Ond\u0159ej Knopp: Flatland (15b)

\r\n\r\n

 

\r\n\r\n
\r\n

 

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 21, + "fields": { + "url": "/clanky/jak-psat-vedecky-clanek/", + "title": "Jak ps\u00e1t v\u011bdeck\u00fd \u010dl\u00e1nek", + "content": "

Pro psan\u00ed v\u011bdeck\u00fdch \u010dl\u00e1nk\u016f byla vytvo\u0159ena n\u011bkter\u00e1 obecn\u00e1 pravidla, kter\u00e1 usnad\u0148uj\u00ed jejich \u010ditelnost a mo\u017enost vyhledat pot\u0159ebn\u00e9 informace. Na tomto m\u00edst\u011b bychom ti cht\u011bli uk\u00e1zat, jak by m\u011bl takov\u00fd v\u011bdeck\u00fd \u010dl\u00e1nek vypadat po obsahov\u00e9 i form\u00e1ln\u00ed str\u00e1nce.

\r\n\r\n

O \u010dem ps\u00e1t?

\r\n\r\n

Kvalita v\u011bdeck\u00e9ho \u010dl\u00e1nku z\u00e1vis\u00ed hlavn\u011b na tom, kolik nov\u00fdch poznatk\u016f p\u0159in\u00e1\u0161\u00ed. Je velmi vhodn\u00e9, aby obsahem bylo jen to, co m\u016f\u017ee zaj\u00edmat ostatn\u00ed \u0159e\u0161itele dan\u00e9ho t\u00e9matu.

\r\n\r\n

D\u00e1le plat\u00ed pravidlo, \u017ee jeden \u010dl\u00e1nek by se m\u011bl t\u00fdkat pr\u00e1v\u011b jednoho probl\u00e9mu. Pokud p\u00ed\u0161e\u0161 o v\u00edce probl\u00e9mech najednou, zamysli se nad t\u00edm, jestli by nebylo mo\u017en\u00e9 napsat v\u00edce \u010dl\u00e1nk\u016f. \u010c\u00edm stru\u010dn\u011bj\u0161\u00ed a p\u0159ehledn\u011bj\u0161\u00ed \u010dl\u00e1nek je a \u010d\u00edm v\u00edce nov\u00fdch poznatk\u016f na tak omezen\u00e9m prostoru obsahuje, t\u00edm \u010diteln\u011bj\u0161\u00ed a zaj\u00edmav\u011bj\u0161\u00ed je pro ostatn\u00ed \u0159e\u0161itele.

\r\n\r\n

Struktura \u010dl\u00e1nku

\r\n\r\n

Ka\u017ed\u00fd \u010dl\u00e1nek by m\u011bl m\u00edt vhodn\u00fd n\u00e1zev (titulek), kter\u00fd dok\u00e1\u017ee p\u0159it\u00e1hnout \u010dten\u00e1\u0159e, kte\u0159\u00ed se zaj\u00edmaj\u00ed o dan\u00e9 t\u00e9ma. Nadpis je ta \u010d\u00e1st \u010dl\u00e1nku, kter\u00e9 si ka\u017ed\u00fd v\u0161imne hned na prvn\u00ed pohled. Nepodce\u0148uj jeho zn\u011bn\u00ed a dej pozor na to, aby p\u0159esn\u011b vystihoval to, \u010demu se v \u010dl\u00e1nku v\u011bnuje\u0161.

\r\n\r\n

\u00favodu bys m\u011bl popsat probl\u00e9m, kter\u00fdm ses zab\u00fdval, d\u00e1le na co a na koho jsi navazoval a tak\u00e9 pro\u010d ses dan\u00fdm probl\u00e9mem zab\u00fdval. V\u011bt\u0161inou je zde uvedena hypot\u00e9za, kter\u00e1 je dokazov\u00e1na v samotn\u00e9m \u010dl\u00e1nku. Sou\u010d\u00e1st\u00ed \u00favodu je i motivace \u010dten\u00e1\u0159e a prvn\u00ed p\u0159ibl\u00ed\u017een\u00ed podstaty probl\u00e9mu.

\r\n\r\n

Za \u00favodem pak pokra\u010duje podrobn\u011bj\u0161\u00ed popis postup\u016f, kter\u00e9 vyu\u017e\u00edv\u00e1\u0161, a zd\u016fvodn\u011bn\u00ed tv\u00fdch tvrzen\u00ed.

\r\n\r\n

Kvalita v\u011bdeck\u00e9ho \u010dl\u00e1nku je d\u00e1na p\u0159edev\u0161\u00edm t\u00edm, jakou m\u00e1 informa\u010dn\u00ed hodnotu. Informacemi v \u010dl\u00e1nku mohou b\u00fdt jak v\u00fdsledky vlastn\u00edho v\u00fdzkumu, tak p\u0159ehledn\u00e9 shrnut\u00ed a zpracov\u00e1n\u00ed jinde uve\u0159ejn\u011bn\u00fdch v\u00fdsledk\u016f t\u00fdkaj\u00edc\u00edch se zkouman\u00e9ho probl\u00e9mu. Takov\u00e9mu zpracov\u00e1n\u00ed se \u0159\u00edk\u00e1 re\u0161er\u0161e a pokud podobn\u00e9 shrnut\u00ed je\u0161t\u011b neexistuje, m\u016f\u017ee b\u00fdt p\u0159\u00ednosn\u00e9 stejn\u011b jako vlastn\u00ed nov\u00fd v\u00fdzkum.

\r\n\r\n

Je d\u016fle\u017eit\u00e9, aby v\u0161echna tvrzen\u00ed uveden\u00e1 v \u010dl\u00e1nku byla dostate\u010dn\u011b podlo\u017eena fakty. \u010cl\u00e1nek tedy nelze zalo\u017eit na n\u011b\u010dem, o \u010dem si jen mysl\u00ed\u0161, \u017ee by to mohlo platit. Jak\u00e1koliv slo\u017eit\u011bj\u0161\u00ed tvrzen\u00ed v \u010dl\u00e1nku by m\u011bla b\u00fdt podpo\u0159ena bu\u010f odkazem na literaturu, anebo d\u016fkazem \u010di experimentem. M\u011bly by b\u00fdt tak\u00e9 uvedeny v\u0161echny p\u0159edpoklady pou\u017eit\u00fdch tvrzen\u00ed a teori\u00ed a v p\u0159\u00edpad\u011b experimentu podm\u00ednky, za kter\u00fdch byl prov\u00e1d\u011bn.

\r\n\r\n

z\u00e1v\u011bru je pak vhodn\u00e9 znovu shrnout hlavn\u00ed v\u00fdsledky sv\u00e9 pr\u00e1ce a p\u0159\u00edpadn\u011b polo\u017eit n\u011bjak\u00e9 dal\u0161\u00ed ot\u00e1zky souvisej\u00edc\u00ed s t\u00e9matem, jejich\u017e \u0159e\u0161en\u00ed by mohlo navazovat na tv\u016fj \u010dl\u00e1nek.

\r\n\r\n

Na \u00fapln\u00e9m konci se pak uv\u00e1d\u00ed seznam pou\u017eit\u00e9 literatury a literatury, na kterou bylo v \u010dl\u00e1nku odkazov\u00e1no. Obvykle se v \u010dl\u00e1nku pou\u017eije jen odkaz, nap\u0159. \u201e... Jak je uvedeno v [1], m\u016f\u017eeme v\u00fdraz upravit...\u201c V seznamu literatury se pak uvedou pln\u00e9 \u00fadaje o knize, \u010dl\u00e1nku \u010di internetov\u00e9 adrese. Dodr\u017euje se n\u00e1sleduj\u00edc\u00ed sch\u00e9ma:

\r\n\r\n

 

\r\n\r\n

[#] Autor. N\u00e1zev d\u00edla: podn\u00e1zev d\u00edla. \u010c\u00edslo vyd\u00e1n\u00ed. M\u00edsto vyd\u00e1n\u00ed: Ozna\u010den\u00ed nakladatele, Rok vyd\u00e1n\u00ed. Po\u010det str\u00e1nek. ISBN.

\r\n\r\n

Nap\u0159\u00edklad:
\r\n[1] O. Lepil, Z. Krupka. Fyzika pro gymn\u00e1zia: Optika. 2. vyd\u00e1n\u00ed. Praha: Prometheus, 1996. 167 s. ISBN 80\u201385849\u201371\u20132.

\r\n\r\n

Jednotliv\u00e9 \u010d\u00e1sti kr\u00e1tk\u00e9ho \u010dl\u00e1nku sta\u010d\u00ed odd\u011blit odstavci. Pokud se jedn\u00e1 o rozs\u00e1hlej\u0161\u00ed p\u0159\u00edsp\u011bvek, je lep\u0161\u00ed rozd\u011blit ho na n\u011bkolik sekc\u00ed s vhodn\u00fdmi podnadpisy.

\r\n\r\n

Jazyk a styl \u010dl\u00e1nku

\r\n\r\n

V odborn\u00e9m \u010dl\u00e1nku je nutn\u00e9 se vyjad\u0159ovat p\u0159esn\u011b a jednozna\u010dn\u011b. Je pot\u0159eba pou\u017e\u00edvat spr\u00e1vn\u00e9 term\u00edny, aby byl \u010dl\u00e1nek spr\u00e1vn\u011b pochopen ostatn\u00edmi \u010dten\u00e1\u0159i. Pokud pou\u017e\u00edv\u00e1\u0161 pom\u011brn\u011b neobvykl\u00fd pojem nebo zav\u00e1d\u00ed\u0161 n\u011bjak\u00fd nov\u00fd, tak je pot\u0159eba jej p\u0159esn\u011b definovat. V\u017edy si po\u0159\u00e1dn\u011b uv\u011bdom, kdo bude tv\u016fj \u010dl\u00e1nek \u010d\u00edst. Na tom tak\u00e9 z\u00e1le\u017e\u00ed, jak\u00e9 term\u00edny pou\u017eije\u0161 a jak moc podrobn\u011b je bude\u0161 vysv\u011btlovat.

\r\n\r\n

Aby byl \u010dl\u00e1nek v\u016fbec publikovateln\u00fd, m\u011bl by b\u00fdt naps\u00e1n bez jazykov\u00fdch a stylistick\u00fdch chyb. V \u010dl\u00e1nku, kter\u00fd je publikov\u00e1n, a tedy jej \u010dte \u0161ir\u0161\u00ed skupina lid\u00ed, pou\u017e\u00edv\u00e1me spisovn\u00fd jazyk. V M&Mku m\u016f\u017ee\u0161 ps\u00e1t \u010desky nebo slovensky.

\r\n\r\n

 

\r\n\r\n

Douf\u00e1me, \u017ee ti tento n\u00e1vod p\u0159i psan\u00ed \u010dl\u00e1nk\u016f pom\u016f\u017ee, a \u017ee i d\u00edky n\u011bmu na\u0161e t\u00e9m\u00e1tka z\u016fstanou p\u0159ehledn\u00e1, \u010diteln\u00e1 a zaj\u00edmav\u00e1.

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 22, + "fields": { + "url": "/co-je-MaM/kontakt/", + "title": "Kontakt", + "content": "

Sv\u00e1 \u0159e\u0161en\u00ed \u010di p\u0159\u00edpadn\u00e9 dotazy n\u00e1m m\u016f\u017eete pos\u00edlat bu\u010f klasickou, nebo elektronickou po\u0161tou:

\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\t

Adresa redakce:

\r\n\r\n\t\t\t

M&M, OPMK MFF UK
\r\n\t\t\tKe Karlovu 3
\r\n\t\t\t121 16 Praha 2

\r\n\t\t\t
\r\n\t\t\t

E-mailmam@matfyz.cz

\r\n\r\n\t\t\t

Facebook: Koresponden\u010dn\u00ed semin\u00e1\u0159 M&M

\r\n\r\n\t\t\t

Google Kalend\u00e1\u0159: casopis.mam@gmail.com

\r\n\t\t\t
\r\n\r\n

 

\r\n\r\n

B\u011bhem \u0161koln\u00edho roku je velk\u00e1 \u010d\u00e1st organiz\u00e1tor\u016f k zasti\u017een\u00ed na koleji 17. listopadu \u010di jinde po Praze.

\r\n\r\n

Adresa koleje:

\r\n\r\n

P\u00e1tkova 3
\r\n182 00, Praha 8

", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 23, + "fields": { + "url": "/odevzdat-reseni/muj-ucet/", + "title": "Odevzdat \u0159e\u0161en\u00ed", + "content": "

Svoje \u0159ešení nám prosím pošli na náš e-mail mam@matfyz.cz, nebo poštou na adresu redakce.

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 24, + "fields": { + "url": "/archiv/vysledky/", + "title": "V\u00fdsledkov\u00e9 listiny", + "content": "

Tady se pracuje

\r\n\r\n

Na této stránce velmi intenzivn\u011b pracujeme. Za do\u010dasnou nedostupnost se omlouváme. Zkuste p\u0159ejít na titulní stránku nebo se podívat na aktuální zadání.

\r\n\r\n

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 25, + "fields": { + "url": "/co-je-MaM/odmeny/", + "title": "Odm\u011bny", + "content": "

Odm\u011bny za um\u00edst\u011bn\u00ed v semin\u00e1\u0159i

\r\n\r\n

Ka\u017ed\u00fd rok oce\u0148ujeme 5 nejlep\u0161\u00edch \u0159e\u0161itel\u016f knihou a deskovou hrou dle jejich v\u00fdb\u011bru.
\r\nLetos m\u016f\u017ee\u0161 b\u00fdt mezi nimi i ty, sta\u010d\u00ed piln\u011b \u0159e\u0161it! :-)
\r\nN\u00e1sleduj\u00edc\u00ed knihy a deskovky si vybralo p\u011bt nej\u00fasp\u011b\u0161n\u011bj\u0161\u00edch \u0159e\u0161itel\u016f 23. ro\u010dn\u00edku semin\u00e1\u0159e:

\r\n\r\n

\"Odm\u011bny

\r\n\r\n

M\u016f\u017ee\u0161 se pod\u00edvat i na odm\u011bny z 22. a 21. ro\u010dn\u00edku.

\r\n\r\n

Odm\u011bny za tituly

\r\n\r\n

 Bc.MM (10 bod\u016f) \u2013 propiska
\r\n\"\"

\r\n\r\n

Mgr.MM (20 bod\u016f) \u2013 reflexn\u00ed p\u00e1ska
\r\n\"\"

\r\n\r\n

Dr.MM (50 bod\u016f) \u2013 hrne\u010dek
\r\n\"\"

\r\n\r\n

Doc.MM (100 bod\u016f) \u2013 deka
\r\n\"\"

\r\n\r\n

Prof.MM (200 bod\u016f) \u2013 mikina

\r\n\r\n

\"\"

\r\n\r\n

Akad.MM (500 bod\u016f) \u2013 tabule s n\u00e1pisem \u201eJsi fakt borec\u201c podepsan\u00e1 v\u0161emi organiz\u00e1tory

\r\n", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +}, +{ + "model": "flatpages.flatpage", + "pk": 27, + "fields": { + "url": "/co-je-MaM/mam-moc-casu/", + "title": "M\u00e1m moc \u010dasu!", + "content": "

Z\u00e1\u017eitkov\u00e9 akce

\r\n\r\n

Letn\u00ed a Zimn\u00ed \u0160kola Matematiky a Fyziky (L\u0160MF, Z\u0160MF) - \u0160MFko je v zim\u011b t\u00fddenn\u00ed, v l\u00e9t\u011b dvout\u00fddenn\u00ed, z\u00e1\u017eitkov\u00e1 akce ur\u010den\u00e1 st\u0159edo\u0161kol\u00e1k\u016fm se z\u00e1jmem o dal\u0161\u00ed sebevzd\u011bl\u00e1n\u00ed. Krom popul\u00e1rn\u011b nau\u010dn\u00fdch p\u0159edn\u00e1\u0161ek se na \u0161mfku prob\u011bhne\u0161 venku, vy\u0159\u00e1d\u00ed\u0161 se ve sn\u011bhu, u\u017eije\u0161 si vesel\u00fd vnit\u0159n\u00ed program a taky se pobav\u00ed\u0161 b\u011bhem spole\u010dn\u00e9ho \u0161ar\u00e1d\u011bn\u00ed, leno\u0161en\u00ed nebo hran\u00ed na kytaru.

\r\n\r\n

InterSoB - InterSoB je z\u00e1bavn\u00e1 a pou\u010dn\u00e1 jednodenn\u00ed sout\u011b\u017e st\u0159edo\u0161kolsk\u00fdch student\u016f, p\u0159i kter\u00e9 m\u00e1te mo\u017enost pod\u00edvat se netradi\u010dn\u00edm zp\u016fsobem do z\u00e1kulis\u00ed Masarykovy univerzity, vyzkou\u0161et si sv\u00e9 schopnosti v mnoha r\u016fzn\u00fdch oblastech, ud\u011blat si s kamar\u00e1dy zaj\u00edmav\u00fd v\u00fdlet po Brn\u011b a v neposledn\u00ed \u0159ad\u011b tak\u00e9 pom\u011b\u0159it svoje s\u00edly s dal\u0161\u00edmi t\u00fdmy.

\r\n\r\n

Dal\u0161\u00ed semin\u00e1\u0159e

\r\n\r\n

Koresponden\u010dn\u00ed Semin\u00e1\u0159 z Programov\u00e1n\u00ed (KSP) - KSP je semin\u00e1\u0159 ur\u010den\u00fd pro studenty st\u0159edn\u00edch a z\u00e1kladn\u00edch \u0161kol, kte\u0159\u00ed maj\u00ed z\u00e1jem nau\u010dit se n\u011bco z oblasti algoritm\u016f, logick\u00fdch \u00faloh, programov\u00e1n\u00ed a informatiky v\u016fbec. Na sv\u00e9 si v\u0161ak p\u0159ijdou i p\u0159\u00edznivci matematiky (a vlastn\u011b libovoln\u00e9ho p\u0159em\u00fd\u0161len\u00ed), je\u017eto oba obory maj\u00ed mnoho spole\u010dn\u00e9ho.

\r\n\r\n

FYzik\u00e1ln\u00ed KOresponden\u010dn\u00ed Semin\u00e1\u0159 (FYKOS) - FYKOS pro v\u00e1s p\u0159edstavuje mo\u017enost si zaj\u00edmav\u00fdm zp\u016fsobem roz\u0161\u00ed\u0159it ch\u00e1p\u00e1n\u00ed fyziky a proniknout do dal\u0161\u00edch, dosud nepoznan\u00fdch, oblast\u00ed t\u00e9to v\u011bdy. C\u00edlem FYKOSu je rozv\u00edjet fyzik\u00e1ln\u00ed my\u0161len\u00ed, proto\u017ee \u010dlov\u011bk, kter\u00fd se um\u00ed nad (nejen fyzik\u00e1ln\u00edmi) probl\u00e9my zamyslet a c\u00edt\u00ed touhu dobrat se k n\u011bjak\u00e9mu \u0159e\u0161en\u00ed, se uplatn\u00ed v\u0161ude, kde si schopnost\u00ed lidsk\u00e9ho mozku cen\u00ed.

\r\n\r\n

Matematick\u00fd koresponden\u010dn\u00ed semin\u00e1\u0159 PraSe (PRA\u017esk\u00fd SEmin\u00e1\u0159) - \u0158e\u0161en\u00edm \u00faloh tohoto semin\u00e1\u0159e z\u00edsk\u00e1\u0161 mnoho matematick\u00fdch znalost\u00ed a nau\u010d\u00ed\u0161 p\u0159esn\u011bji a srozumiteln\u011bji formulovat sv\u00e9 my\u0161lenky a z\u00e1v\u011bry. Semin\u00e1\u0159 je dobrou p\u0159\u00edpravou pro \u00fa\u010dast v nejr\u016fzn\u011bj\u0161\u00edch matematick\u00fdch sout\u011b\u017e\u00edch i pro dal\u0161\u00ed studium matematiky, ale schopnost logick\u00e9ho my\u0161len\u00ed, kterou si m\u016f\u017ee\u0161 procvi\u010dit, se ti v \u017eivot\u011b bude hodit, i kdy\u017e se v n\u011bm t\u0159eba pr\u00e1v\u011b matematice v\u011bnovat nehodl\u00e1\u0161.

\r\n\r\n

Pro mlad\u0161\u00ed sourozence

\r\n\r\n

Pikomat - Pikomat je matematick\u00fd semin\u00e1\u0159 ur\u010den\u00fd \u017e\u00e1k\u016fm \u0161est\u00fdch a\u017e dev\u00e1t\u00fdch t\u0159\u00edd z\u00e1kladn\u00edch \u0161kol a student\u016fm odpov\u00eddaj\u00edc\u00edch ro\u010dn\u00edk\u016f v\u00edcelet\u00fdch gymn\u00e1zi\u00ed. Spo\u010d\u00edv\u00e1 v \u0159e\u0161en\u00ed n\u011bkolika \u00faloh propojen\u00fdch p\u0159\u00edb\u011bhem. Sout\u011b\u017e\u00edc\u00ed ode\u0161le v dan\u00fdch term\u00ednech jednotliv\u00e9 p\u0159\u00edklady dan\u00e9 s\u00e9rie na adresu Pikomatu nebo je odevzd\u00e1 elektronicky. Organiz\u00e1to\u0159i oprav\u00ed do\u0161l\u00e9 \u00falohy, vypracuj\u00ed jejich vzorov\u00e1 \u0159e\u0161en\u00ed a sestav\u00ed v\u00fdsledkovou listinu. Na ja\u0159e se kon\u00e1 soust\u0159ed\u011bn\u00ed pro nejlep\u0161\u00ed \u0159e\u0161itele, v l\u00e9t\u011b pak t\u00e1bor pro v\u0161echny z\u00e1jemce.

\r\n\r\n

V\u00fdfuk (V\u00ddpo\u010dty Fyzik\u00e1ln\u00edch UKol\u016f) - V\u00fdfuk je samostatn\u00fd koresponden\u010dn\u00ed semin\u00e1\u0159 Matfyzu, kter\u00fd spad\u00e1 pod Katedru didaktiky fyziky. B\u011bhem \u0161koln\u00edho roku krom\u011b \u0161esti s\u00e9ri\u00ed semin\u00e1\u0159e organiz\u00e1to\u0159i p\u0159ipravuj\u00ed i podzimn\u00ed a jarn\u00ed setk\u00e1n\u00ed, letn\u00ed t\u00e1bor a N\u00e1boj junior.

\r\n\r\n

 

", + "enable_comments": false, + "template_name": "", + "registration_required": false, + "sites": [ + 1 + ] + } +} +] diff --git a/galerie/admin.py b/galerie/admin.py index 0ca32dc9..54b0751e 100644 --- a/galerie/admin.py +++ b/galerie/admin.py @@ -5,50 +5,50 @@ from django.contrib import admin from django.http import HttpResponseRedirect from django import forms from django.db import models -from autocomplete_light import shortcuts as autocomplete_light # akction def zverejnit_fotogalerii(modeladmin, request, queryset): - '''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' - for galerie in queryset: - galerie.zobrazit = 0 - galerie.save() - zverejnit_fotogalerii(modeladmin, request, - Galerie.objects.filter(galerie_up = galerie)) - zverejnit_fotogalerii.short_description = 'Zveřejnit fotogalerie' + '''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' + for galerie in queryset: + galerie.zobrazit = 0 + galerie.save() + zverejnit_fotogalerii(modeladmin, request, + Galerie.objects.filter(galerie_up = galerie)) + zverejnit_fotogalerii.short_description = 'Zveřejnit fotogalerie' def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): - '''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' - for galerie in queryset: - galerie.zobrazit = 1 - galerie.save() - prepnout_fotogalerii_do_org_rezimu(modeladmin, request, - Galerie.objects.filter(galerie_up = galerie)) - prepnout_fotogalerii_do_org_rezimu.short_description = \ - 'Přepnout do režimu úprav (zneveřejní galerii)' + '''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' + for galerie in queryset: + galerie.zobrazit = 1 + galerie.save() + prepnout_fotogalerii_do_org_rezimu(modeladmin, request, + Galerie.objects.filter(galerie_up = galerie)) + prepnout_fotogalerii_do_org_rezimu.short_description = \ + 'Přepnout do režimu úprav (zneveřejní galerii)' class GalerieInline(admin.TabularInline): - model = Obrazek - fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi'] - readonly_fields = ['nazev', 'obrazek_maly_tag'] - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } + model = Obrazek + fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi'] + readonly_fields = ['nazev', 'obrazek_maly_tag'] + formfield_overrides = { + models.TextField: {'widget': forms.TextInput}, + } class ObrazekAdmin(admin.ModelAdmin): - list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi') - + list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi') + search_fields = ['nazev','popis'] + class GalerieAdmin(admin.ModelAdmin): - form = autocomplete_light.modelform_factory(Galerie, autocomplete_fields=['titulni_obrazek'], fields=['titulni_obrazek']) - model = Galerie - fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni', 'poradi') - list_display = ('nazev', 'soustredeni', 'galerie_up', 'poradi', 'zobrazit', 'datum_zmeny') - inlines = [GalerieInline] - actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu] - save_on_top = True - ordering = ['galerie_up__nazev', 'poradi'] + model = Galerie + fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni', 'poradi') + autocomplete_fields = ['titulni_obrazek'] + list_display = ('nazev', 'soustredeni', 'galerie_up', 'poradi', 'zobrazit', 'datum_zmeny') + inlines = [GalerieInline] + actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu] + save_on_top = True + ordering = ['galerie_up__nazev', 'poradi'] admin.site.register(Obrazek, ObrazekAdmin) admin.site.register(Galerie, GalerieAdmin) diff --git a/galerie/autocomplete_light_registry.py b/galerie/autocomplete_light_registry.py.old similarity index 92% rename from galerie/autocomplete_light_registry.py rename to galerie/autocomplete_light_registry.py.old index 69dc6a5b..dcedfc1a 100644 --- a/galerie/autocomplete_light_registry.py +++ b/galerie/autocomplete_light_registry.py.old @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals - from autocomplete_light import shortcuts as autocomplete_light -from models import Obrazek, Galerie -from views import cesta_od_korene +from .models import Obrazek, Galerie +from .views import cesta_od_korene class ObrazekAutocomplete(autocomplete_light.AutocompleteModelBase): diff --git a/galerie/forms.py b/galerie/forms.py index 1cadb3fc..e6666884 100644 --- a/galerie/forms.py +++ b/galerie/forms.py @@ -4,8 +4,8 @@ from django import forms from seminar.models import Soustredeni class KomentarForm(forms.Form): - komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False) + komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False) class NewGalerieForm(forms.Form): - nazev = forms.CharField(label = "Název galerie", max_length = 100) - #popis = forms.CharField(label = "Popis", required = False, max_length = 2000, widget = forms.Textarea) + nazev = forms.CharField(label = "Název galerie", max_length = 100) + #popis = forms.CharField(label = "Popis", required = False, max_length = 2000, widget = forms.Textarea) diff --git a/galerie/migrations/0001_initial.py b/galerie/migrations/0001_initial.py index b7406da6..21701185 100644 --- a/galerie/migrations/0001_initial.py +++ b/galerie/migrations/0001_initial.py @@ -21,8 +21,8 @@ class Migration(migrations.Migration): ('datum_zmeny', models.DateTimeField(auto_now=True, verbose_name=b'Datum posledn\xc3\xad zm\xc4\x9bny')), ('popis', models.TextField(null=True, verbose_name=b'Popis', blank=True)), ('zobrazit', models.IntegerField(default=1, verbose_name=b'Zobrazit?', choices=[(0, b'V\xc5\xbedy'), (1, b'Organiz\xc3\xa1tor\xc5\xafm'), (2, b'Nikdy')])), - ('galerie_up', models.ForeignKey(blank=True, to='galerie.Galerie', null=True)), - ('soustredeni', models.ForeignKey(blank=True, to='seminar.Soustredeni', null=True)), + ('galerie_up', models.ForeignKey(blank=True, to='galerie.Galerie', null=True, on_delete=models.CASCADE)), + ('soustredeni', models.ForeignKey(blank=True, to='seminar.Soustredeni', null=True, on_delete=models.CASCADE)), ], options={ 'verbose_name': 'Galerie', @@ -42,7 +42,7 @@ class Migration(migrations.Migration): ('datum_vlozeni', models.DateTimeField(auto_now_add=True, verbose_name=b'Datum vlo\xc5\xbeen\xc3\xad')), ('datum', models.DateTimeField(verbose_name=b'Datum po\xc5\x99\xc3\xadzen\xc3\xad fotografie')), ('poradi', models.IntegerField(null=True, verbose_name=b'Po\xc5\x99ad\xc3\xad', blank=True)), - ('galerie', models.ForeignKey(to='galerie.Galerie')), + ('galerie', models.ForeignKey(to='galerie.Galerie', on_delete=models.CASCADE)), ], options={ 'verbose_name': 'Obr\xe1zek', diff --git a/galerie/migrations/0004_nepovinna_galerie_u_obrazku.py b/galerie/migrations/0004_nepovinna_galerie_u_obrazku.py index c522adfe..53e17922 100644 --- a/galerie/migrations/0004_nepovinna_galerie_u_obrazku.py +++ b/galerie/migrations/0004_nepovinna_galerie_u_obrazku.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='obrazek', name='galerie', - field=models.ForeignKey(blank=True, to='galerie.Galerie', null=True), + field=models.ForeignKey(blank=True, to='galerie.Galerie', null=True, on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/galerie/migrations/0008_auto_20190430_2340.py b/galerie/migrations/0008_auto_20190430_2340.py new file mode 100644 index 00000000..140d554a --- /dev/null +++ b/galerie/migrations/0008_auto_20190430_2340.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-04-30 21:40 +from __future__ import unicode_literals + +from django.db import migrations, models +import galerie.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0007_obrazek_odstranen_datum'), + ] + + operations = [ + migrations.AlterField( + model_name='galerie', + name='datum_vytvoreni', + field=models.DateTimeField(auto_now_add=True, verbose_name='Datum vytvoření'), + ), + migrations.AlterField( + model_name='galerie', + name='datum_zmeny', + field=models.DateTimeField(auto_now=True, verbose_name='Datum poslední změny'), + ), + migrations.AlterField( + model_name='galerie', + name='nazev', + field=models.CharField(max_length=100, verbose_name='Název'), + ), + migrations.AlterField( + model_name='galerie', + name='popis', + field=models.TextField(blank=True, null=True, verbose_name='Popis'), + ), + migrations.AlterField( + model_name='galerie', + name='poradi', + field=models.IntegerField(blank=True, null=True, verbose_name='Pořadí'), + ), + migrations.AlterField( + model_name='galerie', + name='zobrazit', + field=models.IntegerField(choices=[(0, 'Vždy'), (1, 'Organizátorům'), (2, 'Nikdy')], default=1, verbose_name='Zobrazit?'), + ), + migrations.AlterField( + model_name='obrazek', + name='datum_vlozeni', + field=models.DateTimeField(auto_now_add=True, verbose_name='Datum vložení'), + ), + migrations.AlterField( + model_name='obrazek', + name='nazev', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Název'), + ), + migrations.AlterField( + model_name='obrazek', + name='obrazek_velky', + field=models.ImageField(help_text='Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.', upload_to=galerie.models.obrazek_filename), + ), + migrations.AlterField( + model_name='obrazek', + name='popis', + field=models.TextField(blank=True, null=True, verbose_name='Popis'), + ), + migrations.AlterField( + model_name='obrazek', + name='poradi', + field=models.IntegerField(blank=True, null=True, verbose_name='Pořadí'), + ), + ] diff --git a/galerie/migrations/0009_auto_20190610_2358.py b/galerie/migrations/0009_auto_20190610_2358.py new file mode 100644 index 00000000..0228a8a7 --- /dev/null +++ b/galerie/migrations/0009_auto_20190610_2358.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.21 on 2019-06-10 21:58 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0008_auto_20190430_2340'), + ] + + operations = [ + migrations.AlterField( + model_name='galerie', + name='galerie_up', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='galerie.Galerie'), + ), + migrations.AlterField( + model_name='galerie', + name='soustredeni', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='seminar.Soustredeni'), + ), + migrations.AlterField( + model_name='obrazek', + name='galerie', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='galerie.Galerie'), + ), + ] diff --git a/galerie/migrations/0008_auto_20191209_2326.py b/galerie/migrations/0010_auto_20200819_0947.py similarity index 59% rename from galerie/migrations/0008_auto_20191209_2326.py rename to galerie/migrations/0010_auto_20200819_0947.py index 12e605f4..b7678ac1 100644 --- a/galerie/migrations/0008_auto_20191209_2326.py +++ b/galerie/migrations/0010_auto_20200819_0947.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.26 on 2019-12-09 22:26 -from __future__ import unicode_literals +# Generated by Django 2.2.15 on 2020-08-19 07:47 from django.db import migrations, models @@ -8,13 +6,13 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('galerie', '0007_obrazek_odstranen_datum'), + ('galerie', '0009_auto_20190610_2358'), ] operations = [ migrations.AlterField( model_name='galerie', name='poradi', - field=models.IntegerField(blank=True, default=0, verbose_name=b'Po\xc5\x99ad\xc3\xad'), + field=models.IntegerField(blank=True, default=0, verbose_name='Pořadí'), ), ] diff --git a/galerie/models.py b/galerie/models.py index 1b64194c..8e6efdc7 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -2,7 +2,7 @@ from django.db import models #from django.db.models import Q -from django.utils.encoding import force_unicode +from django.utils.encoding import force_text from imagekit.models import ImageSpecField from imagekit.processors import ResizeToFit, Transpose @@ -14,109 +14,112 @@ VZDY=0 ORG=1 NIKDY=2 VIDITELNOST = ( - (VZDY, 'Vždy'), - (ORG, 'Organizátorům'), - (NIKDY, 'Nikdy'), + (VZDY, 'Vždy'), + (ORG, 'Organizátorům'), + (NIKDY, 'Nikdy'), ) # tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují # až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat def obrazek_filename_maly(): - pass + pass def obrazek_filename_stredni(): - pass + pass def obrazek_filename_velky(): - pass + pass def obrazek_filename(self, filename): - gal = self.galerie - cislo_gal = force_unicode(gal.pk) + gal = self.galerie + cislo_gal = gal.pk - # najdi kořenovou galerii - while (gal.galerie_up): - gal = gal.galerie_up + # najdi kořenovou galerii + while (gal.galerie_up): + gal = gal.galerie_up - # soustředění je v cestě jen pokud galerie pod nějaké patří - cesta = ( - ['Galerie'] + - (["soustredeni_" + force_unicode(gal.soustredeni.pk)] if gal.soustredeni else []) + - ["galerie_" + cislo_gal, force_unicode(self.nazev)] - ) + # soustředění je v cestě jen pokud galerie pod nějaké patří + cesta = ( + ['Galerie'] + + (["soustredeni_{}".format(gal.soustredeni.pk)] if gal.soustredeni else []) + + ["galerie_{}".format(cislo_gal), self.nazev] + ) - return os.path.join(*cesta) + return os.path.join(*cesta) class Obrazek(models.Model): - obrazek_velky = models.ImageField(upload_to=obrazek_filename, - help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") - obrazek_stredni = ImageSpecField(source='obrazek_velky', - processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], - options={'quality': 95}) - obrazek_maly = ImageSpecField(source='obrazek_velky', - processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], - options={'quality': 95}) - nazev = models.CharField('Název', max_length=50, blank=True, null=True) - popis = models.TextField('Popis', blank=True, null=True) - datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) - galerie = models.ForeignKey('Galerie', blank=True, null=True) - poradi = models.IntegerField('Pořadí', blank=True, null=True) - - def __unicode__(self): - return unicode(self.obrazek_velky.name) - - class Meta: - verbose_name = 'Obrázek' - verbose_name_plural = 'Obrázky' - ordering = ['nazev'] - - def obrazek_maly_tag(self): - return u''.format(self.obrazek_maly.url) - obrazek_maly_tag.short_description = "Náhled" - obrazek_maly_tag.allow_tags = True - - def save(self, *args, **kwargs): - # obrázek potřebuje název, protože se z něj generuje cesta pro jeho uložení - # (a pak se podle něj taky řadí) - if self.nazev is None: - self.nazev = os.path.basename(self.obrazek_velky.name) - super(Obrazek, self).save(*args, **kwargs) - - + obrazek_velky = models.ImageField(upload_to=obrazek_filename, + help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") + obrazek_stredni = ImageSpecField(source='obrazek_velky', + processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], + options={'quality': 95}) + obrazek_maly = ImageSpecField(source='obrazek_velky', + processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], + options={'quality': 95}) + nazev = models.CharField('Název', max_length=50, blank=True, null=True) + popis = models.TextField('Popis', blank=True, null=True) + datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) + galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.SET_NULL) + poradi = models.IntegerField('Pořadí', blank=True, null=True) + + def __str__(self): + return self.obrazek_velky.name + + class Meta: + verbose_name = 'Obrázek' + verbose_name_plural = 'Obrázky' + ordering = ['nazev'] + + def obrazek_maly_tag(self): + if not self.obrazek_maly: + return '' + return u''.format(self.obrazek_maly.url) + obrazek_maly_tag.short_description = "Náhled" + obrazek_maly_tag.allow_tags = True + + def save(self, *args, **kwargs): + # obrázek potřebuje název, protože se z něj generuje cesta pro jeho uložení + # (a pak se podle něj taky řadí) + if self.nazev is None: + self.nazev = os.path.basename(self.obrazek_velky.name) + super(Obrazek, self).save(*args, **kwargs) + class Galerie(models.Model): - nazev = models.CharField('Název', max_length=100) - datum_vytvoreni = models.DateTimeField('Datum vytvoření', auto_now_add = True) - datum_zmeny = models.DateTimeField('Datum poslední změny', auto_now = True) - popis = models.TextField('Popis', blank = True, null = True) - titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) - zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) - galerie_up = models.ForeignKey('Galerie', blank = True, null = True) - soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True) - poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) - - def __unicode__(self): - return self.nazev - class Meta: - verbose_name = 'Galerie' - verbose_name_plural = 'Galerie' - - #def link_na_preview(self): - #"""Odkaz na galerii, používá se v admin rozhranní. """ - #return 'Preview' % self.id - #link_na_preview.allow_tags = True - #link_na_preview.short_description = 'Zobrazit galerii' + nazev = models.CharField('Název', max_length=100) + datum_vytvoreni = models.DateTimeField('Datum vytvoření', auto_now_add = True) + datum_zmeny = models.DateTimeField('Datum poslední změny', auto_now = True) + popis = models.TextField('Popis', blank = True, null = True) + titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) + zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) + galerie_up = models.ForeignKey('Galerie', blank = True, null = True, + on_delete=models.SET_NULL) + soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True, + on_delete=models.PROTECT) + poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) + + def __str__(self): + return self.nazev + class Meta: + verbose_name = 'Galerie' + verbose_name_plural = 'Galerie' + + #def link_na_preview(self): + #"""Odkaz na galerii, používá se v admin rozhranní. """ + #return 'Preview' % self.id + #link_na_preview.allow_tags = True + #link_na_preview.short_description = 'Zobrazit galerii' # - #def je_publikovano(self): - #"""Vraci True, pokud je tato galerie publikovana. """ - #if self.zobrazit == VZDY: - #return True - #if self.zobrazit == PODLE_CLANKU: - #for clanek in self.clanek_set.all(): - #if clanek.je_publikovano(): - #return True - #return False + #def je_publikovano(self): + #"""Vraci True, pokud je tato galerie publikovana. """ + #if self.zobrazit == VZDY: + #return True + #if self.zobrazit == PODLE_CLANKU: + #for clanek in self.clanek_set.all(): + #if clanek.je_publikovano(): + #return True + #return False # - #@staticmethod - #def publikovane_galerie(): - #"""Vraci galerie, ktere uz maji byt publikovane.""" - #clanky = Blog.models.Clanek.publikovane_clanky() - #return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct() + #@staticmethod + #def publikovane_galerie(): + #"""Vraci galerie, ktere uz maji byt publikovane.""" + #clanky = Blog.models.Clanek.publikovane_clanky() + #return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct() diff --git a/galerie/static/galerie/prvky/dalsi.png b/galerie/static/galerie/prvky/dalsi.png deleted file mode 100644 index b5c68dcc..00000000 Binary files a/galerie/static/galerie/prvky/dalsi.png and /dev/null differ diff --git a/galerie/static/galerie/prvky/dalsi.svg b/galerie/static/galerie/prvky/dalsi.svg new file mode 100644 index 00000000..e928adb2 --- /dev/null +++ b/galerie/static/galerie/prvky/dalsi.svg @@ -0,0 +1,65 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/galerie/static/galerie/prvky/nahoru.png b/galerie/static/galerie/prvky/nahoru.png deleted file mode 100644 index d297af60..00000000 Binary files a/galerie/static/galerie/prvky/nahoru.png and /dev/null differ diff --git a/galerie/static/galerie/prvky/predchozi.png b/galerie/static/galerie/prvky/predchozi.png deleted file mode 100644 index dc657411..00000000 Binary files a/galerie/static/galerie/prvky/predchozi.png and /dev/null differ diff --git a/galerie/static/galerie/prvky/predchozi.svg b/galerie/static/galerie/prvky/predchozi.svg new file mode 100644 index 00000000..b7a491ed --- /dev/null +++ b/galerie/static/galerie/prvky/predchozi.svg @@ -0,0 +1,65 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/galerie/urls.py b/galerie/urls.py index 4b015e44..4d1e8f24 100644 --- a/galerie/urls.py +++ b/galerie/urls.py @@ -1,13 +1,13 @@ # coding: utf-8 -from django.conf.urls import include, url +from django.urls import path from . import views urlpatterns = [ - url(r'^(?P\d+)/$', views.nahled), - url(r'^(?P\d+)/(?P\d+)/$', views.detail), - url(r'^(?P\d+)/new/$', views.new_galerie), - url(r'^(?P\d+)/plus/(?P\d+)/$', views.plus_galerie), - url(r'^(?P\d+)/minus/(?P\d+)/$', views.minus_galerie), + path('/', views.nahled), + path('//', views.detail), + path('/new/', views.new_galerie), + path('/plus//', views.plus_galerie), + path('/minus//', views.minus_galerie), ] diff --git a/galerie/views.py b/galerie/views.py index 916a869b..d23e79f1 100644 --- a/galerie/views.py +++ b/galerie/views.py @@ -12,226 +12,225 @@ from seminar.models import Soustredeni from galerie.forms import KomentarForm, NewGalerieForm def zobrazit(galerie, request): - preview = False - if galerie.zobrazit >= 1: - if request.user.is_staff: - preview = True; - else: - raise Http404 - return preview + preview = False + if galerie.zobrazit >= 1: + if request.user.is_staff: + preview = True; + else: + raise Http404 + return preview def cesta_od_korene(g): - """Vrátí seznam galerií od kořene ke g""" - cesta = [] - while g != None: - cesta.append(g) - g = g.galerie_up - return reversed(cesta) + """Vrátí seznam galerií od kořene ke g""" + cesta = [] + while g != None: + cesta.append(g) + g = g.galerie_up + return reversed(cesta) def nahled(request, pk, soustredeni): - """Zobrazeni nahledu vsech fotek ve skupine.""" - galerie = get_object_or_404(Galerie, pk=pk) - - podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') - if not request.user.is_staff: - podgalerie = podgalerie.filter(zobrazit__lt=1) - - obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') - preview = zobrazit(galerie, request) - - sourozenci = [] - if galerie.galerie_up: - sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') - if not request.user.is_staff: - sourozenci = sourozenci.filter(zobrazit__lt=1) - - predchozi = None - nasledujici = None - minuly = None - for g in sourozenci: - if g.pk == galerie.pk: - predchozi = minuly - if minuly != None and minuly.pk == galerie.pk: - nasledujici = g - break - minuly = g - - cesta = cesta_od_korene(galerie) - - return render(request, 'galerie/GalerieNahled.html', - {'galerie' : galerie, - 'podgalerie' : podgalerie, - 'obrazky' : obrazky, - 'preview' : preview, - 'cesta': cesta, - 'sourozenci': sourozenci, - 'predchozi': predchozi, - 'nasledujici': nasledujici, - }) + """Zobrazeni nahledu vsech fotek ve skupine.""" + galerie = get_object_or_404(Galerie, pk=pk) + + podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') + if not request.user.is_staff: + podgalerie = podgalerie.filter(zobrazit__lt=1) + + obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') + preview = zobrazit(galerie, request) + + sourozenci = [] + if galerie.galerie_up: + sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') + if not request.user.is_staff: + sourozenci = sourozenci.filter(zobrazit__lt=1) + + predchozi = None + nasledujici = None + minuly = None + for g in sourozenci: + if g.pk == galerie.pk: + predchozi = minuly + if minuly != None and minuly.pk == galerie.pk: + nasledujici = g + break + minuly = g + + cesta = cesta_od_korene(galerie) + + return render(request, 'galerie/GalerieNahled.html', + {'galerie' : galerie, + 'podgalerie' : podgalerie, + 'obrazky' : obrazky, + 'preview' : preview, + 'cesta': cesta, + 'sourozenci': sourozenci, + 'predchozi': predchozi, + 'nasledujici': nasledujici, + }) def detail(request, pk, fotka, soustredeni): - """Zobrazeni nahledu fotky s id 'fotka'.""" - MAX_VYSKA = 900 - MAX_SIRKA = 900 - MAX_VYSKA_MALA = 100 - MAX_SIRKA_MALA = 200 - NAHLEDU = 1 - - galerie = get_object_or_404(Galerie, pk=pk) - preview = zobrazit(galerie, request) - obrazek = get_object_or_404(Obrazek, pk=fotka) - obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') - - # vytvoreni a obslouzeni formulare - if request.method == 'POST': - form = KomentarForm(request.POST) - if form.is_valid(): - obrazek.popis = form.cleaned_data['komentar'] - obrazek.save() - else: - form = KomentarForm({'komentar': obrazek.popis}) - - # Poradi aktualniho obrazku v galerii/stitku. - for i in range(len(obrazky)): - if obrazky[i] == obrazek: - poradi = i - break - else: - # Obrazek neni v galerii/stitku. - raise Http404 - - - # Nacteni okolnich obrazku a galerii - # TODO vyjmout zjisteni predchozich a nasledujicich galerii - # a udelat z toho funkci, ktera se pouzije u nahledu - predchozi_galerie = None - nasledujici_galerie = None - obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1] - if (poradi+1) > NAHLEDU: - obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi] - else: - obrazky_predchozi = obrazky[0:poradi] - if galerie.poradi > 1: - predchozi_galerie = Galerie.objects.\ - filter(galerie_up=galerie.galerie_up).\ - filter(poradi=(galerie.poradi-1)) - if predchozi_galerie: - predchozi_galerie = predchozi_galerie[0] - else: - predchozi_galerie = None - if (poradi+1) == len(obrazky): # Tohle je poslední obrázek - if (galerie.poradi is not None - and galerie.galerie_up is not None): - nasledujici_galerie = Galerie.objects.\ - filter(galerie_up=galerie.galerie_up).\ - filter(poradi=(galerie.poradi+1)) - else: - nasledujici_galerie = None - if nasledujici_galerie: - nasledujici_galerie = nasledujici_galerie[0] - else: - nasledujici_galerie = None - - - - # Preskalovani obrazku do vybraneho prostoru. - vyska = obrazek.obrazek_stredni.height - sirka = obrazek.obrazek_stredni.width - if vyska > MAX_VYSKA: - sirka = sirka * MAX_VYSKA / vyska - vyska = MAX_VYSKA - if sirka > MAX_SIRKA: - vyska = vyska * MAX_SIRKA / sirka - sirka = MAX_SIRKA - - return render(request, 'galerie/Galerie.html', - {'galerie' : galerie, - 'predchozi_galerie' : predchozi_galerie, - 'nasledujici_galerie' : nasledujici_galerie, - 'obrazek' : obrazek, - 'vyska' : vyska, - 'sirka' : sirka, - 'obrazky_predchozi' : obrazky_predchozi, - 'obrazky_dalsi' : obrazky_dalsi, - 'preview' : preview, - 'form' : form, - 'cesta': cesta_od_korene(galerie), - }) - + """Zobrazeni nahledu fotky s id 'fotka'.""" + MAX_VYSKA = 900 + MAX_SIRKA = 900 + MAX_VYSKA_MALA = 100 + MAX_SIRKA_MALA = 200 + NAHLEDU = 1 + + galerie = get_object_or_404(Galerie, pk=pk) + preview = zobrazit(galerie, request) + obrazek = get_object_or_404(Obrazek, pk=fotka) + obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') + + # vytvoreni a obslouzeni formulare + if request.method == 'POST': + form = KomentarForm(request.POST) + if form.is_valid(): + obrazek.popis = form.cleaned_data['komentar'] + obrazek.save() + else: + form = KomentarForm({'komentar': obrazek.popis}) + + # Poradi aktualniho obrazku v galerii/stitku. + for i in range(len(obrazky)): + if obrazky[i] == obrazek: + poradi = i + break + else: + # Obrazek neni v galerii/stitku. + raise Http404 + + + # Nacteni okolnich obrazku a galerii + # TODO vyjmout zjisteni predchozich a nasledujicich galerii + # a udelat z toho funkci, ktera se pouzije u nahledu + predchozi_galerie = None + nasledujici_galerie = None + obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1] + if (poradi+1) > NAHLEDU: + obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi] + else: + obrazky_predchozi = obrazky[0:poradi] + if galerie.poradi > 1: + predchozi_galerie = Galerie.objects.\ + filter(galerie_up=galerie.galerie_up).\ + filter(poradi=(galerie.poradi-1)) + if predchozi_galerie: + predchozi_galerie = predchozi_galerie[0] + else: + predchozi_galerie = None + if (poradi+1) == len(obrazky): # Tohle je poslední obrázek + if (galerie.poradi is not None + and galerie.galerie_up is not None): + nasledujici_galerie = Galerie.objects.\ + filter(galerie_up=galerie.galerie_up).\ + filter(poradi=(galerie.poradi+1)) + else: + nasledujici_galerie = None + if nasledujici_galerie: + nasledujici_galerie = nasledujici_galerie[0] + else: + nasledujici_galerie = None + + + + # Preskalovani obrazku do vybraneho prostoru. + vyska = obrazek.obrazek_stredni.height + sirka = obrazek.obrazek_stredni.width + if vyska > MAX_VYSKA: + sirka = sirka * MAX_VYSKA / vyska + vyska = MAX_VYSKA + if sirka > MAX_SIRKA: + vyska = vyska * MAX_SIRKA / sirka + sirka = MAX_SIRKA + + return render(request, 'galerie/Galerie.html', + {'galerie' : galerie, + 'predchozi_galerie' : predchozi_galerie, + 'nasledujici_galerie' : nasledujici_galerie, + 'obrazek' : obrazek, + 'vyska' : vyska, + 'sirka' : sirka, + 'obrazky_predchozi' : obrazky_predchozi, + 'obrazky_dalsi' : obrazky_dalsi, + 'preview' : preview, + 'form' : form, + 'cesta': cesta_od_korene(galerie), + }) def new_galerie(request, galerie, soustredeni): - # zjistime k jakemu soustredeni se vaze nove vytvarena galerie - soustredeni = get_object_or_404(Soustredeni, pk = soustredeni) - # pokud je parametr galerie 0, pak jde o hlavni galerii - # kdyz je nejaky jiny, pak je pk galerie pod kterou tu dalsi vytvarim - if int(galerie) == 0: - galerie_up = False - galerie_text = "Hlavní fotogalerie soustředění" - else: - galerie_up = get_object_or_404(Galerie, pk = int(galerie)) - galerie_text = "podgalerii ke galerii " + str(galerie_up) - - # obsluha formulare umoznujiciho multiple nahravani fotek - if request.method == 'POST': - form = NewGalerieForm(request.POST, request.FILES) - if form.is_valid(): - # vytvoreni nove galerie - gal = Galerie() - gal.nazev = form.cleaned_data['nazev'] - #gal.popis = form.cleaned_data['popis'] # popis nepouzivame - gal.zobrazit = 1 # galerie je v procesu vytvareni - ''' pokud je to podgalerie pridej nadrazenou galerii - a nadrazene soustredeni nechej volne, - pokud je to hlavni galerie, tak nadrazena galerie neexistuje, - ale v takovem pripade musi byt nadrazene soustredeni a ne jinak ''' - if galerie_up: - gal.galerie_up = galerie_up - else: - gal.soustredeni = soustredeni - if gal.galerie_up: - gal.poradi = int(len(gal.galerie_up.galerie_set.all())) + 1 - gal.save() - - # zpracovani obrazku v galerii - for obr in request.FILES.getlist('obr'): - o = Obrazek() - o.obrazek_velky = obr - o.nazev = str(obr) - o.galerie = gal - o.save() - - # presmerovani na prave vzniklou galerii - return HttpResponseRedirect('../../' + str(gal.pk)) - - else: - form = NewGalerieForm() - - - return render(request, 'galerie/GalerieNew.html', - { - 'form' : form, - 'soustredeni' : soustredeni, - 'galerie_text' : galerie_text, - }) + # zjistime k jakemu soustredeni se vaze nove vytvarena galerie + soustredeni = get_object_or_404(Soustredeni, pk = soustredeni) + # pokud je parametr galerie 0, pak jde o hlavni galerii + # kdyz je nejaky jiny, pak je pk galerie pod kterou tu dalsi vytvarim + if int(galerie) == 0: + galerie_up = False + galerie_text = "Hlavní fotogalerie soustředění" + else: + galerie_up = get_object_or_404(Galerie, pk = int(galerie)) + galerie_text = "podgalerii ke galerii " + str(galerie_up) + + # obsluha formulare umoznujiciho multiple nahravani fotek + if request.method == 'POST': + form = NewGalerieForm(request.POST, request.FILES) + if form.is_valid(): + # vytvoreni nove galerie + gal = Galerie() + gal.nazev = form.cleaned_data['nazev'] + #gal.popis = form.cleaned_data['popis'] # popis nepouzivame + gal.zobrazit = 1 # galerie je v procesu vytvareni + ''' pokud je to podgalerie pridej nadrazenou galerii + a nadrazene soustredeni nechej volne, + pokud je to hlavni galerie, tak nadrazena galerie neexistuje, + ale v takovem pripade musi byt nadrazene soustredeni a ne jinak ''' + if galerie_up: + gal.galerie_up = galerie_up + else: + gal.soustredeni = soustredeni + if gal.galerie_up: + gal.poradi = int(len(gal.galerie_up.galerie_set.all())) + 1 + gal.save() + + # zpracovani obrazku v galerii + for obr in request.FILES.getlist('obr'): + o = Obrazek() + o.obrazek_velky = obr + o.nazev = str(obr) + o.galerie = gal + o.save() + + # presmerovani na prave vzniklou galerii + return HttpResponseRedirect('../../' + str(gal.pk)) + + else: + form = NewGalerieForm() + + + return render(request, 'galerie/GalerieNew.html', + { + 'form' : form, + 'soustredeni' : soustredeni, + 'galerie_text' : galerie_text, + }) def plus_galerie(request, galerie, soustredeni, subgalerie): - galerie = get_object_or_404(Galerie, pk=subgalerie) - if galerie.poradi: - galerie.poradi += 1 - else: - galerie.poradi = int(len(galerie.galerie_up.galerie_set.all())) - galerie.save() - return HttpResponseRedirect('../../') + galerie = get_object_or_404(Galerie, pk=subgalerie) + if galerie.poradi: + galerie.poradi += 1 + else: + galerie.poradi = int(len(galerie.galerie_up.galerie_set.all())) + galerie.save() + return HttpResponseRedirect('../../') def minus_galerie(request, galerie, soustredeni, subgalerie): - galerie = get_object_or_404(Galerie, pk=subgalerie) - if galerie.poradi: - galerie.poradi -= 1 - else: - galerie.poradi = 1 - galerie.save() - return HttpResponseRedirect('../../') + galerie = get_object_or_404(Galerie, pk=subgalerie) + if galerie.poradi: + galerie.poradi -= 1 + else: + galerie.poradi = 1 + galerie.save() + return HttpResponseRedirect('../../') diff --git a/init_local.sh b/init_local.sh new file mode 100755 index 00000000..ab373c38 --- /dev/null +++ b/init_local.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e # Spadni pokud něco spadne + +# Check venvu +# NOTE: zkontroluje i správnou složku -- existencí Makefilu +make venv_check + +# Vygenerujeme testdata +./manage.py testdata + +# Nahrajeme statický obsah modelů +./manage.py loaddata flat.json sitetree_new.json + +# Posbíráme statické soubory +./manage.py collectstatic diff --git a/korektury/admin.py b/korektury/admin.py index 25b49e4e..79dfffb1 100644 --- a/korektury/admin.py +++ b/korektury/admin.py @@ -6,21 +6,21 @@ from korektury.models import KorekturovanePDF # Register your models here. class KorekturovanePDFAdmin(VersionAdmin): - readonly_fields = ['cas', 'stran'] + readonly_fields = ['cas', 'stran'] - def get_readonly_fields(self, request, obj=None): - if obj: - return self.readonly_fields + ['pdf'] - return self.readonly_fields + def get_readonly_fields(self, request, obj=None): + if obj: + return self.readonly_fields + ['pdf'] + return self.readonly_fields - fieldsets = [ - (None, - {'fields': - ['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar']}), - # (u'PDF', {'fields': ['pdf']}), - ] - list_display = ['nazev', 'cas', 'stran', 'org'] - list_filter = [] - search_fields = [] + fieldsets = [ + (None, + {'fields': + ['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar']}), + # (u'PDF', {'fields': ['pdf']}), + ] + list_display = ['nazev', 'cas', 'stran', 'org'] + list_filter = [] + search_fields = [] admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin) diff --git a/korektury/forms.py b/korektury/forms.py index 676d6b3a..7385e687 100644 --- a/korektury/forms.py +++ b/korektury/forms.py @@ -1,13 +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) + 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) diff --git a/korektury/migrations/0001_initial.py b/korektury/migrations/0001_initial.py index 22643689..e9a89d18 100644 --- a/korektury/migrations/0001_initial.py +++ b/korektury/migrations/0001_initial.py @@ -50,7 +50,7 @@ class Migration(migrations.Migration): ('cas', models.DateTimeField(help_text=b'\xc4\x8cas zad\xc3\xa1n\xc3\xad koment\xc3\xa1\xc5\x99e', verbose_name='\u010das koment\xe1\u0159e')), ('autor', models.TextField(help_text=b'Autor koment\xc3\xa1\xc5\x99e', verbose_name='autor koment\xe1\u0159e', blank=True)), ('text', models.TextField(help_text=b'Text koment\xc3\xa1\xc5\x99e', verbose_name='text koment\xe1\u0159e', blank=True)), - ('oprava', models.ForeignKey(to='korektury.Oprava')), + ('oprava', models.ForeignKey(to='korektury.Oprava', on_delete=models.CASCADE)), ], options={ 'ordering': ['cas'], diff --git a/korektury/migrations/0002_auto_20151202_2351.py b/korektury/migrations/0002_auto_20151202_2351.py index ba88f7c7..2e7a8032 100644 --- a/korektury/migrations/0002_auto_20151202_2351.py +++ b/korektury/migrations/0002_auto_20151202_2351.py @@ -19,7 +19,7 @@ class Migration(migrations.Migration): ('cas', models.DateTimeField(default=django.utils.timezone.now, help_text=b'\xc4\x8cas zad\xc3\xa1n\xc3\xad koment\xc3\xa1\xc5\x99e', verbose_name='\u010das koment\xe1\u0159e')), ('autor', models.TextField(help_text=b'Autor koment\xc3\xa1\xc5\x99e', verbose_name='autor koment\xe1\u0159e', blank=True)), ('text', models.TextField(help_text=b'Text koment\xc3\xa1\xc5\x99e', verbose_name='text koment\xe1\u0159e', blank=True)), - ('oprava', models.ForeignKey(to='korektury.Oprava')), + ('oprava', models.ForeignKey(to='korektury.Oprava', on_delete=models.CASCADE)), ], options={ 'ordering': ['cas'], diff --git a/korektury/migrations/0006_oprava_pdf.py b/korektury/migrations/0006_oprava_pdf.py index 2adf04e7..e8f81884 100644 --- a/korektury/migrations/0006_oprava_pdf.py +++ b/korektury/migrations/0006_oprava_pdf.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='oprava', name='pdf', - field=models.ForeignKey(default=-1, to='korektury.KorekturovanePDF'), + field=models.ForeignKey(default=-1, to='korektury.KorekturovanePDF', on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/korektury/migrations/0010_Pridani_odkazu_na_organizatora.py b/korektury/migrations/0010_Pridani_odkazu_na_organizatora.py index e76d5058..6b318cab 100644 --- a/korektury/migrations/0010_Pridani_odkazu_na_organizatora.py +++ b/korektury/migrations/0010_Pridani_odkazu_na_organizatora.py @@ -15,11 +15,11 @@ class Migration(migrations.Migration): migrations.AddField( model_name='komentar', name='autor_org', - field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text='Autor koment\xe1\u0159e', null=True), + field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text='Autor koment\xe1\u0159e', null=True, on_delete=models.CASCADE), ), migrations.AddField( model_name='oprava', name='autor_org', - field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text=b'Autor opravy', null=True), + field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text=b'Autor opravy', null=True, on_delete=models.CASCADE), ), ] diff --git a/korektury/migrations/0011_prevod_autora_z_charField_na_Organizator.py b/korektury/migrations/0011_prevod_autora_z_charField_na_Organizator.py index dddb07be..9f64bbd5 100644 --- a/korektury/migrations/0011_prevod_autora_z_charField_na_Organizator.py +++ b/korektury/migrations/0011_prevod_autora_z_charField_na_Organizator.py @@ -18,10 +18,10 @@ def transform_autor(apps, schema_editor): oprava.autor_org = org oprava.save() except: - print "Org nenalezen -- mažu korekturu" + print("Org nenalezen -- mažu korekturu") # oprava.delete() else: - print "Org nenalezen -- mažu korekturu" + print("Org nenalezen -- mažu korekturu") oprava.delete() # preorgovani komentaru @@ -35,10 +35,10 @@ def transform_autor(apps, schema_editor): komentar.autor_org = org komentar.save() except: - print "Org nenalezen -- mažu korekturu" + print("Org nenalezen -- mažu korekturu") # oprava.delete() else: - print "Org nenalezen -- mažu korekturu" + print("Org nenalezen -- mažu korekturu") komentar.delete() def back(apps, schema_editor): diff --git a/korektury/migrations/0014_add_org_to_pdf.py b/korektury/migrations/0014_add_org_to_pdf.py index 9c1292e4..afd939ba 100644 --- a/korektury/migrations/0014_add_org_to_pdf.py +++ b/korektury/migrations/0014_add_org_to_pdf.py @@ -16,10 +16,10 @@ class Migration(migrations.Migration): model_name='korekturovanepdf', name='org', field=models.ForeignKey(default=None, - blank=True, - to='seminar.Organizator', - help_text=b'Zodpov\xc4\x9bdn\xc3\xbd\ - organiz\xc3\xa1tor za obsah', - null=True), + blank=True, + to='seminar.Organizator', + help_text=b'Zodpov\xc4\x9bdn\xc3\xbd\ + organiz\xc3\xa1tor za obsah', + null=True, on_delete=models.CASCADE), ), ] diff --git a/korektury/migrations/0015_auto_20161004_2005.py b/korektury/migrations/0015_auto_20161004_2005.py index c087a221..36be10df 100644 --- a/korektury/migrations/0015_auto_20161004_2005.py +++ b/korektury/migrations/0015_auto_20161004_2005.py @@ -14,6 +14,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='korekturovanepdf', name='org', - field=models.ForeignKey(default=None, blank=True, to='seminar.Organizator', help_text=b'Zodpov\xc4\x9bdn\xc3\xbd organiz\xc3\xa1tor za obsah', null=True), + field=models.ForeignKey(default=None, blank=True, to='seminar.Organizator', help_text=b'Zodpov\xc4\x9bdn\xc3\xbd organiz\xc3\xa1tor za obsah', null=True, on_delete=models.CASCADE), ), ] diff --git a/korektury/migrations/0016_auto_20190430_2340.py b/korektury/migrations/0016_auto_20190430_2340.py new file mode 100644 index 00000000..f14bce2b --- /dev/null +++ b/korektury/migrations/0016_auto_20190430_2340.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-04-30 21:40 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0015_auto_20161004_2005'), + ] + + operations = [ + migrations.AlterField( + model_name='komentar', + name='cas', + field=models.DateTimeField(default=django.utils.timezone.now, help_text='Čas zadání komentáře', verbose_name='čas komentáře'), + ), + migrations.AlterField( + model_name='komentar', + name='text', + field=models.TextField(blank=True, help_text='Text komentáře', verbose_name='text komentáře'), + ), + migrations.AlterField( + model_name='korekturovanepdf', + name='cas', + field=models.DateTimeField(default=django.utils.timezone.now, help_text='Čas vložení PDF', verbose_name='čas vložení PDF'), + ), + migrations.AlterField( + model_name='korekturovanepdf', + name='komentar', + field=models.TextField(blank=True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)', verbose_name='komentář k PDF'), + ), + migrations.AlterField( + model_name='korekturovanepdf', + name='nazev', + field=models.CharField(blank=True, help_text='Název (např. 22.1 verze 4) korekturovaného PDF', max_length=50, verbose_name='název PDF'), + ), + 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.CASCADE, to='seminar.Organizator'), + ), + migrations.AlterField( + model_name='korekturovanepdf', + name='status', + field=models.CharField(choices=[('pridavani', 'Přidávání korektur'), ('zanaseni', 'Korektury jsou zanášeny'), ('zastarale', 'Stará verze, nekorigovat')], default='pridavani', max_length=16, verbose_name='stav PDF'), + ), + migrations.AlterField( + model_name='korekturovanepdf', + name='stran', + field=models.IntegerField(default=0, help_text='Počet stran PDF', verbose_name='počet stran'), + ), + migrations.AlterField( + model_name='oprava', + name='autor', + field=models.ForeignKey(blank=True, help_text='Autor opravy', null=True, on_delete=django.db.models.deletion.CASCADE, to='seminar.Organizator'), + ), + migrations.AlterField( + model_name='oprava', + name='status', + field=models.CharField(choices=[('k_oprave', 'K opravě'), ('opraveno', 'Opraveno'), ('neni_chyba', 'Není chyba'), ('k_zaneseni', 'K zanesení do TeXu')], default='k_oprave', max_length=16, verbose_name='stav opravy'), + ), + migrations.AlterField( + model_name='oprava', + name='strana', + field=models.IntegerField(help_text='Strana s opravou (od 0)', verbose_name='strana s opravou'), + ), + migrations.AlterField( + model_name='oprava', + name='text', + field=models.TextField(blank=True, help_text='Text opravy', verbose_name='text opravy'), + ), + ] diff --git a/korektury/migrations/0017_auto_20190610_2358.py b/korektury/migrations/0017_auto_20190610_2358.py new file mode 100644 index 00000000..111f2f8f --- /dev/null +++ b/korektury/migrations/0017_auto_20190610_2358.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.21 on 2019-06-10 21:58 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0016_auto_20190430_2340'), + ] + + 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='seminar.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='seminar.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='seminar.Organizator'), + ), + migrations.AlterField( + model_name='oprava', + name='pdf', + field=models.ForeignKey(default=-1, on_delete=django.db.models.deletion.PROTECT, to='korektury.KorekturovanePDF'), + ), + ] diff --git a/korektury/models.py b/korektury/models.py index e5b6e01a..88c1a5e6 100644 --- a/korektury/models.py +++ b/korektury/models.py @@ -3,8 +3,7 @@ import os from django.db import models from django.utils import timezone from django.conf import settings -from django.utils.encoding import python_2_unicode_compatible -from django.utils.encoding import force_unicode +from django.utils.encoding import force_text from django.core.exceptions import ObjectDoesNotExist from django.utils.text import get_valid_filename @@ -17,180 +16,176 @@ from unidecode import unidecode def generate_filename(self, filename): - clean = get_valid_filename( - unidecode( - filename.replace('/', '-').replace('\0', '').replace(":", "_") - ) - ) - fname = "%s_%s" % ( - timezone.now().strftime('%Y-%m-%d-%H_%M'), - clean) - return os.path.join(settings.KOREKTURY_PDF_DIR, fname) + clean = get_valid_filename( + unidecode( + filename.replace('/', '-').replace('\0', '').replace(":", "_") + ) + ) + fname = "%s_%s" % ( + timezone.now().strftime('%Y-%m-%d-%H_%M'), + clean) + return os.path.join(settings.KOREKTURY_PDF_DIR, fname) #@reversion.register(ignore_duplicates=True) -#@python_2_unicode_compatible class KorekturovanePDF(models.Model): - class Meta: - ordering = ['-cas'] - db_table = 'korekturovane_cislo' - verbose_name = u'PDF k opravám' - verbose_name_plural = u'PDF k opravám' - - #Interní ID - id = models.AutoField(primary_key = True) - - cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF') - - nazev = models.CharField(u'název PDF',blank = True,max_length=50, help_text='Název (např. 22.1 verze 4) korekturovaného PDF') - - komentar = models.TextField(u'komentář k PDF',blank = True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)') - - pdf = models.FileField(u'PDF', upload_to = generate_filename) - - org = models.ForeignKey(Organizator, blank=True, - help_text='Zodpovědný organizátor za obsah', - null=True, - default=None) - - stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF', - default=0) - STATUS_PRIDAVANI = 'pridavani' - STATUS_ZANASENI = 'zanaseni' - STATUS_ZASTARALE = 'zastarale' - STATUS_CHOICES = ( - (STATUS_PRIDAVANI, u'Přidávání korektur'), - (STATUS_ZANASENI, u'Korektury jsou zanášeny'), - (STATUS_ZASTARALE, u'Stará verze, nekorigovat'), - ) - status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False, - default = STATUS_PRIDAVANI) - - - #TODO Nepovinný foreign key k číslu - - def get_prefix(self): - """Vrať řetězec, ke kterému se připojí číslo a .png""" - # vrátíme jméno souboru bez cesty - return os.path.basename(self.pdf.file.name) - - def convert(self): - """Vytvoří jedno png za každou stranu pdf a uloží se""" - dirname = os.path.join(settings.MEDIA_ROOT, settings.KOREKTURY_IMG_DIR) - if not os.path.exists(dirname): - os.mkdir(dirname) - self.stran = 0 - while True: - res = subprocess.call([ - #Parametry inspirovány chybovou hláškou imagemagicku - "gs", - "-sstdout=%stderr", - "-dSAFER", - "-dNOPAUSE", - "-dBATCH", - "-dNOPROMPT", - "-sDEVICE=pngalpha", - "-r180x180", - "-dFirstPage=%d" % (self.stran+1), - "-dLastPage=%d" % (self.stran+1), - "-sOutputFile="+os.path.join( - dirname, - "%s-%d.png" % (self.get_prefix(), self.stran)), - "-f%s" % (self.pdf.path) - ]) - if not os.path.exists(os.path.join( - dirname, - "%s-%d.png" % (self.get_prefix(), self.stran))): - break - self.stran += 1 - # Změnil se počet stran, ukládáme - super(KorekturovanePDF, self).save() - - def save(self): - # Pokud se nezmenilo PDF, tak nepregenerovavej nahledy - try: - original = KorekturovanePDF.objects.get(pk=self.pk) - if original.pdf == self.pdf: - super(KorekturovanePDF, self).save() - return - except ObjectDoesNotExist: - pass - # uložíme nahrávané pdf - super(KorekturovanePDF, self).save() - - # uložíme png a změněný počet stran - self.convert() + class Meta: + ordering = ['-cas'] + db_table = 'korekturovane_cislo' + verbose_name = u'PDF k opravám' + verbose_name_plural = u'PDF k opravám' + + #Interní ID + id = models.AutoField(primary_key = True) + + cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF') + + nazev = models.CharField(u'název PDF',blank = True,max_length=50, help_text='Název (např. 22.1 verze 4) korekturovaného PDF') + + komentar = models.TextField(u'komentář k PDF',blank = True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)') + + pdf = models.FileField(u'PDF', upload_to = generate_filename) + + org = models.ForeignKey(Organizator, blank=True, + help_text='Zodpovědný organizátor za obsah', + null=True, default=None, on_delete=models.SET_NULL) + + stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF', + default=0) + STATUS_PRIDAVANI = 'pridavani' + STATUS_ZANASENI = 'zanaseni' + STATUS_ZASTARALE = 'zastarale' + STATUS_CHOICES = ( + (STATUS_PRIDAVANI, u'Přidávání korektur'), + (STATUS_ZANASENI, u'Korektury jsou zanášeny'), + (STATUS_ZASTARALE, u'Stará verze, nekorigovat'), + ) + status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False, + default = STATUS_PRIDAVANI) + + + #TODO Nepovinný foreign key k číslu + + def get_prefix(self): + """Vrať řetězec, ke kterému se připojí číslo a .png""" + # vrátíme jméno souboru bez cesty + return os.path.basename(self.pdf.file.name) + + def convert(self): + """Vytvoří jedno png za každou stranu pdf a uloží se""" + dirname = os.path.join(settings.MEDIA_ROOT, settings.KOREKTURY_IMG_DIR) + if not os.path.exists(dirname): + os.mkdir(dirname) + self.stran = 0 + while True: + res = subprocess.call([ + #Parametry inspirovány chybovou hláškou imagemagicku + "gs", + "-sstdout=%stderr", + "-dSAFER", + "-dNOPAUSE", + "-dBATCH", + "-dNOPROMPT", + "-sDEVICE=pngalpha", + "-r180x180", + "-dFirstPage=%d" % (self.stran+1), + "-dLastPage=%d" % (self.stran+1), + "-sOutputFile="+os.path.join( + dirname, + "%s-%d.png" % (self.get_prefix(), self.stran)), + "-f%s" % (self.pdf.path) + ]) + if not os.path.exists(os.path.join( + dirname, + "%s-%d.png" % (self.get_prefix(), self.stran))): + break + self.stran += 1 + # Změnil se počet stran, ukládáme + super(KorekturovanePDF, self).save() + + def save(self): + # Pokud se nezmenilo PDF, tak nepregenerovavej nahledy + try: + original = KorekturovanePDF.objects.get(pk=self.pk) + if original.pdf == self.pdf: + super(KorekturovanePDF, self).save() + return + except ObjectDoesNotExist: + pass + # uložíme nahrávané pdf + super(KorekturovanePDF, self).save() + + # uložíme png a změněný počet stran + self.convert() @reversion.register(ignore_duplicates=True) -@python_2_unicode_compatible class Oprava(models.Model): - class Meta: - db_table = 'opravy' - verbose_name = u'Oprava' - verbose_name_plural = u'Opravy' - ordering = ['y','x'] - - #Interní ID - id = models.AutoField(primary_key = True) - - pdf = models.ForeignKey(KorekturovanePDF, default=-1) - - strana = models.IntegerField(u'strana s opravou', help_text='Strana s opravou (od 0)') - - x = models.IntegerField(u'x-ová souřadnice bugu') - y = models.IntegerField(u'y-ová souřadnice bugu') - - STATUS_K_OPRAVE = 'k_oprave' - STATUS_OPRAVENO = 'opraveno' - STATUS_NENI_CHYBA = 'neni_chyba' - STATUS_K_ZANESENI = 'k_zaneseni' - STATUS_CHOICES = ( - (STATUS_K_OPRAVE, u'K opravě'), - (STATUS_OPRAVENO, u'Opraveno'), - (STATUS_NENI_CHYBA, u'Není chyba'), - (STATUS_K_ZANESENI, u'K zanesení do TeXu'), - ) - status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False, - default = STATUS_K_OPRAVE) - - autor = models.ForeignKey(Organizator, blank = True, - help_text='Autor opravy', - null = True) - - text = models.TextField(u'text opravy',blank = True, help_text='Text opravy') - -# def __init__(self,dictionary): -# for k,v in dictionary.items(): -# setattr(self,k,v) - - def __str__(self): - return force_unicode(u'%s od %s: %s'%(self.status,self.autor,self.text)) + class Meta: + db_table = 'opravy' + verbose_name = u'Oprava' + verbose_name_plural = u'Opravy' + ordering = ['y','x'] + + #Interní ID + id = models.AutoField(primary_key = True) + + pdf = models.ForeignKey(KorekturovanePDF, default=-1, on_delete=models.PROTECT) + + strana = models.IntegerField(u'strana s opravou', help_text='Strana s opravou (od 0)') + + x = models.IntegerField(u'x-ová souřadnice bugu') + y = models.IntegerField(u'y-ová souřadnice bugu') + + STATUS_K_OPRAVE = 'k_oprave' + STATUS_OPRAVENO = 'opraveno' + STATUS_NENI_CHYBA = 'neni_chyba' + STATUS_K_ZANESENI = 'k_zaneseni' + STATUS_CHOICES = ( + (STATUS_K_OPRAVE, u'K opravě'), + (STATUS_OPRAVENO, u'Opraveno'), + (STATUS_NENI_CHYBA, u'Není chyba'), + (STATUS_K_ZANESENI, u'K zanesení do TeXu'), + ) + status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False, + default = STATUS_K_OPRAVE) + + autor = models.ForeignKey(Organizator, blank = True, + help_text='Autor opravy', + null = True, on_delete=models.SET_NULL) + + text = models.TextField(u'text opravy',blank = True, help_text='Text opravy') + +# def __init__(self,dictionary): +# for k,v in dictionary.items(): +# setattr(self,k,v) + + def __str__(self): + return '{} od {}: {}'.format(self.status,self.autor,self.text) @reversion.register(ignore_duplicates=True) -@python_2_unicode_compatible class Komentar(models.Model): - class Meta: - db_table = 'komentare' - verbose_name = u'Komentář k opravě' - verbose_name_plural = u'Komentáře k opravě' - ordering = ['cas'] - - #Interní ID - id = models.AutoField(primary_key = True) - - cas = models.DateTimeField(u'čas komentáře',default=timezone.now,help_text = 'Čas zadání komentáře') - - oprava = models.ForeignKey(Oprava) - autor = models.ForeignKey(Organizator, blank = True, - help_text = u'Autor komentáře', - null = True) - - text = models.TextField(u'text komentáře',blank = True, help_text='Text komentáře') - - def __str__(self): - return force_unicode(u'%s od %s: %s'%(self.cas,self.autor,self.text)) + class Meta: + db_table = 'komentare' + verbose_name = u'Komentář k opravě' + verbose_name_plural = u'Komentáře k opravě' + ordering = ['cas'] + + #Interní ID + id = models.AutoField(primary_key = True) + + cas = models.DateTimeField(u'čas komentáře',default=timezone.now,help_text = 'Čas zadání komentáře') + + oprava = models.ForeignKey(Oprava, on_delete=models.CASCADE) + autor = models.ForeignKey(Organizator, blank = True, + help_text = u'Autor komentáře', + null = True, on_delete=models.SET_NULL) + + text = models.TextField(u'text komentáře',blank = True, help_text='Text komentáře') + + def __str__(self): + return '{} od {}: {}'.format(self.cas,self.autor,self.text) diff --git a/korektury/static/korektury/opraf.css b/korektury/static/korektury/opraf.css index 33146e1b..4a731de4 100644 --- a/korektury/static/korektury/opraf.css +++ b/korektury/static/korektury/opraf.css @@ -13,72 +13,46 @@ body, img{background:white;} +/* Barvy korektur */ +.k_oprave { + --rgb: 255, 0, 0; +} +.opraveno { + --rgb: 0, 0, 255; +} +.neni_chyba { + --rgb: 128, 128, 128; +} +.k_zaneseni { + --rgb: 0, 255, 0; +} + .pointer-hi, -.pointer, -.pointer-wontfix, -.pointer-wontfix-hi, -.pointer-ready, -.pointer-ready-hi, -.pointer-done, -.pointer-done-hi { +.pointer{ position:absolute; /*border-bottom-left-radius: 10px; */ border-left: 2px solid yellow; border-bottom: 2px solid yellow; + border-color: rgb(var(--rgb),var(--alpha)); } -.pointer-done-hi, -.pointer-wontfix-hi, -.pointer-ready-hi, -.pointer-hi { - border-width: 3px; +.pointer { + border-width: 1px; + --alpha: 0.35; } -.pointer { - border-color: #F00; /*IE*/ - border-color: rgba(255, 0, 0, 0.35); -} .pointer-hi { - border-color: #F00; /*IE*/ - border-color: rgba(255, 0, 0, 1); -} -.pointer-done { - border-color: #00F; /*IE*/ - border-color: rgba(0, 0, 255, 0.2); -} -.pointer-done-hi { - border-color: #00F; /*IE*/ - border-color: rgba(0, 0, 255, 1); -} -.pointer-wontfix { - border-color: #000; /*IE*/ - border-color: rgba(128, 128, 128, 0.2); -} -.pointer-wontfix-hi { - border-color: #000; /*IE*/ - border-color: rgba(128, 128, 128, 1); -} -.pointer-ready { - border-color: #0F0; /*IE*/ - border-color: rgba(0, 255, 0, 0.2); -} -.pointer-ready-hi { - border-color: #0F0; /*IE*/ - border-color: rgba(0, 255, 0, 1); + border-width: 3px; + --alpha: 1; } -.box:hover, -.box-done:hover, -.box-ready:hover, -.box-wontfix:hover{ + +.box:hover{ border-width:3px; margin: 0px; } -.box, -.box-done, -.box-ready, -.box-wontfix { +.box { margin: 1px; background-color: white; width:300px; @@ -86,18 +60,7 @@ img{background:white;} padding: 3px; border: 2px solid black; border-radius: 10px; -} -.box { - border-color: red; -} -.box-done { - border-color: blue; -} -.box-ready { - border-color: rgba(0,255,0,1); -} -.box-wontfix { - border-color: grey; + border-color: rgb(var(--rgb)); } form { display:inline; diff --git a/korektury/static/korektury/opraf.js b/korektury/static/korektury/opraf.js index 5cfe02e2..760f3c6a 100644 --- a/korektury/static/korektury/opraf.js +++ b/korektury/static/korektury/opraf.js @@ -65,6 +65,12 @@ function place_comments_one_div(img_id, comments) } } +function place_comments() { + for (var i=0; i < comments.length-1; i++) { + place_comments_one_div(comments[i][0], comments[i][1]) + } +} + // ctrl-enter submits form function textarea_onkey(ev) { @@ -212,45 +218,22 @@ function show_form(img_id, dx, dy, id, text, action) { textarea.focus(); return true; - } -function box_onmouseover(box, stat) +function box_onmouseover(box) { var id = box.id; var pointer = document.getElementById(box.id + '-pointer'); - switch (stat){ - case 'done': - pointer.className = 'pointer-done-hi'; - break; - case 'wontfix': - pointer.className = 'pointer-wontfix-hi'; - break; - case 'ready': - pointer.className = 'pointer-ready-hi'; - break; - default: - pointer.className = 'pointer-hi'; - } + pointer.classList.remove('pointer'); + pointer.classList.add('pointer-hi'); } -function box_onmouseout(box, stat) +function box_onmouseout(box) { var id = box.id; var pointer = document.getElementById(box.id + '-pointer'); - switch (stat){ - case 'done': - pointer.className = 'pointer-done'; - break; - case 'wontfix': - pointer.className = 'pointer-wontfix'; - break; - case 'ready': - pointer.className = 'pointer-ready'; - break; - default: - pointer.className = 'pointer'; - } + pointer.classList.remove('pointer-hi'); + pointer.classList.add('pointer'); } function save_scroll(form) @@ -261,6 +244,33 @@ function save_scroll(form) return true; } +function toggle_corrections(aclass) +{ + var stylesheets = document.styleSheets; + var ssheet = null; + for (var i=0;i - + Korektury {{pdf.nazev}} @@ -20,6 +20,29 @@           | hlavní stránka | wiki | +
+ Zobrazit: + + + + + +