merge
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -24,3 +24,9 @@ TODO | |||
| 
 | ||||
| # .htpasswd kvůli přihlášení | ||||
| .htpasswd | ||||
| 
 | ||||
| # reversion kvůli historii objektů v reversion | ||||
| **/reversion | ||||
| 
 | ||||
| # pro lidi, co programují v nástrojích od JetBrains | ||||
| .idea | ||||
							
								
								
									
										187
									
								
								MIGRATIONS
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,187 @@ | |||
| Jak zvládnout migrace na nový model: | ||||
| 
 | ||||
| - V mojí verzi databáze mají úlohy-Problémy typ "b'uloha'" | ||||
| 
 | ||||
| 
 | ||||
| Log migrace na nový model: | ||||
| 
 | ||||
| Operations to perform: | ||||
|   Apply all migrations: admin, auth, contenttypes, django_comments, flatpages, fluent_comments, galerie, korektury, prednasky, reversion, seminar, sessions, sites, sitetree, taggit, threadedcomments | ||||
| Running migrations: | ||||
|   Applying admin.0003_logentry_add_action_flag_choices... OK | ||||
|   Applying auth.0009_alter_user_last_name_max_length... OK | ||||
|   Applying auth.0010_alter_group_name_max_length... OK | ||||
|   Applying auth.0011_update_proxy_permissions... OK | ||||
|   Applying galerie.0008_auto_20190430_2340... OK | ||||
|   Applying galerie.0009_auto_20190610_2358... OK | ||||
|   Applying galerie.0010_auto_20200819_0947... OK | ||||
|   Applying korektury.0016_auto_20190430_2340... OK | ||||
|   Applying korektury.0017_auto_20190610_2358... OK | ||||
|   Applying prednasky.0011_auto_20190430_2340... OK | ||||
|   Applying prednasky.0012_auto_20190610_2358... OK | ||||
|   Applying seminar.0049_auto_20190430_2354... OK | ||||
|   Applying seminar.0050_auto_20190510_2228... OK | ||||
|   Applying seminar.0051_resitel_to_osoba... OK | ||||
|   Applying seminar.0052_user_to_organizator... OK | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2004-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1998-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2017-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2017-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2014-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2011-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2013-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2004-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2013-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2012-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2007-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2011-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2009-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2009-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2008-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2005-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2015-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2001-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2010-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2008-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2006-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2002-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2005-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1999-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2003-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2000-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2002-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2001-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1996-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2000-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (1999-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (1996-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1994-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2012-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2016-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2018-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2014-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2019-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2006-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1995-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2007-12-31 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2015-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2016-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2018-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2019-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
| /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2020-01-01 00:00:00) while time zone support is active. | ||||
|   RuntimeWarning) | ||||
|   Applying seminar.0053_organizator_organizuje_od_do... OK | ||||
|   Applying seminar.0055_smazat_nemigrovane_zastarale_veci... OK | ||||
|   Applying seminar.0056_vrcholy_pro_rocniky_a_cisla... OK | ||||
|   Applying seminar.0057_reseni_to_reseni_hodnoceni...!!!!!!!!!!!!!!! | ||||
| 31397 Reseni object (31397) | ||||
| !!!!!!!!!!!!!!! | ||||
| !!!!!!!!!!!!!!! | ||||
| 31396 Reseni object (31396) | ||||
| !!!!!!!!!!!!!!! | ||||
| !!!!!!!!!!!!!!! | ||||
| 31395 Reseni object (31395) | ||||
| !!!!!!!!!!!!!!! | ||||
| !!!!!!!!!!!!!!! | ||||
| 31394 Reseni object (31394) | ||||
| !!!!!!!!!!!!!!! | ||||
| !!!!!!!!!!!!!!! | ||||
| 31393 Reseni object (31393) | ||||
| !!!!!!!!!!!!!!! | ||||
|  OK | ||||
|   Applying seminar.0058_problem_to_uloha_tema_clanek... OK | ||||
|   Applying seminar.fix_0058... OK | ||||
|   Applying seminar.0059_vytvorit_pohadkanode... OK | ||||
|   Applying seminar.0060_spoj_stromy... OK | ||||
|   Applying seminar.0061_kill_frankenstein... OK | ||||
|   Applying seminar.0062_redukce_modelu_pohadky... OK | ||||
|   Applying seminar.0063_procisteni_migraci... OK | ||||
|   Applying seminar.0064_auto_20190610_2358... OK | ||||
|   Applying seminar.0065_treenode_polymorphic_ctype... OK | ||||
|   Applying seminar.0066_problem_polymorphic_ctype... OK | ||||
|   Applying seminar.0067_auto_20190814_0805... OK | ||||
|   Applying seminar.0068_treenode_nazev... OK | ||||
|   Applying seminar.0069_auto_20191120_2115... OK | ||||
|   Applying seminar.0070_auto_20191120_2357... OK | ||||
|   Applying seminar.0071_remove_nastaveni_aktualni_rocnik... OK | ||||
|   Applying seminar.0072_auto_20191204_2257... OK | ||||
|   Applying seminar.0073_copy_osoba_email_to_user_email... OK | ||||
|   Applying seminar.0074_auto_20200228_1401... OK | ||||
|   Applying seminar.0075_auto_20200228_2010... OK | ||||
|   Applying seminar.0076_auto_20200228_2013... OK | ||||
|   Applying seminar.0077_auto_20200318_2146... OK | ||||
|   Applying seminar.0078_otistenereseninode... OK | ||||
|   Applying seminar.0079_clanek_resitelsky... OK | ||||
|   Applying seminar.0080_zruseni_claneknode_a_konferanode... OK | ||||
|   Applying seminar.0081_auto_20200408_2221... OK | ||||
|   Applying seminar.0082_auto_20200506_1951... OK | ||||
|   Applying seminar.0083_auto_20200506_1952... OK | ||||
| WARNING 2020-08-20 00:49:07,941 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2215) | ||||
| WARNING 2020-08-20 00:49:07,953 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2221) | ||||
| WARNING 2020-08-20 00:49:07,959 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2212) | ||||
| WARNING 2020-08-20 00:49:07,965 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1955) | ||||
| WARNING 2020-08-20 00:49:07,968 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2027) | ||||
| WARNING 2020-08-20 00:49:07,971 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1981) | ||||
| WARNING 2020-08-20 00:49:07,974 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1970) | ||||
| WARNING 2020-08-20 00:49:07,978 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2001) | ||||
| WARNING 2020-08-20 00:49:07,981 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2004) | ||||
| WARNING 2020-08-20 00:49:07,984 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1941) | ||||
| WARNING 2020-08-20 00:49:07,990 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2024) | ||||
| WARNING 2020-08-20 00:49:07,993 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2031) | ||||
| WARNING 2020-08-20 00:49:07,997 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2211) | ||||
| WARNING 2020-08-20 00:49:08,005 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2073) | ||||
| WARNING 2020-08-20 00:49:08,017 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2018) | ||||
| WARNING 2020-08-20 00:49:08,022 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2222) | ||||
| WARNING 2020-08-20 00:49:08,028 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1953) | ||||
| WARNING 2020-08-20 00:49:08,034 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2026) | ||||
|   Applying seminar.0084_clanek_cislo... OK | ||||
|   Applying seminar.0085_nepovinna_prezdivka... OK | ||||
|   Applying seminar.0086_auto_20200819_0959... OK | ||||
|   Applying sitetree.0001_initial... OK | ||||
|   Applying taggit.0003_taggeditem_add_unique_index... OK | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						|  | @ -65,7 +65,7 @@ schema_all.pdf: venv_check | |||
| # Deploy to current *mamweb-test* directory
 | ||||
| deploy_test: venv_check | ||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | ||||
| 	@if [ `pwd` != "/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi | ||||
| 	@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in directory mamweb-test"; exit 1; fi | ||||
| 	@echo "Installing version from origin/test ..." | ||||
| 	git pull origin test | ||||
| 	git clean -f | ||||
|  | @ -81,9 +81,9 @@ deploy_test: venv_check | |||
| # Deploy to current *mamweb-prod* directory
 | ||||
| deploy_prod: venv_check | ||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | ||||
| 	@if [ `pwd` != "/akce/mam/www/mamweb-prod" ]; then echo "Only possible in /akce/mam/www/mamweb-prod"; exit 1; fi | ||||
| 	@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-prod" ]; then echo "Only possible in directory mamweb-prod"; exit 1; fi | ||||
| 	@echo "Backing up production DB ..." | ||||
| 	( cd .. && ./backup_prod_db.sh ) | ||||
| 	( cd -P .. && ./backup_prod_db.sh ) | ||||
| 	@echo "Installing version from origin/master ..." | ||||
| 	git pull origin master | ||||
| 	git clean -f | ||||
|  | @ -109,7 +109,7 @@ sync_prod_flatpages: venv_check | |||
| # Sync test media directory with production
 | ||||
| sync_test_media: | ||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | ||||
| 	@if [ `pwd` != "/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi | ||||
| 	@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi | ||||
| 	rsync -av --delete /akce/mam/www/mamweb-prod/media/ ./media | ||||
| 
 | ||||
| # Sync test database with production database
 | ||||
|  |  | |||
|  | @ -30,14 +30,14 @@ def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): | |||
| 
 | ||||
| class GalerieInline(admin.TabularInline): | ||||
| 	model = Obrazek | ||||
| 	fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag'] | ||||
| 	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') | ||||
| 	list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi') | ||||
| 	search_fields = ['nazev','popis'] | ||||
| 
 | ||||
| class GalerieAdmin(admin.ModelAdmin): | ||||
|  |  | |||
							
								
								
									
										18
									
								
								galerie/migrations/0010_auto_20200819_0947.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,18 @@ | |||
| # Generated by Django 2.2.15 on 2020-08-19 07:47 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('galerie', '0009_auto_20190610_2358'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='galerie', | ||||
|             name='poradi', | ||||
|             field=models.IntegerField(blank=True, default=0, verbose_name='Pořadí'), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -94,7 +94,7 @@ class Galerie(models.Model): | |||
| 		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 = True) | ||||
| 	poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) | ||||
| 
 | ||||
| 	def __str__(self): | ||||
| 		return self.nazev | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ Galerie {{galerie.nazev}} | |||
|             {{ galerie|truncatechars:max_delka_nazvu }} | ||||
|             </div> | ||||
|         </a> | ||||
|         {% if user.is_staff and galerie.zobrazit > 0 %} | ||||
|         {% if user.je_org and galerie.zobrazit > 0 %} | ||||
|           <div class="mam-org-only-galerie"> | ||||
|             ({{galerie.poradi}}) | ||||
|             <span class="plus"><a href="plus/{{galerie.pk}}/">+</a></span> | ||||
|  | @ -73,7 +73,7 @@ Galerie {{galerie.nazev}} | |||
|       {% endwith %} | ||||
|     {% endif %} | ||||
|   {% endif %} | ||||
|   {% if user.is_staff and galerie.zobrazit > 0 %} | ||||
|   {% if user.je_org and galerie.zobrazit > 0 %} | ||||
|   <div class="mam-org-only"> | ||||
|       <a href="./new">Vytvořit novou podgalerii </a> | ||||
|   </div> | ||||
|  |  | |||
|  | @ -1,13 +1,14 @@ | |||
| # coding: utf-8 | ||||
| 
 | ||||
| from django.urls import path | ||||
| from seminar.utils import org_required | ||||
| from . import views | ||||
| 
 | ||||
| urlpatterns = [ | ||||
| 	path('<int:pk>/', views.nahled), | ||||
| 	path('<int:pk>/<int:fotka>/', views.detail), | ||||
| 	path('<int:galerie>/new/', views.new_galerie), | ||||
| 	path('<int:galerie>/plus/<int:subgalerie>/', views.plus_galerie), | ||||
| 	path('<int:galerie>/minus/<int:subgalerie>/', views.minus_galerie), | ||||
| 	path('<int:galerie>/new/', org_required(views.new_galerie)), | ||||
| 	path('<int:galerie>/plus/<int:subgalerie>/', org_required(views.plus_galerie)), | ||||
| 	path('<int:galerie>/minus/<int:subgalerie>/', org_required(views.minus_galerie)), | ||||
| ] | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ from galerie.forms import KomentarForm, NewGalerieForm | |||
| def zobrazit(galerie, request): | ||||
| 	preview = False | ||||
| 	if galerie.zobrazit >= 1: | ||||
| 		if request.user.is_staff: | ||||
| 		if request.user.je_org: | ||||
| 			preview = True; | ||||
| 		else: | ||||
| 			raise Http404 | ||||
|  | @ -35,16 +35,16 @@ def nahled(request, pk, soustredeni): | |||
| 	galerie = get_object_or_404(Galerie, pk=pk) | ||||
| 
 | ||||
| 	podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') | ||||
| 	if not request.user.is_staff: | ||||
| 	if not request.user.je_org: | ||||
| 		podgalerie = podgalerie.filter(zobrazit__lt=1) | ||||
| 
 | ||||
| 	obrazky = Obrazek.objects.filter(galerie = galerie) | ||||
| 	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: | ||||
| 		if not request.user.je_org: | ||||
| 			sourozenci = sourozenci.filter(zobrazit__lt=1) | ||||
| 
 | ||||
| 	predchozi = None | ||||
|  | @ -82,7 +82,7 @@ def detail(request, pk, fotka, soustredeni): | |||
| 	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() | ||||
| 	obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') | ||||
| 
 | ||||
| 	# vytvoreni a obslouzeni formulare | ||||
| 	if request.method == 'POST': | ||||
|  | @ -96,22 +96,23 @@ def detail(request, pk, fotka, soustredeni): | |||
| 	# Poradi aktualniho obrazku v galerii/stitku. | ||||
| 	for i in range(len(obrazky)): | ||||
| 		if obrazky[i] == obrazek: | ||||
| 			znacka = i | ||||
| 			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[znacka+1:znacka+NAHLEDU+1] | ||||
| 	if (znacka+1) > NAHLEDU: | ||||
| 		obrazky_predchozi = obrazky[znacka-NAHLEDU:znacka] | ||||
| 	obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1] | ||||
| 	if (poradi+1) > NAHLEDU: | ||||
| 		obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi] | ||||
| 	else: | ||||
| 		obrazky_predchozi = obrazky[0:znacka] | ||||
| 		obrazky_predchozi = obrazky[0:poradi] | ||||
| 		if galerie.poradi > 1: | ||||
| 			predchozi_galerie = Galerie.objects.\ | ||||
| 				filter(galerie_up=galerie.galerie_up).\ | ||||
|  | @ -120,41 +121,44 @@ def detail(request, pk, fotka, soustredeni): | |||
| 			predchozi_galerie = predchozi_galerie[0] | ||||
| 		else: | ||||
| 			predchozi_galerie = None | ||||
| 	if (znacka+1) == len(obrazky): | ||||
| 		nasledujici_galerie = Galerie.objects.\ | ||||
| 				filter(galerie_up=galerie.galerie_up).\ | ||||
| 				filter(poradi=(galerie.poradi+1)) | ||||
| 	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 | ||||
| 		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), | ||||
| 			}) | ||||
| 
 | ||||
| 		{'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): | ||||
| 
 | ||||
|  |  | |||
|  | @ -79,22 +79,31 @@ class KorekturovanePDF(models.Model): | |||
| 		self.stran = 0 | ||||
| 		while True: | ||||
| 			res = subprocess.call([ | ||||
| 				"convert", | ||||
| 				"-density", "180x180", | ||||
| 				"-geometry", " 1024x1448", | ||||
| 				"%s[%d]" % (self.pdf.path, self.stran), | ||||
| 				os.path.join( | ||||
| 				#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) | ||||
| 				) | ||||
| 					"%s-%d.png" % (self.get_prefix(), self.stran)), | ||||
| 				"-f%s" % (self.pdf.path) | ||||
| 			]) | ||||
| 			if res == 1: | ||||
| 			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): | ||||
| 	def save(self, **kwargs): | ||||
| 		# Pokud se nezmenilo PDF, tak nepregenerovavej nahledy | ||||
| 		try: | ||||
| 			original = KorekturovanePDF.objects.get(pk=self.pk) | ||||
|  | @ -104,7 +113,7 @@ class KorekturovanePDF(models.Model): | |||
| 		except ObjectDoesNotExist: | ||||
| 			pass | ||||
| 		# uložíme nahrávané pdf | ||||
| 		super(KorekturovanePDF, self).save() | ||||
| 		super(KorekturovanePDF, self).save(kwargs) | ||||
| 
 | ||||
| 		# uložíme png a změněný počet stran | ||||
| 		self.convert() | ||||
|  |  | |||
|  | @ -1,5 +1,9 @@ | |||
| {% extends "base.html" %} | ||||
| 
 | ||||
| {% block submenu %} | ||||
|   {% include "korektury/submenu.html" %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block content %} | ||||
| {# blok do kterého se nacita text, v pripade jinyhc templatu obalit vlastnim blokem #} | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -1,4 +1,11 @@ | |||
| {% extends "korektury/base.html" %} | ||||
| 
 | ||||
| {% block submenu %} | ||||
|   {% with "help" as selected %} | ||||
|     {% include "korektury/submenu.html" %} | ||||
|   {% endwith %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% load staticfiles %} | ||||
| 
 | ||||
| {% block title %} Nápověda ke korigovátku {% endblock title %} | ||||
|  |  | |||
|  | @ -36,12 +36,12 @@ | |||
| 		id="neni_chyba_checkbox" | ||||
| 		name="neni_chyba_checkbox" | ||||
| 		onchange="toggle_corrections('neni_chyba')" checked> | ||||
| 	<label for="neni_chyba_checkbox">Není chyba ({{neni_chyba_cnt}})</labe> | ||||
| 	<label for="neni_chyba_checkbox">Není chyba ({{neni_chyba_cnt}})</label> | ||||
| 	<input type="checkbox" | ||||
| 		id="k_zaneseni_checkbox" | ||||
| 		name="k_zaneseni_checkbox" | ||||
| 		onchange="toggle_corrections('k_zaneseni')" checked> | ||||
| 	<label for="k_zaneseni_checkbox">K zanesení ({{k_zaneseni_cnt}})</labe> | ||||
| 	<label for="k_zaneseni_checkbox">K zanesení ({{k_zaneseni_cnt}})</label> | ||||
| 
 | ||||
| 	<hr/> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,10 @@ | |||
| {% extends "korektury/base.html" %} | ||||
| {% load staticfiles %} | ||||
| 
 | ||||
| {% block submenu %} | ||||
|   {% include "korektury/submenu.html" %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block script%} | ||||
|   <link rel="stylesheet" type="text/css" media="screen, projection" href="{% static "korektury/opraf-list.css" %}" /> | ||||
| {% endblock %} | ||||
|  |  | |||
							
								
								
									
										13
									
								
								korektury/templates/korektury/submenu.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,13 @@ | |||
| {% with "/korektury" as cesta %} | ||||
| 
 | ||||
| <div id='submenu'> | ||||
| <ul> | ||||
|   <li class="{% if selected == "aktualni" %}selected{% endif %}"><a href="{{cesta}}/">Aktuální</a> | ||||
|   <li class="{% if selected == "zastarale" %}selected{% endif %}"><a href="{{cesta}}/zastarale/">Zastaralé</a> | ||||
|   <li class="{% if selected == "help" %}selected{% endif %}"><a href="{{cesta}}/help/">Nápověda</a> | ||||
| </ul> | ||||
| </div> | ||||
| 
 | ||||
| {% endwith %} | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										
											BIN
										
									
								
								korektury/testpdfs/A.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5125
									
								
								korektury/testpdfs/B.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										69
									
								
								korektury/testutils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,69 @@ | |||
| import logging | ||||
| import os | ||||
| from shutil import copyfile, rmtree | ||||
| 
 | ||||
| from django.db import transaction | ||||
| from django.conf import settings | ||||
| 
 | ||||
| from korektury.models import KorekturovanePDF, generate_filename | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| @transaction.atomic | ||||
| def create_test_pdf(rnd, organizatori): | ||||
| 	logger.info('Vyrábím testovací pdf ke korekturovani') | ||||
| 	try: | ||||
| 		testpdfs = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'testpdfs') | ||||
| 
 | ||||
| 		# smaže minulé pdfka a obrázky k nim a vytvoří (znovu) jejich složky | ||||
| 		pdf_dir = os.path.join(settings.BASE_DIR, os.path.join('media', settings.KOREKTURY_PDF_DIR)) | ||||
| 		img_dir = os.path.join(settings.BASE_DIR, os.path.join('media', settings.KOREKTURY_IMG_DIR)) | ||||
| 		rmtree(pdf_dir, ignore_errors=True) | ||||
| 		os.makedirs(pdf_dir) | ||||
| 		rmtree(img_dir, ignore_errors=True) | ||||
| 		os.makedirs(img_dir) | ||||
| 
 | ||||
| 		def gen_filename(filename): | ||||
| 			name = generate_filename(None, filename) | ||||
| 			print(name) | ||||
| 			copyfile(os.path.join(testpdfs, filename), os.path.join(settings.BASE_DIR, os.path.join('media', name))) | ||||
| 			return name | ||||
| 
 | ||||
| 		# TODO silent ghostscript (vypisuje odstavec za každou stránku…) | ||||
| 
 | ||||
| 		KorekturovanePDF.objects.create( | ||||
| 			nazev='B', komentar='Neuronové sítě', org=rnd.choice(organizatori), pdf=gen_filename(filename='B.pdf') | ||||
| 		) | ||||
| 
 | ||||
| 		KorekturovanePDF.objects.create( | ||||
| 			nazev='A', komentar='M&M: Jak řešit?', org=rnd.choice(organizatori), pdf=gen_filename(filename='A.pdf') | ||||
| 		) | ||||
| 
 | ||||
| 		korekturovane_pdf = KorekturovanePDF.objects.create( | ||||
| 			nazev='A', komentar='M&M: Jak řešit?', org=rnd.choice(organizatori), pdf=gen_filename(filename='A.pdf'), | ||||
| 			status='zanaseni' | ||||
| 		) | ||||
| 
 | ||||
| 		KorekturovanePDF.objects.create( | ||||
| 			nazev='A', komentar='M&M: Jak řešit?', org=rnd.choice(organizatori), pdf=gen_filename(filename='A.pdf'), | ||||
| 			status='zastarale' | ||||
| 		) | ||||
| 	except (FileNotFoundError, Exception) as e: | ||||
| 		# TODO najít správné chyby, které vyhazují různé systémy při neexistenci ImageMagick, nebo knihoven | ||||
| 		logger.error(str(e)) | ||||
| 		logger.error( | ||||
| 			'Chyba vytváření testovacích korektur, pravděpodobně není nainstalován ImageMagick nebo některá z knihoven' | ||||
| 			'pro práci se soubory pdf (ghostscript) nebo png (libpng?).\n' | ||||
| 			''' | ||||
| 				Instalaci na linux provedete např. příkazy: | ||||
| 				sudo apt-get build-dep imagemagick | ||||
| 				git clone https://github.com/ImageMagick/ImageMagick.git | ||||
| 				cd ImageMagick/ | ||||
| 				./configure | ||||
| 				make | ||||
| 				sudo make install | ||||
| 				sudo ldconfig /usr/local/lib | ||||
| 				cd .. | ||||
| 				rm -r ImageMagick/ | ||||
| 			''' | ||||
| 		) | ||||
|  | @ -1,11 +1,10 @@ | |||
| from django.urls import path | ||||
| from django.contrib.auth.decorators import user_passes_test | ||||
| from seminar.utils import org_required | ||||
| from . import views | ||||
| 
 | ||||
| staff_member_required = user_passes_test(lambda u: u.is_staff) | ||||
| 
 | ||||
| urlpatterns = [ | ||||
| 	path('korektury/', staff_member_required(views.KorekturyListView.as_view()), name='korektury-list'), | ||||
| 	path('korektury/<int:pdf>/', staff_member_required(views.KorekturyView.as_view()), name='korektury'), | ||||
| 	path('korektury/help/', staff_member_required(views.KorekturyHelpView.as_view()), name='korektury-help'), | ||||
| 	path('korektury/', org_required(views.KorekturyAktualniListView.as_view()), name='korektury-list'), | ||||
| 	path('korektury/zastarale/', org_required(views.KorekturyZastaraleListView.as_view()), name='korektury-list'), | ||||
| 	path('korektury/<int:pdf>/', org_required(views.KorekturyView.as_view()), name='korektury'), | ||||
| 	path('korektury/help/', org_required(views.KorekturyHelpView.as_view()), name='korektury-help'), | ||||
| ] | ||||
|  |  | |||
|  | @ -29,6 +29,28 @@ class KorekturyListView(generic.ListView): | |||
| 		) | ||||
| 	template_name = 'korektury/seznam.html' | ||||
| 
 | ||||
| class KorekturyAktualniListView(KorekturyListView): | ||||
|     def get_queryset(self, *args, **kwargs): | ||||
|         queryset=super(KorekturyAktualniListView,self).get_queryset() | ||||
|         queryset=queryset.exclude(status="zastarale") | ||||
|         return queryset | ||||
| 
 | ||||
|     def get_context_data(self, **kwargs): | ||||
|         context = super(KorekturyAktualniListView,self).get_context_data(**kwargs) | ||||
|         context['selected'] = 'aktualni' | ||||
|         return context | ||||
| 
 | ||||
| class KorekturyZastaraleListView(KorekturyListView): | ||||
|     def get_queryset(self, *args, **kwargs): | ||||
|         queryset=super(KorekturyZastaraleListView,self).get_queryset() | ||||
|         queryset=queryset.filter(status="zastarale") | ||||
|         return queryset | ||||
| 
 | ||||
|     def get_context_data(self, **kwargs): | ||||
|         context = super(KorekturyZastaraleListView,self).get_context_data(**kwargs) | ||||
|         context['selected'] = 'zastarale' | ||||
|         return context | ||||
| 
 | ||||
| ### Korektury | ||||
| class KorekturyView(generic.TemplateView): | ||||
| 	model = Oprava | ||||
|  | @ -130,7 +152,9 @@ class KorekturyView(generic.TemplateView): | |||
| 		''' | ||||
| 
 | ||||
| 		# parametry e-mailu | ||||
| 		odkaz = "https://mam.mff.cuni.cz/korektury/{}/".format(oprava.pdf.pk) | ||||
| 		#odkaz = "https://mam.mff.cuni.cz/korektury/{}/".format(oprava.pdf.pk) | ||||
| 		from django.urls import reverse | ||||
| 		odkaz = self.request.build_absolute_uri(reverse('korektury', kwargs={'pdf': oprava.pdf.pk})) | ||||
| 		from_email = 'korekturovatko@mam.mff.cuni.cz' | ||||
| 		subject = 'Nová korektura od {} v {}'.format(autor, | ||||
| 													 oprava.pdf.nazev) | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ INSTALLED_APPS = ( | |||
| 
 | ||||
|     # Utilities | ||||
|     'sekizai', | ||||
| #    'reversion', | ||||
|     'reversion', | ||||
|     'django_countries', | ||||
|     'solo', | ||||
|     'ckeditor', | ||||
|  | @ -136,7 +136,6 @@ INSTALLED_APPS = ( | |||
| #    'admin_tools.theming', | ||||
| #    'admin_tools.menu', | ||||
| #    'admin_tools.dashboard', | ||||
|     'flat', | ||||
|     'django.contrib.admin', | ||||
| ) | ||||
| 
 | ||||
|  | @ -179,7 +178,8 @@ CKEDITOR_CONFIGS = { | |||
| #        'toolbar': 'full', | ||||
|         'height': '40em', | ||||
|         'width': '100%', | ||||
|         'toolbarStartupExpanded': False | ||||
|         'toolbarStartupExpanded': False, | ||||
|         'allowedContent' : True, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
|  | @ -248,7 +248,7 @@ LOGGING = { | |||
|                 'class': 'django.utils.log.AdminEmailHandler', | ||||
|                 'formatter': 'verbose',  | ||||
|                 }, | ||||
|             'mail_registraion': { | ||||
|             'mail_registration': { | ||||
|                 'level': 'WARN', | ||||
|                 'class': 'django.utils.log.AdminEmailHandler', | ||||
|                 'formatter': 'verbose',  | ||||
|  |  | |||
|  | @ -94,4 +94,6 @@ LOGGING = { | |||
| # set to 'DEBUG' for EXTRA verbose output | ||||
| # LOGGING['handlers']['console']['level'] = 'INFO' | ||||
| 
 | ||||
| # E-maily posílat chceme, ale do terminálu :-) | ||||
| EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' | ||||
| SEND_EMAIL_NOTIFICATIONS = True | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ import os.path | |||
| # Import common settings | ||||
| from .settings_common import * # zatim nutne, casem snad vyresime # noqa | ||||
| 
 | ||||
| MIDDLEWARE_CLASSES += ( | ||||
| MIDDLEWARE += ( | ||||
|     'debug_toolbar.middleware.DebugToolbarMiddleware', | ||||
|     ) | ||||
| 
 | ||||
|  | @ -32,7 +32,7 @@ DEBUG = True | |||
| 
 | ||||
| TEMPLATES[0]['OPTIONS']['debug'] = True | ||||
| 
 | ||||
| ALLOWED_HOSTS = ['*.mam.mff.cuni.cz', 'atrey.karlin.mff.cuni.cz', 'mam.mff.cuni.cz', 'mam-test.kam.mff.cuni.cz', 'gimli.ms.mff.cuni.cz'] | ||||
| ALLOWED_HOSTS = ['*.mam.mff.cuni.cz', 'atrey.karlin.mff.cuni.cz', 'mam.mff.cuni.cz', 'mam-test.kam.mff.cuni.cz', 'gimli.ms.mff.cuni.cz', 'mam-test.ks.matfyz.cz'] | ||||
| 
 | ||||
| # Database | ||||
| # https://docs.djangoproject.com/en/1.7/ref/settings/#databases | ||||
|  |  | |||
|  | @ -338,6 +338,10 @@ ul.submenu li>a:hover { | |||
| 	color: black; | ||||
| } | ||||
| 
 | ||||
| ul.menu li.active>a, ul.submenu li.active>a { | ||||
| 	color: black; | ||||
| } | ||||
| 
 | ||||
| /* konec nového menu */ | ||||
| 
 | ||||
| div.novinky_name { | ||||
|  |  | |||
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
|  | @ -12,7 +12,7 @@ | |||
|     <link href="{% static 'css/mamweb.css' %}" rel="stylesheet"> | ||||
|     <link href="{% static 'css/prettyPhoto.css' %}" rel="stylesheet" type="text/css" media="screen" charset="utf-8" /> | ||||
|     <script src="{% static 'js/jquery-1.11.1.js' %}"></script> | ||||
|     <script src="{% static '/jquery-3.4.1.js' %}"></script> | ||||
|     <script src="{% static 'js/jquery-3.4.1.js' %}"></script> | ||||
| 
 | ||||
|     <link rel="stylesheet" type="text/css" href="{% static 'fluent_comments/css/ajaxcomments.css' %}" /> | ||||
|     <script type="text/javascript" src="{% static 'fluent_comments/js/ajaxcomments.js' %}"></script> | ||||
|  | @ -57,7 +57,7 @@ | |||
|           <a href='/'> | ||||
| 	    <div id="title" >M&M - korespondenční seminář a časopis MFF UK</div> | ||||
|             <div id="header" class="{% if noc %}NOC{% endif %}{% block header %}{% endblock %}"> | ||||
| 		<img class="logo" src="{% static 'images/logo.svg' %}" /> | ||||
| 		{% sitetree_menu from "main_menu" include "trunk" template "logo.html" %} | ||||
| 		<img class="logo-mobile" src="{% static 'images/logo-mobile.svg' %}" /> | ||||
|             </div> | ||||
|             </a> | ||||
|  | @ -106,7 +106,7 @@ | |||
| 		<div id="footer"> | ||||
| 			<p class="license">S obsahem webu M&M je možné nakládat dle licence <a href="https://creativecommons.org/licenses/by/3.0/cz/">Creative Commons Attribution 3.0</a>.</p> | ||||
| 		</div> | ||||
| 		<p class="license-mobile">Korespondenční seminář M&M organizují převážně studenti <a herf="https://www.mff.cuni.cz/">MFF UK</a>. Organizaci semináře a vydávání časopisu podporuje <a href="https://jcmf.cz/">Jednota českých matematiků a fyziků</a>. S obsahem webu M&M je možné nakládat dle licence <a href="https://creativecommons.org/licenses/by/3.0/cz/">Creative Commons Attribution 3.0</a>.</p> | ||||
| 		<p class="license-mobile">Korespondenční seminář M&M organizují převážně studenti <a href="https://www.mff.cuni.cz/">MFF UK</a>. Organizaci semináře a vydávání časopisu podporuje <a href="https://jcmf.cz/">Jednota českých matematiků a fyziků</a>. S obsahem webu M&M je možné nakládat dle licence <a href="https://creativecommons.org/licenses/by/3.0/cz/">Creative Commons Attribution 3.0</a>.</p> | ||||
| 	  </div> | ||||
| 	</div> | ||||
|     </div> | ||||
|  |  | |||
							
								
								
									
										26
									
								
								mamweb/templates/logo.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,26 @@ | |||
| {% load staticfiles %} | ||||
| <img class="logo" | ||||
|     {% for item in sitetree_items %} | ||||
|         {% if item.is_active or item.in_current_branch %} | ||||
|             {% if forloop.counter == 1 %} | ||||
|                 src="{% static 'images/logo_1.svg' %}" | ||||
|             {% endif %} | ||||
|             {% if forloop.counter == 2 %} | ||||
|                 src="{% static 'images/logo_2.svg' %}" | ||||
|             {% endif %} | ||||
|             {% if forloop.counter == 3 %} | ||||
|                 src="{% static 'images/logo_3.svg' %}" | ||||
|             {% endif %} | ||||
|             {% if forloop.counter == 4 %} | ||||
|                 src="{% static 'images/logo_4.svg' %}" | ||||
|             {% endif %} | ||||
|             {% if forloop.counter == 5 %} | ||||
|                 src="{% static 'images/logo_5.svg' %}" | ||||
|             {% endif %} | ||||
|             {% if forloop.counter == 6 %} | ||||
|                 src="{% static 'images/logo_6.svg' %}" | ||||
|             {% endif %} | ||||
|         {% endif %} | ||||
|     {% endfor %} | ||||
|     src="{% static 'images/logo.svg' %}" | ||||
| /> | ||||
|  | @ -3,7 +3,9 @@ | |||
| {% autoescape off %} | ||||
| <ul class="menu"> | ||||
|     {% for item in sitetree_items %} | ||||
|         <li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}" >  | ||||
|         <li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}" | ||||
|             style="{% if item.title == "HIDDEN" %}display:none{% endif %}" | ||||
|         > | ||||
|             <a href="{% sitetree_url for item %}" > | ||||
|                 {{ item.title_resolved }} | ||||
|             </a> | ||||
|  |  | |||
|  | @ -3,7 +3,9 @@ | |||
| {% autoescape off %} | ||||
| <ul class="menu_mobile"> | ||||
|     {% for item in sitetree_items %} | ||||
|         <li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}"> | ||||
|         <li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}" | ||||
|             style="{% if item.title == "HIDDEN" %}display:none{% endif %}" | ||||
|         > | ||||
|             <a href="{% if item.has_children %}#{% else %}{% sitetree_url for item %}{% endif %}" {% if item.has_children %}class="dropdown-toggle" data-toggle="dropdown"{% endif %}> | ||||
|                 {{ item.title_resolved }} | ||||
|             </a> | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ chdir = /akce/mam/www/mamweb-prod/ | |||
| home = /akce/mam/www/mamweb-prod/ | ||||
| 
 | ||||
| module = mamweb.wsgi | ||||
| plugin = python | ||||
| plugin = python3 | ||||
| virtualenv = env | ||||
| master = True | ||||
| vacuum = True | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ chdir = /akce/mam/www/mamweb-test/ | |||
| home = /akce/mam/www/mamweb-test/ | ||||
| 
 | ||||
| module = mamweb.wsgi | ||||
| plugin = python | ||||
| plugin = python3 | ||||
| virtualenv = env | ||||
| master = True | ||||
| vacuum = True | ||||
|  |  | |||
|  | @ -17,19 +17,17 @@ Jak moc by ses chtěl(a) zúčastnit následujících přednášek? | |||
| 
 | ||||
| <form enctype="multipart/form-data" action="." method="post"> | ||||
|   {% csrf_token %} | ||||
|   <table>{{form.as_table}} | ||||
|   </table> | ||||
|   <table> | ||||
|     {% for p in prednasky.prednaska_set.all %} | ||||
|     {% for p, h in prednasky %} | ||||
|     <tr><td><label>{{p.org}}: <span style="font-size: 175%">{{p.nazev}}</span></label></td></tr> | ||||
|     <tr><td><p><i>{{p.anotace}}</i></p></td></tr> | ||||
|     <tr><td><label>Obor: </label> {{p.obor}}</td></tr> | ||||
|     <tr><td><label>Obtížnost: </label> {{p.obtiznost}}</td>   </tr> | ||||
|     {% if p.klicova %}<tr><td><label>Klíčová slova: </label> {{p.klicova}}</td></tr>{% endif%} | ||||
|     <tr><td>Hodnocení: | ||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="-1"> rozhodně nechci | ||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="0" checked> je mi to jedno | ||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="1"> rozhodně chci | ||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="-1" {% if h == -1 %} CHECKED="checked" {% endif %} > rozhodně nechci | ||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="0" {% if h == 0 %} CHECKED="checked" {% endif %}> je mi to jedno | ||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="1" {% if h == 1 %} CHECKED="checked" {% endif %}> rozhodně chci | ||||
|     </td></tr> | ||||
|     <tr><td> </td></tr> | ||||
|     {% endfor %} | ||||
|  |  | |||
|  | @ -19,6 +19,8 @@ | |||
|     <a href="/prednasky/seznam_prednasek/{{seznam.id}}/export">Export</a> | ||||
|     </li> | ||||
|   {% endfor %} | ||||
|   </ul> | ||||
|   </div> | ||||
| 
 | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,5 +15,7 @@ | |||
|       {{ prednaska.body }} b</i>) – {{ prednaska.org }} | ||||
|     </li> | ||||
|   {% endfor %} | ||||
|   </ul> | ||||
|   </div> | ||||
| 
 | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -1,19 +1,7 @@ | |||
| {% block content %} | ||||
| {% spaceless %} | ||||
| {% for hlas in hlasovani %} | ||||
| hlas({{hlas.ucastnik}},{{hlas.prednaska.id}},{{hlas.body}}) | ||||
| {% endfor %} | ||||
| {% for prednaska in prednasky %} | ||||
| prednaska({{prednaska.id}},{{prednaska.org.id}},{{prednaska.obtiznost}},{{prednaska.obor}}) | ||||
| {% endfor %} | ||||
| {% for org in orgove %} | ||||
| org({{org.id}},4,0,15) | ||||
| {% endfor %} | ||||
| {% for org in orgove %} | ||||
| {{org.id}};{{org}} | ||||
| {% endfor %} | ||||
| {% for prednaska in prednasky %} | ||||
| {{prednaska.id}};{{prednaska.nazev}};{{prednaska.org.id}} | ||||
| {{prednaska.id}};{{prednaska.nazev}};{{prednaska.org}} | ||||
| {{prednaska.body}} | ||||
| {% endfor %} | ||||
| {% endspaceless %} | ||||
|  |  | |||
|  | @ -1,14 +1,25 @@ | |||
| from django.urls import path | ||||
| from django.contrib.auth.decorators import user_passes_test | ||||
| from seminar.utils import org_required, resitel_required | ||||
| from . import views | ||||
| 
 | ||||
| staff_member_required = user_passes_test(lambda u: u.is_staff) | ||||
| 
 | ||||
| urlpatterns = [ | ||||
| 	path('prednasky/', views.newPrednaska), | ||||
| 	path( | ||||
| 		'prednasky/', | ||||
| 		resitel_required(views.newPrednaska) | ||||
| 	), | ||||
| 	path('prednasky/hotovo', views.Prednaska_hotovo), | ||||
| 	path('prednasky/metaseznam_prednasek', staff_member_required(views.MetaSeznamListView.as_view()), name='metaseznam-list'), | ||||
| 	path('prednasky/seznam_prednasek/<int:seznam>/export', staff_member_required(views.SeznamExportView), name='seznam-export'), | ||||
| 	path('prednasky/seznam_prednasek/<int:seznam>/', staff_member_required(views.SeznamListView.as_view()), name='seznam-list'), | ||||
| #	path('korektury/help/', staff_member_required(views.KorekturyHelpView.as_view()), name='korektury-help'), | ||||
| 	path( | ||||
| 		'prednasky/metaseznam_prednasek', | ||||
| 		org_required(views.MetaSeznamListView.as_view()), | ||||
| 		name='metaseznam-list'), | ||||
| 	path( | ||||
| 		'prednasky/seznam_prednasek/<int:seznam>/export', | ||||
| 		org_required(views.SeznamExportView), | ||||
| 		name='seznam-export' | ||||
| 	), | ||||
| 	path( | ||||
| 		'prednasky/seznam_prednasek/<int:seznam>/', | ||||
| 		org_required(views.SeznamListView.as_view()), | ||||
| 		name='seznam-list' | ||||
| 	), | ||||
| ] | ||||
|  |  | |||
|  | @ -4,41 +4,52 @@ from django.views import generic | |||
| from django.shortcuts import HttpResponseRedirect | ||||
| from django.core.exceptions import ObjectDoesNotExist | ||||
| from django.db.models import Sum | ||||
| from django.forms import Form | ||||
| 
 | ||||
| from prednasky.models import Prednaska, Hlasovani, Seznam, STAV_NAVRH | ||||
| from seminar.models import Soustredeni | ||||
| from prednasky.forms import NewPrednaskyForm | ||||
| from seminar.models import Soustredeni, Osoba | ||||
| 
 | ||||
| def newPrednaska(request): | ||||
| 	# hlasovani se vztahuje k nejnovejsimu soustredeni | ||||
| 	sous = Soustredeni.objects.first() | ||||
| 	seznam = Seznam.objects.filter(soustredeni = sous, stav = STAV_NAVRH).first() | ||||
| 	print(seznam) | ||||
| 	osoba = Osoba.objects.filter(user=request.user).first() | ||||
| 	ucastnik = osoba.plne_jmeno() + ' ' + str(osoba.id) | ||||
| 	# obsluha formulare | ||||
| 	if request.method == 'POST': | ||||
| 		form = NewPrednaskyForm(request.POST, request.FILES) | ||||
| 		form = Form(request.POST, request.FILES) | ||||
| 		if form.is_valid(): | ||||
| 			jmeno = form.cleaned_data['ucastnik'] | ||||
| 			# id z důvodu duplicitních jmen (přechod z jména na objekt Osoby nějak kape na tom, | ||||
| 			# že všechna předchozí hlasování zde mají náhodný string…) | ||||
| 			# TODO Změnit to na Osobu | ||||
| 
 | ||||
| 			# TODO v následujících řádcích je zbytečně mnoho dotazů na QuerySet (pokud účastník hlasoval, hlasoval u všech) | ||||
| 			for i in request.POST: | ||||
| 				if i[0] == 'q': | ||||
| 					hlasovani = Hlasovani() | ||||
| 					print("q:"+i[1:]) | ||||
| 					hlasovani.prednaska = Prednaska.objects.filter(pk = int(i[1:]))[0] | ||||
| 					prednaska = Prednaska.objects.filter(pk=int(i[1:]))[0] | ||||
| 					hlasovani = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first() | ||||
| 					if not hlasovani: | ||||
| 						hlasovani = Hlasovani() | ||||
| 						hlasovani.prednaska = prednaska | ||||
| 						hlasovani.ucastnik = ucastnik | ||||
| 						hlasovani.seznam = seznam | ||||
| 					hlasovani.body = int(request.POST[i]) | ||||
| 					hlasovani.ucastnik = jmeno | ||||
| 					hlasovani.seznam = seznam | ||||
| 					hlasovani.save() | ||||
| 
 | ||||
| 			# presmerovani na prave vzniklou galerii | ||||
| 			return HttpResponseRedirect('./hotovo') | ||||
| 
 | ||||
| 	else: | ||||
| 		form = NewPrednaskyForm() | ||||
| 	def prednaska_hodnoceni(prednaska): | ||||
| 		h = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first() | ||||
| 		if h: | ||||
| 			return prednaska, h.body | ||||
| 		else: | ||||
| 			return prednaska, 0 | ||||
| 
 | ||||
| 	return render( | ||||
| 		request, | ||||
| 		'prednasky/base.html', | ||||
| 		{'form': form, 'prednasky': seznam} | ||||
| 		{'prednasky': map(prednaska_hodnoceni, seznam.prednaska_set.all())} | ||||
| 	) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -57,12 +68,26 @@ class SeznamListView(generic.ListView): | |||
| 		self.seznam = get_object_or_404(Seznam, id=self.kwargs["seznam"]) | ||||
| 		prednasky = Prednaska.objects.filter(seznamy=self.seznam).order_by( | ||||
| 			'org__user__first_name', 'org__user__last_name' | ||||
| 		).annotate(body=Sum('hlasovani__body')) | ||||
| 		) | ||||
| 		return prednasky | ||||
| 
 | ||||
| 	# FIXME nahradit anotaci s filtrem po prechodu na Django 2.2 | ||||
| 	def get_context_data(self,**kwargs): | ||||
| 		context = super(SeznamListView, self).get_context_data(**kwargs) | ||||
| 
 | ||||
| 		# hlasovani se vztahuje k nejnovejsimu soustredeni | ||||
| 		sous = Soustredeni.objects.first() | ||||
| 		seznam = Seznam.objects.filter(soustredeni = sous, stav = STAV_NAVRH).first() | ||||
| 	 | ||||
| 		for obj in self.object_list: | ||||
| 			hlasovani_set = obj.hlasovani_set.filter(seznam=seznam).only('body') | ||||
| 			obj.body = sum(map(lambda x: x.body,hlasovani_set)) | ||||
| 
 | ||||
| 		return context | ||||
| 
 | ||||
| 
 | ||||
| def SeznamExportView(request, seznam): | ||||
| 	u"""Vypíše výsledky hlasování ve formátu pro prologovský optimalizátor""" | ||||
| 	"""Vypíše výsledky hlasování ve formátu pro prologovský optimalizátor""" | ||||
| 	# TODO zřejmě se nepoužívá, časem vyřadit? nahradit tabulkou vhodnější pro | ||||
| 	# lidi? | ||||
| 	hlasovani = Hlasovani.objects.filter(seznam=seznam) | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ from django.contrib import admin | |||
| from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter | ||||
| from reversion.admin import VersionAdmin | ||||
| from django_reverse_admin import ReverseModelAdmin | ||||
| from solo.admin import SingletonModelAdmin | ||||
| 
 | ||||
| # Todo: reversion | ||||
| 
 | ||||
|  | @ -160,5 +161,5 @@ class TextNodeAdmin(PolymorphicChildModelAdmin): | |||
| 	show_in_index = True | ||||
| 
 | ||||
| 
 | ||||
| admin.site.register(m.Nastaveni) | ||||
| admin.site.register(m.Nastaveni, SingletonModelAdmin) | ||||
| admin.site.register(m.Novinky) | ||||
|  |  | |||
|  | @ -1,17 +1,17 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| from django.core.management.base import NoArgsCommand | ||||
| from django.core.management.base import BaseCommand | ||||
| from django.contrib.sessions.models import Session | ||||
| from django.contrib.auth.models import User | ||||
| 
 | ||||
| class Command(NoArgsCommand): | ||||
| class Command(BaseCommand): | ||||
|     u"""Vypiš username přihlášeného orga s daným session_key. | ||||
| 
 | ||||
|     Příkaz pro manage.py, který ze vstupu přečte session_key (tak, jak je | ||||
|     uložen v cookie sessionid) a pokud session existuje a příslušný přihlášený | ||||
|     uživatel má právo přihlásit se do admina, vypíše jeho username. | ||||
|     """ | ||||
|     def handle_noargs(self, **options): | ||||
|     def handle(self, *args, **options): | ||||
|         session_key = raw_input() | ||||
|         s = Session.objects.get(pk=session_key).get_decoded() | ||||
|         user_id = s['_auth_user_id'] | ||||
|  |  | |||
|  | @ -511,7 +511,7 @@ def vyrob_problemum_ctypes(apps, schema_editor): | |||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
|     atomic = False | ||||
|     replaces = [('seminar', '0001_initial'), ('seminar', '0002_add_body_views'), ('seminar', '0003_add_skola_zs_ss'), ('seminar', '0004_add_old_dakos_id'), ('seminar', '0005_alter_problem_autor'), ('seminar', '0006_problem_add_timestamp'), ('seminar', '0007_problem_zamereni'), ('seminar', '0008_reseni_forma'), ('seminar', '0009_rename_imported_IDs'), ('seminar', '0010_alter_rok_maturity'), ('seminar', '0011_alter_timestamp_def'), ('seminar', '0012_remove_soustredeni_ucastnici'), ('seminar', '0013_soustredeni_ucastnici_through_model'), ('seminar', '0014_uprava_poznamek'), ('seminar', '0015_soustredeni_text'), ('seminar', '0016_texty_problemu'), ('seminar', '0017_texty_problemu_minor'), ('seminar', '0018_problemnavrh_problemzadany'), ('seminar', '0019_rocnik_ciselne'), ('seminar', '0020_indexy_a_razeni'), ('seminar', '0021_cislo_verejna_vysledkovka'), ('seminar', '0022_decimal_body'), ('seminar', '0023_add_novinky'), ('seminar', '0024_add_organizator'), ('seminar', '0025_zmena_cesty_nahravani_obrazku'), ('seminar', '0026_soustredeni_typ'), ('seminar', '0027_export_flag_a_typ_akce'), ('seminar', '0028_add_body_celkem_views'), ('seminar', '0029_fix_body_celkem_views'), ('seminar', '0030_add_vysledky'), ('seminar', '0031_cislo_pdf'), ('seminar', '0032_cislo_pdf_blank_typos'), ('seminar', '0033_organizator_studuje_popisek'), ('seminar', '0034_reseni_forma_default_email'), ('seminar', '0035_django_imagekit'), ('seminar', '0036_add_org_to_soustredeni'), ('seminar', '0037_prispevek'), ('seminar', '0038_change_meta_prispevek'), ('seminar', '0039_pohadka'), ('seminar', '0040_pohadka_nepovinny_autor'), ('seminar', '0041_konfery'), ('seminar', '0042_cislo_faze'), ('seminar', '0043_uprava_faze'), ('seminar', '0044_uprava_faze'), ('seminar', '0045_cislo_pridani_faze_nahrano'), ('seminar', '0042_auto_20161005_0847'), ('seminar', '0046_merge'), ('seminar', '0047_auto_20170120_2118'), ('seminar', '0048_add_cislo_datum_deadline_soustredeni'), ('seminar', '0049_auto_20190430_2354'), ('seminar', '0050_auto_20190510_2228'), ('seminar', '0051_resitel_to_osoba'), ('seminar', '0052_user_to_organizator'), ('seminar', '0053_organizator_organizuje_od_do'), ('seminar', '0055_smazat_nemigrovane_zastarale_veci'), ('seminar', '0056_vrcholy_pro_rocniky_a_cisla'), ('seminar', '0057_reseni_to_reseni_hodnoceni'), ('seminar', '0058_problem_to_uloha_tema_clanek'), ('seminar', '0059_vytvorit_pohadkanode'), ('seminar', '0060_spoj_stromy'), ('seminar', '0061_kill_frankenstein'), ('seminar', '0062_redukce_modelu_pohadky'), ('seminar', '0063_procisteni_migraci'), ('seminar', '0064_auto_20190610_2358'), ('seminar', '0065_treenode_polymorphic_ctype'), ('seminar', '0066_problem_polymorphic_ctype'), ('seminar', '0067_auto_20190814_0805')] | ||||
|     replaces = [('seminar', '0001_initial'), ('seminar', '0002_add_body_views'), ('seminar', '0003_add_skola_zs_ss'), ('seminar', '0004_add_old_dakos_id'), ('seminar', '0005_alter_problem_autor'), ('seminar', '0006_problem_add_timestamp'), ('seminar', '0007_problem_zamereni'), ('seminar', '0008_reseni_forma'), ('seminar', '0009_rename_imported_IDs'), ('seminar', '0010_alter_rok_maturity'), ('seminar', '0011_alter_timestamp_def'), ('seminar', '0012_remove_soustredeni_ucastnici'), ('seminar', '0013_soustredeni_ucastnici_through_model'), ('seminar', '0014_uprava_poznamek'), ('seminar', '0015_soustredeni_text'), ('seminar', '0016_texty_problemu'), ('seminar', '0017_texty_problemu_minor'), ('seminar', '0018_problemnavrh_problemzadany'), ('seminar', '0019_rocnik_ciselne'), ('seminar', '0020_indexy_a_razeni'), ('seminar', '0021_cislo_verejna_vysledkovka'), ('seminar', '0022_decimal_body'), ('seminar', '0023_add_novinky'), ('seminar', '0024_add_organizator'), ('seminar', '0025_zmena_cesty_nahravani_obrazku'), ('seminar', '0026_soustredeni_typ'), ('seminar', '0027_export_flag_a_typ_akce'), ('seminar', '0028_add_body_celkem_views'), ('seminar', '0029_fix_body_celkem_views'), ('seminar', '0030_add_vysledky'), ('seminar', '0031_cislo_pdf'), ('seminar', '0032_cislo_pdf_blank_typos'), ('seminar', '0033_organizator_studuje_popisek'), ('seminar', '0034_reseni_forma_default_email'), ('seminar', '0035_django_imagekit'), ('seminar', '0036_add_org_to_soustredeni'), ('seminar', '0037_prispevek'), ('seminar', '0038_change_meta_prispevek'), ('seminar', '0039_pohadka'), ('seminar', '0040_pohadka_nepovinny_autor'), ('seminar', '0041_konfery'), ('seminar', '0042_cislo_faze'), ('seminar', '0043_uprava_faze'), ('seminar', '0044_uprava_faze'), ('seminar', '0045_cislo_pridani_faze_nahrano'), ('seminar', '0042_auto_20161005_0847'), ('seminar', '0046_merge'), ('seminar', '0047_auto_20170120_2118'), ('seminar', '0048_add_cislo_datum_deadline_soustredeni'), ('seminar', '0049_auto_20190430_2354'), ('seminar', '0050_auto_20190510_2228'), ('seminar', '0051_resitel_to_osoba'), ('seminar', '0052_user_to_organizator'), ('seminar', '0053_organizator_organizuje_od_do'), ('seminar', '0055_smazat_nemigrovane_zastarale_veci'), ('seminar', '0056_vrcholy_pro_rocniky_a_cisla'), ('seminar', '0057_reseni_to_reseni_hodnoceni'), ('seminar', '0058_problem_to_uloha_tema_clanek'), ('seminar', 'fix_0058'), ('seminar', '0059_vytvorit_pohadkanode'), ('seminar', '0060_spoj_stromy'), ('seminar', '0061_kill_frankenstein'), ('seminar', '0062_redukce_modelu_pohadky'), ('seminar', '0063_procisteni_migraci'), ('seminar', '0064_auto_20190610_2358'), ('seminar', '0065_treenode_polymorphic_ctype'), ('seminar', '0066_problem_polymorphic_ctype'), ('seminar', '0067_auto_20190814_0805')] | ||||
| 
 | ||||
|     initial = True | ||||
| 
 | ||||
|  | @ -877,6 +877,7 @@ class Migration(migrations.Migration): | |||
|         ), | ||||
|         migrations.RunSQL( | ||||
|             sql='update seminar_rocniky set rocnik_n = cast (rocnik as integer)', | ||||
|             reverse_sql='update seminar_rocniky set rocnik_n = cast (rocnik as nvarchar(16))', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='rocnik', | ||||
|  | @ -1733,15 +1734,19 @@ class Migration(migrations.Migration): | |||
|         # migr 0052 | ||||
|         migrations.RunPython( | ||||
|            spoj_k_organizatorum_osoby, | ||||
|         	reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
|         migrations.RunPython( | ||||
|             fix_problem, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
|         migrations.RunPython( | ||||
|             fix_pohadka, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
|         migrations.RunPython( | ||||
|             fix_novinka, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
| 
 | ||||
|         # migr 0053 | ||||
|  | @ -1795,35 +1800,49 @@ class Migration(migrations.Migration): | |||
|         # migr 0056 | ||||
|         migrations.RunPython( | ||||
|             generuj_RocnikNody_a_CisloNody, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
| 
 | ||||
|         # migr 0057 | ||||
|         migrations.RunPython( | ||||
|             reseni_to_Reseni, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
| 
 | ||||
|         # migr 0058 | ||||
|         migrations.RunPython( | ||||
|             uloha_to_Uloha, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
|         migrations.RunPython( | ||||
|             tema_to_Tema, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
|         migrations.RunPython( | ||||
|             clanek_to_Clanek, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
|         migrations.RunPython( | ||||
|             konfery_rucne, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
| 
 | ||||
|         # migr "fix 0058" | ||||
|         migrations.RunSQL( | ||||
|             "update seminar_problemy set typ = 'uloha' where typ like 'b_uloha_';", | ||||
|             "update seminar_problemy set typ = 'uloha' where typ like 'b_uloha_';" | ||||
|         ), | ||||
| 
 | ||||
|         # migr 0059 | ||||
|         migrations.RunPython( | ||||
|             vytvor_pohadkanode, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
| 
 | ||||
|         # migr 0060 | ||||
|         migrations.RunPython( | ||||
|             pokacej_les, | ||||
|             reverse_code=migrations.RunPython.noop, | ||||
|         ), | ||||
| 
 | ||||
|         migrations.RemoveField( | ||||
|  |  | |||
|  | @ -18,7 +18,8 @@ class Migration(migrations.Migration): | |||
|             preserve_default=False, | ||||
|         ), | ||||
|         migrations.RunSQL( | ||||
|             sql="update seminar_rocniky set rocnik_n = cast (rocnik as integer)" | ||||
|             sql="update seminar_rocniky set rocnik_n = cast (rocnik as integer)", | ||||
|             reverse_sql='update seminar_rocniky set rocnik_n = cast (rocnik as nvarchar(16))', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='rocnik', | ||||
|  |  | |||
|  | @ -75,8 +75,8 @@ class Migration(migrations.Migration): | |||
| 	] | ||||
| 
 | ||||
| 	operations = [ | ||||
| 		migrations.RunPython(spoj_k_organizatorum_osoby), | ||||
| 		migrations.RunPython(fix_problem), | ||||
| 		migrations.RunPython(fix_pohadka), | ||||
| 		migrations.RunPython(fix_novinka), | ||||
| 		migrations.RunPython(spoj_k_organizatorum_osoby, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(fix_problem, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(fix_pohadka, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(fix_novinka, migrations.RunPython.noop), | ||||
| 	] | ||||
|  |  | |||
|  | @ -43,5 +43,5 @@ class Migration(migrations.Migration): | |||
| 	] | ||||
| 
 | ||||
| 	operations = [ | ||||
| 		migrations.RunPython(generuj_RocnikNody_a_CisloNody), | ||||
| 		migrations.RunPython(generuj_RocnikNody_a_CisloNody, migrations.RunPython.noop), | ||||
| 	] | ||||
|  |  | |||
|  | @ -30,5 +30,5 @@ class Migration(migrations.Migration): | |||
| 	] | ||||
| 
 | ||||
| 	operations = [ | ||||
| 		migrations.RunPython(reseni_to_Reseni)		 | ||||
| 		migrations.RunPython(reseni_to_Reseni, migrations.RunPython.noop) | ||||
| 	] | ||||
|  |  | |||
|  | @ -154,8 +154,8 @@ class Migration(migrations.Migration): | |||
| 
 | ||||
| 	operations = [ | ||||
| 		# ashes to Ashes, dust to Dust.... | ||||
| 		migrations.RunPython(uloha_to_Uloha), | ||||
| 		migrations.RunPython(tema_to_Tema), | ||||
| 		migrations.RunPython(clanek_to_Clanek), | ||||
| 		migrations.RunPython(konfery_rucne), | ||||
| 		migrations.RunPython(uloha_to_Uloha, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(tema_to_Tema, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(clanek_to_Clanek, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(konfery_rucne, migrations.RunPython.noop), | ||||
| 	] | ||||
|  |  | |||
|  | @ -21,9 +21,9 @@ def vytvor_pohadkanode(apps, schema_editor): | |||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
| 	dependencies = [ | ||||
| 		('seminar', '0058_problem_to_uloha_tema_clanek'), | ||||
| 		('seminar', 'fix_0058'), | ||||
| 	] | ||||
| 
 | ||||
| 	operations = [ | ||||
| 		migrations.RunPython(vytvor_pohadkanode), | ||||
| 		migrations.RunPython(vytvor_pohadkanode, migrations.RunPython.noop), | ||||
| 	] | ||||
|  |  | |||
|  | @ -108,5 +108,5 @@ class Migration(migrations.Migration): | |||
| 	] | ||||
| 
 | ||||
| 	operations = [ | ||||
| 		migrations.RunPython(pokacej_les), | ||||
| 		migrations.RunPython(pokacej_les, migrations.RunPython.noop), | ||||
| 	] | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import django.db.models.deletion | |||
| 
 | ||||
| def vyrob_treenodum_ctypes(apps, schema_editor): | ||||
| 	# Kód zkopírovaný z dokumentace: https://django-polymorphic.readthedocs.io/en/stable/migrating.html | ||||
| 	# XXX: Nevím, jestli se tohle náhodou nemělo spustit na všech childech (jen/i) | ||||
| 	# NOTE: Tahle migrace je špatně, 0087 ji opravuje. Možno squashnout pryč. | ||||
| 	TreeNode = apps.get_model('seminar', 'TreeNode') | ||||
| 	ContentType = apps.get_model('contenttypes', 'ContentType') | ||||
| 	 | ||||
|  | @ -27,5 +27,5 @@ class Migration(migrations.Migration): | |||
| 			name='polymorphic_ctype', | ||||
| 			field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_seminar.treenode_set+', to='contenttypes.ContentType'), | ||||
| 		), | ||||
| 		migrations.RunPython(vyrob_treenodum_ctypes, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(vyrob_treenodum_ctypes, migrations.RunPython.noop, elidable=True), | ||||
| 	] | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import django.db.models.deletion | |||
| 
 | ||||
| def vyrob_problemum_ctypes(apps, schema_editor): | ||||
| 	# Kód zkopírovaný z dokumentace: https://django-polymorphic.readthedocs.io/en/stable/migrating.html | ||||
| 	# XXX: Nevím, jestli se tohle náhodou nemělo spustit na všech childech (jen/i) | ||||
| 	# NOTE: Tahle migrace je špatně, 0087 ji opravuje. Možno squashnout pryč. | ||||
| 	Problem = apps.get_model('seminar', 'Problem') | ||||
| 	ContentType = apps.get_model('contenttypes', 'ContentType') | ||||
| 	 | ||||
|  | @ -25,5 +25,5 @@ class Migration(migrations.Migration): | |||
| 			name='polymorphic_ctype', | ||||
| 			field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_seminar.problem_set+', to='contenttypes.ContentType'), | ||||
| 		), | ||||
| 		migrations.RunPython(vyrob_problemum_ctypes, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(vyrob_problemum_ctypes, migrations.RunPython.noop, elidable=True), | ||||
| 	] | ||||
|  |  | |||
|  | @ -103,5 +103,5 @@ class Migration(migrations.Migration): | |||
|             name='nazev', | ||||
|             field=models.TextField(help_text='Tento název se zobrazuje v nabídkách pro výběr vhodného TreeNode', null=True, verbose_name='název tohoto node'), | ||||
|         ), | ||||
|         migrations.RunPython(fix_all_names), | ||||
|         migrations.RunPython(fix_all_names, migrations.RunPython.noop), | ||||
|     ] | ||||
|  |  | |||
|  | @ -65,6 +65,9 @@ class Migration(migrations.Migration): | |||
|             model_name='reseni', | ||||
|             name='text_zkraceny', | ||||
|         ), | ||||
|         migrations.DeleteModel(  # nejdříve musím smazat objekt ukazující na konferu, | ||||
|             name='KonferaNode',  # pak až změnit klíč konferám (viz další operace) | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='konfera', | ||||
|             name='problem_ptr', | ||||
|  | @ -95,9 +98,6 @@ class Migration(migrations.Migration): | |||
|         migrations.DeleteModel( | ||||
|             name='ClanekNode', | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='KonferaNode', | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Konfery_Ucastnici', | ||||
|             fields=[ | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ from django.db import migrations, models | |||
| import django.db.models.deletion | ||||
| from seminar.treelib import get_parent | ||||
| 
 | ||||
| import logging | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| def najdi_cislo(apps, schema_editor): | ||||
| 	Clanek = apps.get_model('seminar', 'Clanek') | ||||
| 	Hodnoceni = apps.get_model('seminar', 'Hodnoceni') | ||||
|  | @ -15,7 +18,10 @@ def najdi_cislo(apps, schema_editor): | |||
| 	for c in Clanek.objects.all(): | ||||
| 		reseni = c.reseni_set | ||||
| 		if (reseni.count() != 1):	# Pozor, reseni_set je Manager, takže se na něj musí trošku jinak | ||||
| 			raise ValueError("Článek k sobě má nejedno řešení!") | ||||
| 			logger.warn(f"Více než jedno řešení pro článek {c}") | ||||
| 			c.cislo = None | ||||
| 			c.save() | ||||
| 			continue | ||||
| 		r = reseni.first() | ||||
| 		aktualniNode = r.text_cely # Hlavní ReseniNode pro řešení | ||||
| 		while aktualniNode is not None: | ||||
|  |  | |||
							
								
								
									
										17
									
								
								seminar/migrations/0086_auto_20200819_0959.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,17 @@ | |||
| # Generated by Django 2.2.15 on 2020-08-19 07:59 | ||||
| 
 | ||||
| from django.db import migrations | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('seminar', '0085_nepovinna_prezdivka'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterModelOptions( | ||||
|             name='organizator', | ||||
|             options={'ordering': ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'], 'verbose_name': 'Organizátor', 'verbose_name_plural': 'Organizátoři'}, | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										49
									
								
								seminar/migrations/0087_fix_polymorphism.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,49 @@ | |||
| # Generated by Django 2.2.16 on 2020-09-04 12:06 | ||||
| 
 | ||||
| from django.db import migrations | ||||
| from logging import getLogger | ||||
| 
 | ||||
| log = getLogger(__name__) | ||||
| 
 | ||||
| # Oprava migrací 0065 a 0066, kde jsem špatně pochopil django-polymorphic | ||||
| 
 | ||||
| # Pomocná funkce -- děláme to samé pro obě polymorfní hierarchie | ||||
| def fix_ctypes(parent: str, children, apps, schema_editor): | ||||
| 	Parent = apps.get_model('seminar', parent) | ||||
| 	ContentType = apps.get_model('contenttypes', 'ContentType') | ||||
| 
 | ||||
| 	# Nejdřív všechno smažeme: | ||||
| 	Parent.objects.update(polymorphic_ctype=None) | ||||
| 
 | ||||
| 	# Opravíme děti | ||||
| 	for clsname in children: | ||||
| 		Model = apps.get_model('seminar', clsname) | ||||
| 		ct = ContentType.objects.get_for_model(Model) | ||||
| 		Model.objects.update(polymorphic_ctype=ct) | ||||
| 	 | ||||
| 
 | ||||
| 	# Ostatní instance mají mít explicitně content type pro rodiče | ||||
| 	new_ct = ContentType.objects.get_for_model(Parent) | ||||
| 	for obj in Parent.objects.filter(polymorphic_ctype__isnull=True): | ||||
| 		log.warn(f"{parent} \"{obj}\" neměl content type -- nejspíš to je instance přímo {parent}!") | ||||
| 		obj.polymorphic_ctype=new_ct | ||||
| 		obj.save() | ||||
| 
 | ||||
| def fix_treenode(apps, schema_editor): | ||||
| 	children = ['RocnikNode', 'CisloNode', 'MezicisloNode', 'TemaVCisleNode', | ||||
| 			'OrgTextNode', 'UlohaZadaniNode', 'UlohaVzorakNode', 'PohadkaNode', | ||||
| 			'TextNode', 'CastNode', 'ReseniNode'] | ||||
| 	fix_ctypes("TreeNode", children, apps, schema_editor) | ||||
| 
 | ||||
| def fix_problem(apps, schema_editor): | ||||
| 	children = ['Tema', 'Clanek', 'Uloha'] # FIXME: Konfera z nějakého důvodu tenhle field vůbec nemá, asi je to špatně. | ||||
| 	fix_ctypes("Problem", children, apps, schema_editor) | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 	dependencies = [ | ||||
| 		('seminar', '0086_auto_20200819_0959'), | ||||
| 	] | ||||
| 	operations = [ | ||||
| 		migrations.RunPython(fix_treenode, migrations.RunPython.noop), | ||||
| 		migrations.RunPython(fix_problem, migrations.RunPython.noop), | ||||
| 	] | ||||
							
								
								
									
										35
									
								
								seminar/migrations/0088_perm_org_a_ucastnik.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,35 @@ | |||
| # Generated by Django 2.2.15 on 2020-09-05 10:10 | ||||
| from django.db import migrations | ||||
| 
 | ||||
| 
 | ||||
| def add_perms(apps, schema_editor): | ||||
|     ContentType = apps.get_model('contenttypes', 'ContentType') | ||||
|     User = apps.get_model('auth', 'User') | ||||
|     Permission = apps.get_model('auth', 'Permission') | ||||
|     Resitel = apps.get_model('seminar', 'Resitel') | ||||
| 
 | ||||
|     c = ContentType.objects.get_for_model(User) | ||||
|     org_perm = Permission.objects.filter(codename__exact='org').first() | ||||
|     if not org_perm: | ||||
|         org_perm = Permission.objects.create(codename='org', name='org', content_type=c) | ||||
|     resitel_perm = Permission.objects.filter(codename__exact='resitel').first() | ||||
|     if not resitel_perm: | ||||
|         resitel_perm = Permission.objects.create(codename='resitel', name='resitel', content_type=c) | ||||
|     for r in Resitel.objects.all(): | ||||
|         u = r.osoba.user | ||||
|         if u: | ||||
|             u.user_permissions.add(resitel_perm) | ||||
|     for org in User.objects.all(): | ||||
|         if org and org.is_staff: | ||||
|             org.user_permissions.add(org_perm) | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('seminar', '0087_fix_polymorphism'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.RunPython(add_perms, migrations.RunPython.noop), | ||||
|     ] | ||||
							
								
								
									
										14
									
								
								seminar/migrations/fix_0058.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,14 @@ | |||
| from django.db import migrations | ||||
| 
 | ||||
| sql = "update seminar_problemy set typ = 'uloha' where typ like 'b_uloha_';" | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
| 	dependencies = [ | ||||
| 		('seminar', '0058_problem_to_uloha_tema_clanek'), | ||||
| 	] | ||||
| 
 | ||||
| 	operations = [ | ||||
| 		migrations.RunSQL(sql, sql), | ||||
| 	] | ||||
| 
 | ||||
|  | @ -582,7 +582,7 @@ class Organizator(SeminarModelBase): | |||
| 		"školu, ale jen obor, možnost zobrazit zvlášť") | ||||
| 
 | ||||
| 	def clean(self): | ||||
| 		if self.organizuje_od > self.organizuje_do: | ||||
| 		if self.organizuje_od and self.organizuje_do and (self.organizuje_od > self.organizuje_do): | ||||
| 			raise ValidationError("Organizátor nemůže skončit s organizováním dříve než začal!") | ||||
| 		super().clean() | ||||
| 
 | ||||
|  | @ -597,6 +597,11 @@ class Organizator(SeminarModelBase): | |||
| 	class Meta: | ||||
| 		verbose_name = 'Organizátor' | ||||
| 		verbose_name_plural = 'Organizátoři' | ||||
| 		# Řadí aktivní orgy na začátek, pod tím v pořadí od nejstarších neaktivní orgy. | ||||
| 		# TODO: Chtěl bych spíš mít nejstarší orgy dole. | ||||
| 		# TODO: Zohledňovat přezdívky? | ||||
| 		# TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu | ||||
| 		ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] | ||||
| 
 | ||||
| @reversion.register(ignore_duplicates=True) | ||||
| class Soustredeni(SeminarModelBase): | ||||
|  |  | |||
|  | @ -18,9 +18,9 @@ | |||
|     <h2>Zadané problémy</h2> | ||||
|     <ul> | ||||
|     {% for p in v_cisle_zadane %} | ||||
|       <li{% if user.is_staff and not cislo.verejne %} class='mam-org-only'{% endif %}> | ||||
|         {% if user.is_staff or cislo.verejne %} | ||||
|           <a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff or cislo.verejne %}</a>{% endif %} | ||||
|       <li{% if user.je_org and not cislo.verejne %} class='mam-org-only'{% endif %}> | ||||
|         {% if user.je_org or cislo.verejne %} | ||||
|           <a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.je_org or cislo.verejne %}</a>{% endif %} | ||||
|     {% endfor %} | ||||
|     </ul> | ||||
|   {% endif %} | ||||
|  | @ -29,14 +29,14 @@ | |||
|     <h2>Řešené problémy</h2> | ||||
|     <ul> | ||||
|     {% for p in resene_problemy %} | ||||
|       <li{% if user.is_staff and not cislo.verejne %} class='mam-org-only'{% endif %}> | ||||
|         {% if user.is_staff or cislo.verejne %} | ||||
|           <a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff or cislo.verejne %}</a>{% endif %} | ||||
|       <li{% if user.je_org and not cislo.verejne %} class='mam-org-only'{% endif %}> | ||||
|         {% if user.je_org or cislo.verejne %} | ||||
|           <a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.je_org or cislo.verejne %}</a>{% endif %} | ||||
|     {% endfor %} | ||||
|     </ul> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if user.is_staff %} | ||||
|   {% if user.je_org %} | ||||
|       <div class="mam-org-only"> | ||||
|         <h2> Orgovské odkazy </h2> | ||||
|         <ul> | ||||
|  | @ -52,13 +52,13 @@ | |||
|   <h2>Výsledkovka</h2> | ||||
| 
 | ||||
|   {% else %} | ||||
|     {% if user.is_staff %} | ||||
|     {% if user.je_org %} | ||||
|       <div class='mam-org-only'> | ||||
|       <h2>Výsledkovka (neveřejná)</h2> | ||||
|     {% endif %} | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if cislo.verejna_vysledkovka or user.is_staff %} | ||||
|   {% if cislo.verejna_vysledkovka or user.je_org %} | ||||
|     <table class='vysledkovka'> | ||||
|       <tr class='border-b'> | ||||
|         <th class='border-r'># | ||||
|  | @ -66,7 +66,7 @@ | |||
|         {% for p in problemy %} | ||||
|         <th class='border-r'><a href="{{ p.verejne_url }}">{{ p.kod_v_rocniku }}</a> | ||||
|         {% endfor %} | ||||
|         <th class='border-r'>Za číslo</sup> | ||||
|         <th class='border-r'>Za číslo | ||||
|         <th class='border-r'>Za ročník | ||||
|         <th class='border-r'>Odjakživa | ||||
|     {% for rv in radky_vysledkovky %} | ||||
|  | @ -88,7 +88,7 @@ | |||
|     </table> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if not cislo.verejna_vysledkovka and user.is_staff %} | ||||
|   {% if not cislo.verejna_vysledkovka and user.je_org %} | ||||
|       </div> | ||||
|   {% endif %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,11 +3,11 @@ | |||
| {% load comments %} | ||||
| 
 | ||||
| {% block content %} | ||||
| <div {% if not problem.verejne and user.is_staff %}class="mam-org-only"{% endif %}> | ||||
| <div {% if not problem.verejne and user.je_org %}class="mam-org-only"{% endif %}> | ||||
|   {% block problem %} | ||||
|   {% endblock %} | ||||
| 
 | ||||
|   {% if user.is_staff %} | ||||
|   {% if user.je_org %} | ||||
|   <div class='mam-org-only'> | ||||
| 
 | ||||
|     <h2>Text - org</h2> | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ | |||
| </div> | ||||
| 
 | ||||
|   {% if vysledkovka %} | ||||
|     {% if user.is_staff %} | ||||
|     {% if user.je_org %} | ||||
|       <div class='mam-org-only'> | ||||
|         <a href='vysledkovka.tex'>Výsledkovka ročníku (LaTeX)</a> | ||||
|       </div> | ||||
|  | @ -72,7 +72,7 @@ | |||
|     {% include "seminar/vysledkovka_rocnik.html" %} | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if user.is_staff and vysledkovka_s_neverejnymi %} | ||||
|   {% if user.je_org and vysledkovka_s_neverejnymi %} | ||||
|     <div class='mam-org-only'> | ||||
|     <h2>Výsledková listina včetně neveřejných bodů</h2> | ||||
|       {% with radky_vyledkovky_s_neverejnymi as radky_vysledkovky %} | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| </h1> | ||||
| 
 | ||||
| {% for clanek in object_list %} | ||||
| {% with clanek.cislo_zadani.rocnik.rocnik as rocnik %} | ||||
| {% with clanek.cislo.rocnik.rocnik as rocnik %} | ||||
|   {% ifchanged rocnik %} | ||||
|     {% if not forloop.first %}</ul>{% endif %} | ||||
|     <h2>{{ rocnik }}. ročník</h2> | ||||
|  |  | |||
							
								
								
									
										10
									
								
								seminar/templates/seminar/formular_ok.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,10 @@ | |||
| {% extends "base.html" %} | ||||
| 
 | ||||
| {% block nadpis1a %}Formulář byl odeslán{% endblock %} | ||||
| 
 | ||||
| {% block content %} | ||||
| <h1> Formulář byl úspěšně odeslán </h1> | ||||
| {% for odkaz in odkazy %} | ||||
| <p><a href="{{odkaz.1}}">{{odkaz.0}}</a></p> | ||||
| {% endfor %} | ||||
| {% endblock %} | ||||
|  | @ -1,11 +1,13 @@ | |||
| {% for novinka in object_list %} | ||||
|   {% if not novinka.zverejneno and user.is_staff %} | ||||
| {# pripravene div-y na stylovani#} | ||||
| <div> | ||||
|   {% if not novinka.zverejneno and user.je_org %} | ||||
|   <div class="mam-org-only"> | ||||
|     <ul> | ||||
|       <li><a href="/admin/seminar/novinky/{{novinka.pk}}">Upravit novinku</a> | ||||
|     </ul> | ||||
|   {% endif %} | ||||
|   {% if novinka.zverejneno or user.is_staff %} | ||||
|   {% if novinka.zverejneno or user.je_org %} | ||||
|   {# datum #} | ||||
|   <div class=novinka_datum>{{novinka.datum}}</div> | ||||
|   {# text #} | ||||
|  | @ -31,7 +33,7 @@ | |||
|     {{novinka.autor.osoba.prijmeni}} | ||||
|   </div> | ||||
|   {% endif %} | ||||
|   {% if not novinka.zverejneno and user.is_staff %} | ||||
|   {% if not novinka.zverejneno and user.je_org %} | ||||
|   </div> | ||||
|   {% endif %} | ||||
| {% endfor%} | ||||
|  |  | |||
							
								
								
									
										87
									
								
								seminar/templates/seminar/orgorozcestnik.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,87 @@ | |||
| {% extends "base.html" %} | ||||
| {# FIXME: Použít ideálně reverse() ke zjišťování URL #} | ||||
| 
 | ||||
| {% block content %} | ||||
| <h2><strong>Informace, komunikace</strong></h2> | ||||
| 
 | ||||
| <ul> | ||||
| 	<li><strong><a href="https://wiki.mam.bezva.org/">wiki</a> </strong>obsahuje různé návody a know-how</li> | ||||
| 	<li><strong><a href="https://riot.im/app/#/room/#orgovna:dolujeme.eu">Riot</a> </strong>chatování s dalšími orgy</li> | ||||
| 	<li><strong>Kanboard </strong>správa TODO | ||||
| 	<ul> | ||||
| 		<li><a href="https://kanboard.ledoian.cz/?controller=BoardViewController&action=show&project_id=10">webařský</a></li> | ||||
| 		<li>soustředění</li> | ||||
| 	</ul> | ||||
| 	</li> | ||||
| 	<li><a href="/admin/seminar/novinky/add/"><strong>přidat novinku</strong></a> na web</li> | ||||
| </ul> | ||||
| 
 | ||||
| <hr /> | ||||
| <h2><strong>Tvorba čísla</strong></h2> | ||||
| 
 | ||||
| <ul> | ||||
| 	<li><a href="/admin/seminar/problemnavrh/add/"><strong>přidat téma</strong></a></li> | ||||
| 	<li><strong>korektury</strong> | ||||
| 	<ul> | ||||
| 		<li><a href="/korektury/">korekturování</a></li> | ||||
| 		<li><a href="/admin/korektury/korekturovanepdf/add/">přidat pdf k opravám</a></li> | ||||
| 	</ul> | ||||
| 	</li> | ||||
| 	<li><a href='{{ posledni_cislo_url }}'><strong>poslední vydané číslo </strong></a></li> | ||||
| </ul> | ||||
| <hr /> | ||||
| 
 | ||||
| <h2><strong>Moje problémy</strong></h2> | ||||
| 
 | ||||
| <h3> Témata </h3> | ||||
| <ul> | ||||
| {% for t in temata %} | ||||
| <li> {{ t }} </li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
| 
 | ||||
| <h3> Úlohy </h3> | ||||
| <ul> | ||||
| {% for u in ulohy %} | ||||
| <li> {{ u }} </li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
| 
 | ||||
| <h3> Články </h3> | ||||
| <ul> | ||||
| {% for c in clanky %} | ||||
| <li> {{ c }} </li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
| 
 | ||||
| <hr /> | ||||
| <h2><strong>Soustředění</strong></h2> | ||||
| 
 | ||||
| <ul> | ||||
| 	<li><strong>přednášky</strong> | ||||
| 
 | ||||
| 	<ul> | ||||
| 		<li><a href="/admin/prednasky/prednaska/">vypisování přednášek</a></li> | ||||
| 		<li>hlasování o přednáškách</li> | ||||
| 	</ul> | ||||
| 	</li> | ||||
| 	<li><a href="/soustredeni/probehlo/">proběhlá soustředění</a> | ||||
| 	<ul> | ||||
| 		<li>vytvoření galerie</li> | ||||
| 		<li>stažení seznamu účastníků</li> | ||||
| 		<li>obálky</li> | ||||
| 	</ul> | ||||
| 	</li> | ||||
| </ul> | ||||
| 
 | ||||
| <hr /> | ||||
| <h2><strong>Můj profil</strong></h2> | ||||
| 
 | ||||
| <ul> | ||||
| 	<li><a href="http://127.0.0.1:8000/admin/seminar/organizator/{{ organizator.id }}/change/"><strong>upravit </strong></a></li> | ||||
| </ul> | ||||
| 
 | ||||
| <hr /> | ||||
| <p>Nemůžeš najít, co hledáš? Může to být v <a href="/admin/">administračním rozhraní webu</a>.</p> | ||||
| {% endblock content %} | ||||
| 
 | ||||
|  | @ -36,13 +36,14 @@ Tento souhlas uděluji ze své vlastní a svobodné vůle a beru na vědomí, ž | |||
| </p> | ||||
| <p class="gdpr"> | ||||
| Dále máte právo: | ||||
| </p> | ||||
| <ul> | ||||
| <li>požádat o informaci, jaké osobní údaje jsou o vás zpracovávány, | ||||
| <li>požadovat opravu osobních údajů, pokud jsou neplatné nebo zastaralé, | ||||
| <li>požadovat, aby nebyly vaše osobní údaje zpracovávány do doby, než bude vyřešena oprávněnost výše uvedených požadavků, | ||||
| <li>požadovat, aby byly vaše osobní údaje předány jinému správci, | ||||
| <li>podat stížnost u dozorového úřadu. | ||||
| </p> | ||||
| </ul> | ||||
| <p class="gdpr"> | ||||
| V případě jakéhokoliv dotazu nebo uplatnění svých práv můžete kontaktovat pověřence pro ochranu osobních údajů na e-mailové adrese gdpr@cuni.cz. | ||||
| </p> | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ | |||
|               </td> | ||||
|               <td {% if field.help_text %} class="field-with-comment"{% endif %}> | ||||
|                 {{ field }} | ||||
|                 <span class="field-comment">{{ field.help_text|safe }} | ||||
|                   <span class="field-comment">{{ field.help_text|safe }}</span>> | ||||
|               </td> | ||||
| 
 | ||||
|             <td><span class="field-error">{{ field.errors }}</span></td> | ||||
|  | @ -74,7 +74,7 @@ | |||
| <div id="empty_form" style="display:none"> | ||||
| 	<div class="attachment"> | ||||
| 
 | ||||
|         <table class='form' id="reseni" class='no_error'> | ||||
|         <table class='form no_error' id="reseni"> | ||||
|           <tr> | ||||
|           {% for field in prilohy.empty_form.visible_fields %} | ||||
| 
 | ||||
|  | @ -86,7 +86,7 @@ | |||
|               </td> | ||||
|               <td {% if field.help_text %} class="field-with-comment"{% endif %}> | ||||
|                 {{ field }} | ||||
|                 <span class="field-comment">{{ field.help_text|safe }} | ||||
|                 <span class="field-comment">{{ field.help_text|safe }}</span> | ||||
|               </td> | ||||
| 
 | ||||
|             <td><span class="field-error">{{ field.errors }}</span></td> | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
|   </td> | ||||
|   <td {% if field.help_text %} class="field-with-comment"{% endif %}> | ||||
|     {{ field }} | ||||
|     <span class="field-comment">{{ field.help_text|safe }} | ||||
|     <span class="field-comment">{{ field.help_text|safe }}</span> | ||||
|   </td> | ||||
| </tr> | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ | |||
|   {# Projdi vsechna soustredeni #} | ||||
|   {% for soustredeni in object_list %} | ||||
|     {# Kdyz je verejne -> zobraz #} | ||||
|     {% if soustredeni.verejne_db or user.is_staff %} | ||||
|       {% if not soustredeni.verejne_db and user.is_staff %} | ||||
|     {% if soustredeni.verejne_db or user.je_org %} | ||||
|       {% if not soustredeni.verejne_db and user.je_org %} | ||||
|         <div class="mam-org-only"> | ||||
|         <!--Groups of user: {{user.groups.all}} <br>--> | ||||
|       {% endif %} | ||||
|  | @ -29,8 +29,8 @@ | |||
|         {# Zobrazeni odkazu na galerie #} | ||||
|         {% if soustredeni.galerie_set.all %} | ||||
|           {% for galerie in soustredeni.galerie_set.all %} | ||||
|             {% if galerie.zobrazit == 0 or user.is_staff %} | ||||
|               <li {% if galerie.zobrazit > 0 and user.is_staff %}class="mam-org-only"{% endif %}> | ||||
|             {% if galerie.zobrazit == 0 or user.je_org %} | ||||
|               <li {% if galerie.zobrazit > 0 and user.je_org %}class="mam-org-only"{% endif %}> | ||||
|                 <a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">Fotogalerie</a> | ||||
|                 {# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #} | ||||
|               </li> | ||||
|  | @ -38,7 +38,7 @@ | |||
|           {% endfor %} | ||||
|         {% endif %} | ||||
|       </ul> | ||||
|       {% if user.is_staff %} | ||||
|       {% if user.je_org %} | ||||
|         <div class="mam-org-only"> | ||||
|           <a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a><br> | ||||
|           <a href="../{{soustredeni.pk}}/obalky.pdf">Vygenerovat obálky pro účastníky</a><br> | ||||
|  | @ -55,7 +55,7 @@ | |||
|       {% if soustredeni.text %} | ||||
|         {% autoescape off %}{{soustredeni.text}}{% endautoescape %} | ||||
|       {% endif %} | ||||
|       {% if user.is_staff %} | ||||
|       {% if user.je_org %} | ||||
|       <div class="mam-org-only"> | ||||
|         {# Účastníci #} | ||||
|         <h2>Soustředění se zúčastnili tito účastníci:</h2> | ||||
|  | @ -77,7 +77,7 @@ | |||
|       </div> | ||||
|       {% endif %} | ||||
| 
 | ||||
|       {% if not soustredeni.verejne_db and user.is_staff %} | ||||
|       {% if not soustredeni.verejne_db and user.je_org %} | ||||
|         </div> {# class="mam-org-only" #} | ||||
|       {% endif %} | ||||
|     {% endif %} | ||||
|  |  | |||
|  | @ -35,7 +35,6 @@ | |||
|       Žádní účastníci nebyli... | ||||
|   {% endfor %} | ||||
|   </table> | ||||
|   </ul> | ||||
| </body> | ||||
| </html> | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| 
 | ||||
|   {% if dead %} | ||||
|   <div class="odpocet"> | ||||
|     <p><b>Do konce <a href="https://mam.mff.cuni.cz/zadani/aktualni/">odeslání řešení</a> {% if deadline_soustredeni %}(pro účast na soustředění) {% endif %}zbývá:<br> | ||||
|     <p><b>Do konce <a href="/zadani/aktualni/">odeslání řešení</a> {% if deadline_soustredeni %}(pro účast na soustředění) {% endif %}zbývá:<br> | ||||
|       <big>{{ted|timesince:dead}}</big></b></p> | ||||
|   </div> | ||||
|   {% endif %} | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| {% extends "seminar/archiv/base_ulohy.html" %} | ||||
| {% extends "seminar/archiv/base.html" %} | ||||
| 
 | ||||
| {% load comments %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ | |||
|     v <a href="/archiv/cisla/">archivu</a>. | ||||
|   </p> | ||||
| 
 | ||||
|   {% if user.is_staff and vysledkovka_s_neverejnymi %} | ||||
|   {% if user.je_org and vysledkovka_s_neverejnymi %} | ||||
|     <div class='mam-org-only'> | ||||
|     <h1>Výsledky včetně neveřejných</h1> | ||||
|     {% with vysledkovka_s_neverejnymi as vysledkovka %} | ||||
|  |  | |||
|  | @ -16,8 +16,8 @@ | |||
| {% with nastaveni.aktualni_cislo as ac %} | ||||
|   | ||||
| {# Zobrazovani neverejnych zadani jen organizatorum #} | ||||
| {% if user.is_staff or verejne %} | ||||
| {% if user.is_staff and not verejne %}<div class="mam-org-only">{% endif %} | ||||
| {% if user.je_org or verejne %} | ||||
| {% if user.je_org and not verejne %}<div class="mam-org-only">{% endif %} | ||||
| 
 | ||||
|   {% if ac.zadane_problemy.all %} | ||||
|     {% if ac.datum_deadline_soustredeni %} | ||||
|  | @ -35,34 +35,38 @@ | |||
| 
 | ||||
| 
 | ||||
|     {% if ac.pdf %} | ||||
|       <p><a href="{{ac.pdf.url}}">Aktuální číslo v PDF</a></p> | ||||
|       <h3>Aktuální témata najdete v <a href="{{ac.pdf.url}}">aktuálním čísle v PDF</a>.</h3> | ||||
|     {% endif %} | ||||
|     {% for sada in jednorazove_problemy %} | ||||
|       {# podnadpisy, kdyz neni zakomentuje se nadpis #} | ||||
|       {% if not sada %}<!--{% endif %} | ||||
|       <h2>{% cycle 'Úlohy' 'Seriál' %}</h2> | ||||
|       {% if not sada %}-->{% endif %} | ||||
|       {# publikace jednotlivych zadani #} | ||||
|       {% for problem in sada %} | ||||
|         {% for tag in problem.zamereni.names %} | ||||
|            <a name="zam_{{tag}}"></a> | ||||
|         {% endfor %} | ||||
| 		<!--Toto jsem zakomentoval, aby se tam nezobrazovala temata, ale text, že vše najdou pouze v PDF--> | ||||
| 		{% if False %}	 | ||||
| 			{% for sada in jednorazove_problemy %} | ||||
| 				{# podnadpisy, kdyz neni zakomentuje se nadpis #} | ||||
| 				{% if not sada %}<!--{% endif %} | ||||
| 				<h2>{% cycle 'Úlohy' 'Seriál' %}</h2> | ||||
| 				{% if not sada %}-->{% endif %} | ||||
| 				{# publikace jednotlivych zadani #} | ||||
| 				{% for problem in sada %} | ||||
| 					{% for tag in problem.zamereni.names %} | ||||
| 						 <a name="zam_{{tag}}"></a> | ||||
| 					{% endfor %} | ||||
| 
 | ||||
|         {# TODO použít {{problem.kod_v_rocniku}} ? vrací 4.u1 místo 4.1 #} | ||||
|         <h3>{{problem.cislo_zadani.cislo}}.{{problem.kod}} {{problem.nazev}} {{ problem.body_v_zavorce }}</h3> | ||||
|         {% autoescape off %}{{problem.text_zadani}}{% endautoescape %} | ||||
|         <hr> | ||||
|       {% endfor %} | ||||
|     {% empty %} | ||||
|       Aktuálně nejsou zadané žádné úlohy k řešení. | ||||
|     {% endfor %} | ||||
| 					{# TODO použít {{problem.kod_v_rocniku}} ? vrací 4.u1 místo 4.1 #} | ||||
| 					<h3>{{problem.cislo_zadani.cislo}}.{{problem.kod}} {{problem.nazev}} {{ problem.body_v_zavorce }}</h3> | ||||
| 					{% autoescape off %}{{problem.text_zadani}}{% endautoescape %} | ||||
| 					<hr> | ||||
| 				{% endfor %} | ||||
| 			{% empty %} | ||||
| 				Aktuálně nejsou zadané žádné úlohy k řešení. | ||||
| 			{% endfor %} | ||||
| 		{% endif %} | ||||
| 
 | ||||
| {% if user.is_staff and not verejne%}</div>{% endif %} | ||||
| {% if user.je_org and not verejne%}</div>{% endif %} | ||||
| {% else %} | ||||
|   <h2>Aktuálně nejsou zveřejněny žádné úlohy</h2> | ||||
| {% endif %} | ||||
| 
 | ||||
| 
 | ||||
| 	{% if False %}	 | ||||
|     <h2>Témata</h2> | ||||
|       <ul> | ||||
|       {% for problem in temata %} | ||||
|  | @ -71,9 +75,14 @@ | |||
|         <a href="{{problem.verejne_url}}">Téma {{problem.kod}}: {{problem.nazev}}</a> | ||||
| 	</li> | ||||
|       {% empty %} | ||||
|         Aktuálně nejsou zadána žádná témata k řešení. | ||||
| 				{% if ac.pdf %} | ||||
| 					<p>Aktuální témata najdete v <a href="{{ac.pdf.url}}">aktuálním čísle v PDF</a>.</p> | ||||
| 				{% else %} | ||||
| 					<p>Aktuálně nemáme žádná témata.</p> | ||||
| 				{% endif %} | ||||
|       {% endfor %} | ||||
|       </ul> | ||||
| 	{% endif %} | ||||
| 
 | ||||
| {% endwith %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,15 +16,20 @@ | |||
|     {% endblock %}{% endblock %} | ||||
|   </h1> | ||||
| 
 | ||||
| 
 | ||||
|   <h3> | ||||
|   	<b> Pozor, tato stránka není aktuální!</b> Aktualizovaný seznam všech čísel v PDF najdete <a href="/rocnik/26/">zde</a>. Za problémy se omlouváme. | ||||
|   </h3> | ||||
|   <p> | ||||
|     Témata jsou hlavním obsahem časopisu M&M. Obvykle představují | ||||
|     složitější a obecnější problémy než samostatné úlohy. Navíc je v jejich | ||||
|     zadání vždy prostor pro tvůrčí rozšíření. Za pěkný článek k tématu lze | ||||
|     získat třeba i 20 bodů, určitě se tedy vyplatí se tématy zabývat. | ||||
|     Témata jsou texty nejen z oblasti matematiky, fyziky a informatiky, které | ||||
|     popisují nějaký problém a jsou doprovázeny návodnými úlohami. Vaším úkolem | ||||
|     je zamyslet se nad daným problémem a sepsat vaše úvahy ve formě krátkého | ||||
|     textu. | ||||
|   </p> | ||||
|   <p> | ||||
|     <a href="/co-je-MaM/jak-resit/">Jak řešit téma?</a> | ||||
|   </p> | ||||
| 	<!-- | ||||
|   {% if temata %} | ||||
|   <p> | ||||
|     Letos jsme pro tebe připravili tato témata: | ||||
|  | @ -72,6 +77,7 @@ | |||
|   {% empty %} | ||||
|     Aktuálně nejsou zadána žádná témata k řešení. | ||||
|   {% endfor %} | ||||
| 	--> | ||||
| 
 | ||||
| </div> | ||||
| {% endwith %} | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| import datetime | ||||
| 
 | ||||
| from django.contrib.auth.models import Permission | ||||
| from pytz import timezone | ||||
| import random | ||||
| import lorem | ||||
|  | @ -9,6 +11,7 @@ from django.db import transaction | |||
| import unidecode | ||||
| import logging | ||||
| 
 | ||||
| from korektury.testutils import create_test_pdf | ||||
| from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode | ||||
| import seminar.models as m | ||||
| 
 | ||||
|  | @ -70,7 +73,7 @@ def gen_osoby(rnd, size): | |||
| 		if pokusy >= max_pokusy: | ||||
| 			print("Chyba, na danou velikost testovacích dat příliš málo možných" | ||||
| 				" jmen a příjmení") | ||||
| 			exit | ||||
| 			exit() | ||||
| 		prezdivka = rnd.choice(prezdivky) | ||||
| 		email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)]) | ||||
| 		telefon = "".join([str(rnd.choice([k for k in range(10)])) for i in range(9)]) | ||||
|  | @ -124,9 +127,20 @@ def gen_resitele(rnd, osoby, skoly): | |||
| 	logger.info('Generuji řešitele...') | ||||
| 
 | ||||
| 	resitele = [] | ||||
| 	x = 0 | ||||
| 	resitel_perm = Permission.objects.filter(codename__exact='resitel').first() | ||||
| 	for os in osoby: | ||||
| 		rand = rnd.randint(0, 8) | ||||
| 		if not (rand % 8 == 0): | ||||
| 			if not os.user: | ||||
| 				if x: | ||||
| 					user = User.objects.create_user(username='r'+str(x), email=os.email, password='r') | ||||
| 				else: | ||||
| 					user = User.objects.create_user(username='r', email=os.email, password='r') | ||||
| 				x += 1 | ||||
| 				os.user = user | ||||
| 				os.save() | ||||
| 			os.user.user_permissions.add(resitel_perm) | ||||
| 			resitele.append(Resitel.objects.create(osoba=os, skola=rnd.choice(skoly), | ||||
| 				rok_maturity=rnd.randint(2019, 2029), | ||||
| 				zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0])) | ||||
|  | @ -139,7 +153,7 @@ def gen_prijemci(rnd, osoby, kolik=10): | |||
| 		prijemci.append(Prijemce.objects.create(osoba=i)) | ||||
| 	return prijemci | ||||
| 
 | ||||
| def gen_organizatori(rnd, osoby, last_rocnik, users): | ||||
| def gen_organizatori(rnd, osoby, last_rocnik): | ||||
| 	logger.info('Generuji organizátory...') | ||||
| 	organizatori = [] | ||||
| 
 | ||||
|  | @ -149,6 +163,8 @@ def gen_organizatori(rnd, osoby, last_rocnik, users): | |||
| 	seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu", | ||||
| 			"informatiku", "informatiku", "běhání dokolečka"] | ||||
| 
 | ||||
| 	x = 0 | ||||
| 	org_perm = Permission.objects.filter(codename__exact='org').first() | ||||
| 	for os in osoby: | ||||
| 		rand = rnd.randint(0, 8) | ||||
| 		if (rand % 8 == 0): | ||||
|  | @ -175,6 +191,15 @@ def gen_organizatori(rnd, osoby, last_rocnik, users): | |||
| 
 | ||||
| 			if do.year > datetime.datetime.now().year: | ||||
| 				do = None | ||||
| 			if not os.user: | ||||
| 				if x: | ||||
| 					user = User.objects.create_user(username='o'+str(x), email=os.email, password='o') | ||||
| 				else: | ||||
| 					user = User.objects.create_user(username='o', email=os.email, password='o') | ||||
| 				x += 1 | ||||
| 				os.user = user | ||||
| 				os.save() | ||||
| 			os.user.user_permissions.add(org_perm) | ||||
| 			organizatori.append(Organizator.objects.create(osoba=os, | ||||
| 				organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga)) | ||||
| 	return organizatori | ||||
|  | @ -681,14 +706,14 @@ def otec_syn(otec, syn): | |||
| 	syn.save() | ||||
| 	otec.save() | ||||
| 
 | ||||
| def gen_clanek(rnd): | ||||
| def gen_clanek(rnd, organizatori, resitele): | ||||
| 	logger.info("Generuji článek do čísla 22.2") | ||||
| 	clanek = m.Clanek.objects.create( | ||||
| 		nazev="Článek o Lorem ipsum", | ||||
| 		nadproblem=None, | ||||
| 		stav='vyreseny', | ||||
| 		zamereni=['I'], | ||||
| 		garant=rnd.choice(m.Organizator.objects.all()), | ||||
| 		garant=rnd.choice(organizatori), | ||||
| 		kod='cl', | ||||
| 		) | ||||
| 	clanek.save() | ||||
|  | @ -696,7 +721,7 @@ def gen_clanek(rnd): | |||
| 	reseni = m.Reseni.objects.create( | ||||
| 		zverejneno=True, | ||||
| 		) | ||||
| 	reseni.resitele.add(rnd.choice(m.Resitel.objects.all())) | ||||
| 	reseni.resitele.add(rnd.choice(resitele)) | ||||
| 	reseni.save() | ||||
| 
 | ||||
| 	cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2) | ||||
|  | @ -771,11 +796,22 @@ def create_test_data(size = 6, rnd = None): | |||
| 
 | ||||
| 	# users | ||||
| 	admin = User.objects.create_superuser(username='admin', email='', password='admin') | ||||
| 	os_admin = Osoba.objects.create( | ||||
| 		user=admin, jmeno='admin', prijmeni='admin', | ||||
| 		prezdivka='admin', pohlavi_muz=1, email='admin@admin.admin', | ||||
| 		telefon='123 456 789', datum_narozeni=datetime.date(2000, 1, 1), | ||||
| 		ulice='admin', mesto='admin', psc='100 00', | ||||
| 		datum_registrace=datetime.date(2020, 9, 6) | ||||
| 	) | ||||
| 	or_admin = Organizator.objects.create( | ||||
| 		osoba=os_admin, organizuje_od=None, organizuje_do=None, | ||||
| 		strucny_popis_organizatora="Organizátor k uživateli Admin" | ||||
| 	) | ||||
| 
 | ||||
| 	usernames = ['anet', 'bara', 'cyril', 'david', 'eva', 'filip'] | ||||
| 	users = [] | ||||
| 	for usr in usernames[:size]: | ||||
| 		u = User.objects.create(username=usr, password=usr) | ||||
| 		u = User.objects.create_user(username=usr, password=usr) | ||||
| 		u.first_name = usr.capitalize() | ||||
| 		u.save() | ||||
| 		users.append(u) | ||||
|  | @ -789,8 +825,8 @@ def create_test_data(size = 6, rnd = None): | |||
| 
 | ||||
| 	# resitele a organizatori | ||||
| 	last_rocnik = 25 | ||||
| 	organizatori = gen_organizatori(rnd, osoby, last_rocnik) | ||||
| 	resitele = gen_resitele(rnd, osoby, skoly) | ||||
| 	organizatori = gen_organizatori(rnd, osoby, last_rocnik, users) | ||||
| 
 | ||||
| 	#generování novinek | ||||
| 	novinky = gen_novinky(rnd, organizatori) | ||||
|  | @ -830,6 +866,9 @@ def create_test_data(size = 6, rnd = None): | |||
| 	#generování konfer | ||||
| 	konfery = gen_konfery(size, rnd, organizatori, resitele, soustredeni) | ||||
| 
 | ||||
| 	# vytvoreni pdf ke korekturam | ||||
| 	create_test_pdf(rnd, organizatori) | ||||
| 
 | ||||
| 			# TODO: nastavi správně, kolik se čeho generuje, aby rozsahy přibližně odpovídaly | ||||
| 			# FIXME: misto typu ruzne typy objektu a vnoreni do sebe (Tom nechápe, co je tímto fixme míněno) | ||||
| 			# TODO: vytvorit temata s ruznymi vlakny | ||||
|  | @ -840,7 +879,7 @@ def create_test_data(size = 6, rnd = None): | |||
| 			# TODO: přidat ke konferám řešení a dát je do čísel | ||||
| 
 | ||||
| 	# Dohackované vytvoření jednoho článku | ||||
| 	gen_clanek(rnd) | ||||
| 	gen_clanek(rnd, organizatori, resitele) | ||||
| 
 | ||||
| 
 | ||||
| 	# obecné nastavení semináře, musí být už přidané ročníky a čísla, jinak se nastaví divně | ||||
|  |  | |||
							
								
								
									
										112
									
								
								seminar/urls.py
									
									
									
									
									
								
							
							
						
						|  | @ -1,11 +1,8 @@ | |||
| from django.urls import path, include | ||||
| from django.contrib.auth.decorators import user_passes_test | ||||
| from django.contrib.auth.decorators import login_required | ||||
| from . import views, export | ||||
| from .utils import staff_member_required | ||||
| from .utils import org_required, resitel_required | ||||
| from django.views.generic.base import RedirectView | ||||
| from django.contrib.auth import views as auth_views | ||||
| 
 | ||||
| staff_member_required = user_passes_test(lambda u: u.is_staff) | ||||
| 
 | ||||
| urlpatterns = [ | ||||
| #	path('aktualni/temata/', views.TemataRozcestnikView), | ||||
|  | @ -33,17 +30,17 @@ urlpatterns = [ | |||
| 	), | ||||
| 	path( | ||||
| 		'soustredeni/<int:soustredeni>/seznam_ucastniku', | ||||
| 		staff_member_required(views.SoustredeniUcastniciView.as_view()), | ||||
| 		org_required(views.SoustredeniUcastniciView.as_view()), | ||||
| 		name='soustredeni_ucastnici' | ||||
| 	), | ||||
| 	path( | ||||
| 		'soustredeni/<int:soustredeni>/maily_ucastniku', | ||||
| 		staff_member_required(views.SoustredeniMailyUcastnikuView.as_view()), | ||||
| 		org_required(views.SoustredeniMailyUcastnikuView.as_view()), | ||||
| 		name='maily_ucastniku' | ||||
| 	), | ||||
| 	path( | ||||
| 		'soustredeni/<int:soustredeni>/export_ucastniku', | ||||
| 		staff_member_required(views.soustredeniUcastniciExportView), | ||||
| 		org_required(views.soustredeniUcastniciExportView), | ||||
| 		name='soustredeni_ucastnici_export' | ||||
| 	), | ||||
| 	path( | ||||
|  | @ -62,58 +59,101 @@ urlpatterns = [ | |||
| 	#path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'), | ||||
| 
 | ||||
| 	# Aesop | ||||
| 	path('aesop-export/mam-rocnik-<int:prvni_rok>.csv', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'), | ||||
| 	path('aesop-export/mam-sous-<str:datum_zacatku>.csv', export.ExportSousView.as_view(), name='seminar_export_sous'), | ||||
| 	path('aesop-export/index.csv', export.ExportIndexView.as_view(), name='seminar_export_index'), | ||||
| 	path( | ||||
| 		'aesop-export/mam-rocnik-<int:prvni_rok>.csv', | ||||
| 		org_required(export.ExportRocnikView.as_view()), | ||||
| 		name='seminar_export_rocnik' | ||||
| 	), | ||||
| 	path( | ||||
| 		'aesop-export/mam-sous-<str:datum_zacatku>.csv', | ||||
| 		org_required(export.ExportSousView.as_view()), | ||||
| 		name='seminar_export_sous' | ||||
| 	), | ||||
| 	path( | ||||
| 		'aesop-export/index.csv', | ||||
| 		org_required(export.ExportIndexView.as_view()), | ||||
| 		name='seminar_export_index' | ||||
| 	), | ||||
| 
 | ||||
| 	# Stranky viditelne pouze pro orgy: | ||||
| 	path( | ||||
| 	    'rocnik/<int:rocnik>/vysledkovka.tex', | ||||
| 	    staff_member_required(views.RocnikVysledkovkaView.as_view()), | ||||
| 	    name='seminar_rocnik_vysledkovka' | ||||
| 		'rocnik/<int:rocnik>/vysledkovka.tex', | ||||
| 		org_required(views.RocnikVysledkovkaView.as_view()), | ||||
| 		name='seminar_rocnik_vysledkovka' | ||||
| 	), | ||||
| 	path('cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex', | ||||
| 	    staff_member_required(views.CisloVysledkovkaView.as_view()),  | ||||
| 	    name='seminar_cislo_vysledkovka' | ||||
| 	path( | ||||
| 		'cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex', | ||||
| 		org_required(views.CisloVysledkovkaView.as_view()), | ||||
| 		name='seminar_cislo_vysledkovka' | ||||
| 	), | ||||
| 	path( | ||||
| 		'cislo/<int:rocnik>.<int:cislo>/obalky.pdf', | ||||
| 		org_required(views.cisloObalkyView), | ||||
| 		name='seminar_cislo_obalky' | ||||
| 	), | ||||
| 	path( | ||||
| 		'cislo/<int:rocnik>.<int:cislo>/tituly.tex', | ||||
| 		org_required(views.TitulyView), | ||||
| 		name='seminar_cislo_titul' | ||||
| 	), | ||||
| 	path( | ||||
| 		'stav', | ||||
| 		org_required(views.StavDatabazeView), | ||||
| 		name='stav_databaze' | ||||
| 	), | ||||
| 	path( | ||||
| 		'cislo/<int:rocnik>.<int:cislo>/obalkovani', | ||||
| 		org_required(views.ObalkovaniView.as_view()), | ||||
| 		name='seminar_cislo_resitel_obalkovani' | ||||
| 	), | ||||
| 	path( | ||||
| 		'soustredeni/<int:soustredeni>/obalky.pdf', | ||||
| 		org_required(views.soustredeniObalkyView), | ||||
| 		name='seminar_soustredeni_obalky' | ||||
| 	), | ||||
| 	path( | ||||
| 		'org/vloz_body/<int:tema>/', | ||||
| 		org_required(views.VlozBodyView.as_view()), | ||||
| 		name='seminar_org_vlozbody' | ||||
| 	), | ||||
| 	# příprava na nestatický orgorozcestník | ||||
| 	path( | ||||
| 		'org/rozcestnik/', | ||||
| 		org_required(views.OrgoRozcestnikView.as_view()), | ||||
| 		name='seminar_org_rozcestnik' | ||||
| 	), | ||||
| 	path('cislo/<int:rocnik>.<int:cislo>/obalky.pdf', | ||||
| 		staff_member_required(views.cisloObalkyView), name='seminar_cislo_obalky'), | ||||
| 
 | ||||
| 	path('cislo/<int:rocnik>.<int:cislo>/tituly.tex', | ||||
| 	    	staff_member_required(views.TitulyView), name='seminar_cislo_titul'), | ||||
| 	path('stav', | ||||
| 		staff_member_required(views.StavDatabazeView), name='stav_databaze'), | ||||
| 	path('cislo/<int:rocnik>.<int:cislo>/obalkovani', | ||||
| 		staff_member_required(views.ObalkovaniView.as_view()), name='seminar_cislo_resitel_obalkovani'), | ||||
| 	path('soustredeni/<int:soustredeni>/obalky.pdf', | ||||
| 		staff_member_required(views.soustredeniObalkyView), name='seminar_soustredeni_obalky'), | ||||
| 
 | ||||
| 	path('org/vloz_body/<int:tema>/', | ||||
| 		staff_member_required(views.VlozBodyView.as_view()),name='seminar_org_vlozbody'), | ||||
| 	path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'), | ||||
| 	path('login/', views.LoginView.as_view(), name='login'), | ||||
| 	path('logout/', views.LogoutView.as_view(), name='logout'), | ||||
| 	path('resitel/', views.ResitelView.as_view(), name='seminar_resitel'), | ||||
| 	path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'), | ||||
| 	path('reset_password/', views.PasswordResetView.as_view(), name='reset_password'), | ||||
| 	path('change_password/', views.PasswordChangeView.as_view(), name='change_password'), | ||||
| 	path('reset_password_done/', views.PasswordResetDoneView.as_view(), name='reset_password_done'), | ||||
| 	path('reset_password_confirm/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), | ||||
| 	path('reset_password_complete/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'), | ||||
| 	path('resitel_edit', views.resitelEditView, name='seminar_resitel_edit'), | ||||
| 	path( | ||||
| 		'resitel_edit', | ||||
| 		login_required(views.resitelEditView, login_url='/login/'), | ||||
| 		name='seminar_resitel_edit' | ||||
| 	), | ||||
| 
 | ||||
| 	# Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku | ||||
| 	path('profil/', views.profilView, name='profil'), | ||||
| 
 | ||||
| 	# Autocomplete | ||||
| 	path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'), | ||||
| 	path('autocomplete/resitel/',views.ResitelAutocomplete.as_view(), name='autocomplete_resitel'), | ||||
| 	path('autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'), | ||||
| 	path('autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'), | ||||
| 
 | ||||
| 	path('temp/add_solution', views.AddSolutionView.as_view(),name='seminar_vloz_reseni'), | ||||
| 	path('temp/nahraj_reseni', views.NahrajReseniView.as_view(),name='seminar_nahraj_reseni'), | ||||
| 	path('temp/add_solution', org_required(views.AddSolutionView.as_view()), name='seminar_vloz_reseni'), | ||||
| 	path('temp/nahraj_reseni', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'), | ||||
| 
 | ||||
| 	path('', views.TitulniStranaView.as_view(), name='titulni_strana'), | ||||
| 
 | ||||
| 	# Ceka na autocomplete v3 | ||||
| 	# path('autocomplete/organizatori/', | ||||
| 	# staff_member_required(views.OrganizatorAutocomplete.as_view()), | ||||
| 	# org_member_required(views.OrganizatorAutocomplete.as_view()), | ||||
| 	# name='seminar_autocomplete_organizator') | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,15 +1,25 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| import datetime | ||||
| from django.contrib.auth.decorators import user_passes_test | ||||
| 
 | ||||
| from django.contrib.auth import get_user_model | ||||
| from django.contrib.auth.decorators import permission_required | ||||
| from html.parser import HTMLParser | ||||
| 
 | ||||
| from django.contrib.auth.models import AnonymousUser | ||||
| from django.contrib.contenttypes.models import ContentType | ||||
| from django.core.exceptions import ObjectDoesNotExist | ||||
| 
 | ||||
| import seminar.models as m | ||||
| import seminar.treelib as t | ||||
| 
 | ||||
| staff_member_required = user_passes_test(lambda u: u.is_staff) | ||||
| org_required = permission_required('auth.org', raise_exception=True) | ||||
| resitel_required = permission_required('auth.resitel', raise_exception=True) | ||||
| User = get_user_model() | ||||
| User.je_org = lambda self: self.has_perm('auth.org') | ||||
| User.je_resitel = lambda self: self.has_perm('auth.resitel') | ||||
| AnonymousUser.je_org = lambda self: False | ||||
| AnonymousUser.je_resitel = lambda self: False | ||||
| 
 | ||||
| 
 | ||||
| class FirstTagParser(HTMLParser): | ||||
|  |  | |||
|  | @ -6,8 +6,6 @@ from html.parser import HTMLParser | |||
| 
 | ||||
| import seminar.models as m | ||||
| 
 | ||||
| staff_member_required = user_passes_test(lambda u: u.is_staff) | ||||
| 
 | ||||
| class FirstTagParser(HTMLParser): | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		self.firstTag = None | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # coding:utf-8 | ||||
| 
 | ||||
| from django.shortcuts import get_object_or_404, render | ||||
| from django.shortcuts import get_object_or_404, render, redirect | ||||
| from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse | ||||
| from django.urls import reverse,reverse_lazy | ||||
| from django.core.exceptions import PermissionDenied, ObjectDoesNotExist | ||||
|  | @ -10,9 +10,10 @@ from django.http import Http404,HttpResponseBadRequest,HttpResponseRedirect | |||
| from django.db.models import Q, Sum, Count | ||||
| from django.views.decorators.csrf import ensure_csrf_cookie | ||||
| from django.views.generic.edit import FormView, CreateView | ||||
| from django.views.generic.base import TemplateView | ||||
| from django.contrib.auth import authenticate, login, get_user_model, logout | ||||
| from django.contrib.auth import views as auth_views | ||||
| from django.contrib.auth.models import User | ||||
| from django.contrib.auth.models import User, Permission | ||||
| from django.contrib.auth.mixins import LoginRequiredMixin | ||||
| from django.db import transaction | ||||
| 
 | ||||
|  | @ -201,7 +202,7 @@ class AktualniZadaniView(TreeNodeView): | |||
| #			"cisla" : cisla | ||||
| #		}) | ||||
| #	return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik}) | ||||
| #     | ||||
| #	 | ||||
| 
 | ||||
| #def ZadaniAktualniVysledkovkaView(request): | ||||
| #	nastaveni = get_object_or_404(Nastaveni) | ||||
|  | @ -238,8 +239,7 @@ def spravne_novinky(request): | |||
| 	user = request.user | ||||
| 	# Využíváme líné vyhodnocování QuerySetů | ||||
| 	qs = Novinky.objects.all() | ||||
| 	# TODO: Tohle by mělo spíš kontrolovat, že je/není někdo org, než že může do Adminu. | ||||
| 	if not user.is_staff: | ||||
| 	if not user.je_org: | ||||
| 		qs = qs.filter(zverejneno=True) | ||||
| 	return qs.order_by('-datum') | ||||
| 
 | ||||
|  | @ -644,7 +644,7 @@ class ProblemView(generic.DetailView): | |||
| 	def get_context_data(self, **kwargs): | ||||
| 		context = super().get_context_data(**kwargs) | ||||
| 		# Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče. | ||||
| 		if not context['object'].verejne() and not self.request.user.is_staff: | ||||
| 		if not context['object'].verejne() and not self.request.user.je_org: | ||||
| 			raise PermissionDenied() | ||||
| 		if isinstance(context['object'], Clanek): | ||||
| 			context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni') | ||||
|  | @ -896,6 +896,43 @@ def oldObalkovaniView(request, rocnik, cislo): | |||
| 		{'cislo': cislo, 'problemy': problemy, 'reseni': reseni} | ||||
| 	) | ||||
| 
 | ||||
| ### Orgostránky | ||||
| 
 | ||||
| class OrgoRozcestnikView(TemplateView): | ||||
| 	''' Zobrazí organizátorský rozcestník.''' | ||||
| 
 | ||||
| 	template_name = 'seminar/orgorozcestnik.html' | ||||
| 
 | ||||
| 	def get_context_data(self, **kwargs): | ||||
| 		context = super().get_context_data(**kwargs) | ||||
| 		context['posledni_soustredeni'] = Soustredeni.objects.order_by('-datum_konce').first() | ||||
| 		nastaveni = Nastaveni.objects.first() | ||||
| 		aktualni_rocnik = nastaveni.aktualni_rocnik | ||||
| 		context['posledni_cislo_url'] = nastaveni.aktualni_cislo.verejne_url() | ||||
| 		# TODO možná chceme odkazovat na právě rozpracované číslo, a ne to poslední vydané | ||||
| 		# pokud nechceme haluzit kód (= poradi) dalšího čísla, bude asi potřeba jít  | ||||
| 		# přes treenody (a dát si přitom pozor na MezicisloNode) | ||||
| 
 | ||||
| 		u = self.request.user | ||||
| 		os = s.Osoba.objects.get(user=u) | ||||
| 		organizator = s.Organizator.objects.get(osoba=os) | ||||
| 		temata_garant = s.Tema.objects.filter(garant=organizator,  | ||||
| 			rocnik=aktualni_rocnik) | ||||
| 		#FIXME: přidat opravovatel, stav='STAV_ZADANY' | ||||
| 		ulohy_garant = s.Uloha.objects.filter(garant=organizator, | ||||
| 			cislo_zadani__rocnik=aktualni_rocnik) | ||||
| 		clanky_garant = s.Clanek.objects.filter(garant=organizator, | ||||
| 			cislo__rocnik=aktualni_rocnik) | ||||
| 
 | ||||
| 		context['temata'] = temata_garant | ||||
| 		context['ulohy'] = ulohy_garant | ||||
| 		context['clanky'] = clanky_garant | ||||
| 		context['organizator'] = organizator | ||||
| 		return context | ||||
| 
 | ||||
| 		#content_type = 'text/plain; charset=UTF8' | ||||
| 	#XXX | ||||
| 
 | ||||
| ### Tituly | ||||
| 
 | ||||
| def TitulyView(request, rocnik, cislo): | ||||
|  | @ -974,12 +1011,44 @@ def soustredeniUcastniciExportView(request,soustredeni): | |||
| 
 | ||||
| 
 | ||||
| ### Články | ||||
| def group_by_rocnik(clanky): | ||||
| 	''' Vezme zadaný seznam článků a seskupí je podle ročníku. | ||||
| 	Vrátí seznam seznamů článků ze stejného ročníku.''' | ||||
| 	if len(clanky) == 0: | ||||
| 		return clanky | ||||
| 	clanky.order_by('cislo__rocnik__rocnik') | ||||
| 	skupiny_clanku = [] | ||||
| 	skupina = [] | ||||
| 
 | ||||
| 	rocnik = clanky.first().cislo.rocnik.rocnik # první ročník | ||||
| 	for clanek in clanky: | ||||
| 		if clanek.cislo.rocnik.rocnik == rocnik: | ||||
| 			skupina.append(clanek) | ||||
| 		else: | ||||
| 			skupiny_clanku.append(skupina) | ||||
| 			skupina = [] | ||||
| 			skupina.append(clanek) | ||||
| 			rocnik = clanek.cislo.rocnik.rocnik | ||||
| 	skupiny_clanku.append(skupina) | ||||
| 	return skupiny_clanku | ||||
| 	 | ||||
| 
 | ||||
| # FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi | ||||
| # FIXME: Původně tu byl kód přímo v těle třídy, což rozbíjelo migrace. Opravil jsem, ale vůbec nevím, jestli to funguje. | ||||
| class ClankyResitelView(generic.ListView): | ||||
| 	model = Problem | ||||
| 	template_name = 'seminar/clanky/resitelske_clanky.html' | ||||
| 	queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') | ||||
| 
 | ||||
| 	# FIXME: QuerySet není pole! | ||||
| 	def get_queryset(self): | ||||
| 		clanky = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik') | ||||
| 		queryset = [] | ||||
| 		skupiny_clanku = group_by_rocnik(clanky) | ||||
| 		for skupina in skupiny_clanku: | ||||
| 			skupina.sort(key=lambda clanek: clanek.kod_v_rocniku()) | ||||
| 			for clanek in skupina: | ||||
| 				queryset.append(clanek) | ||||
| 		return queryset | ||||
| 
 | ||||
| # FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit | ||||
| #class ClankyOrganizatorView(generic.ListView)<F12>: | ||||
|  | @ -1088,63 +1157,63 @@ def logoutView(request): | |||
| 
 | ||||
| 
 | ||||
| def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data): | ||||
| 	msg = "{}, form_hash:{}".format(msg,hash(form_data)) | ||||
| 	msg = "{}, form_hash:{}".format(msg,hash(frozenset(form_data.items))) | ||||
| 	logger.warn(msg) | ||||
| 	gdpr_logger.warn(msg+", form:{}".format(form_data))		 | ||||
| 
 | ||||
| from django.forms.models import model_to_dict | ||||
| def resitelEditView(request): | ||||
|     err_logger = logging.getLogger('seminar.prihlaska.problem') | ||||
|     ## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately | ||||
|     u = request.user | ||||
|     osoba_edit = Osoba.objects.get(user=u) | ||||
|     resitel_edit = osoba_edit.resitel | ||||
|     user_edit = osoba_edit.user | ||||
|     ## Vytvoření slovníku, kterým předvyplním formulář  | ||||
|     prefill_1=model_to_dict(user_edit) | ||||
|     prefill_2=model_to_dict(resitel_edit) | ||||
|     prefill_3=model_to_dict(osoba_edit) | ||||
|     prefill_1.update(prefill_2) | ||||
|     prefill_1.update(prefill_3) | ||||
|     form = ProfileEditForm(initial=prefill_1) | ||||
|     ## Změna údajů a jejich uložení | ||||
|     if request.method == 'POST': | ||||
|         form = ProfileEditForm(request.POST) | ||||
|         if form.is_valid(): | ||||
|             ## Změny v osobě | ||||
|             fcd = form.cleaned_data | ||||
|             osoba_edit.jmeno = fcd['jmeno'] | ||||
|             osoba_edit.prijmeni = fcd['prijmeni'] | ||||
|             osoba_edit.pohlavi_muz = fcd['pohlavi_muz'] | ||||
|             osoba_edit.email = fcd['email'] | ||||
|             osoba_edit.telefon = fcd['telefon'] | ||||
|             osoba_edit.ulice = fcd['ulice'] | ||||
|             osoba_edit.mesto = fcd['mesto'] | ||||
|             osoba_edit.psc = fcd['psc'] | ||||
|             ## Změny v osobě s podmínkami | ||||
|             if fcd.get('spam',False): | ||||
|                 osoba_edit.datum_souhlasu_zasilani = date.today() | ||||
|             if fcd.get('stat','') in ('CZ','SK'): | ||||
|                 osoba_edit.stat = fcd['stat'] | ||||
|             else: | ||||
|                 ## Neznámá země | ||||
|                 msg = "Unknown country {}".format(fcd['stat_text']) | ||||
| 	err_logger = logging.getLogger('seminar.prihlaska.problem') | ||||
| 	## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately | ||||
| 	u = request.user | ||||
| 	osoba_edit = Osoba.objects.get(user=u) | ||||
| 	resitel_edit = osoba_edit.resitel | ||||
| 	user_edit = osoba_edit.user | ||||
| 	## Vytvoření slovníku, kterým předvyplním formulář  | ||||
| 	prefill_1=model_to_dict(user_edit) | ||||
| 	prefill_2=model_to_dict(resitel_edit) | ||||
| 	prefill_3=model_to_dict(osoba_edit) | ||||
| 	prefill_1.update(prefill_2) | ||||
| 	prefill_1.update(prefill_3) | ||||
| 	form = ProfileEditForm(initial=prefill_1) | ||||
| 	## Změna údajů a jejich uložení | ||||
| 	if request.method == 'POST': | ||||
| 		form = ProfileEditForm(request.POST) | ||||
| 		if form.is_valid(): | ||||
| 			## Změny v osobě | ||||
| 			fcd = form.cleaned_data | ||||
| 			osoba_edit.jmeno = fcd['jmeno'] | ||||
| 			osoba_edit.prijmeni = fcd['prijmeni'] | ||||
| 			osoba_edit.pohlavi_muz = fcd['pohlavi_muz'] | ||||
| 			osoba_edit.email = fcd['email'] | ||||
| 			osoba_edit.telefon = fcd['telefon'] | ||||
| 			osoba_edit.ulice = fcd['ulice'] | ||||
| 			osoba_edit.mesto = fcd['mesto'] | ||||
| 			osoba_edit.psc = fcd['psc'] | ||||
| 			## Změny v osobě s podmínkami | ||||
| 			if fcd.get('spam',False): | ||||
| 				osoba_edit.datum_souhlasu_zasilani = date.today() | ||||
| 			if fcd.get('stat','') in ('CZ','SK'): | ||||
| 				osoba_edit.stat = fcd['stat'] | ||||
| 			else: | ||||
| 				## Neznámá země | ||||
| 				msg = "Unknown country {}".format(fcd['stat_text']) | ||||
| 
 | ||||
|             ## Změny v řešiteli | ||||
|             resitel_edit.skola = fcd['skola'] | ||||
|             resitel_edit.rok_maturity = fcd['rok_maturity'] | ||||
|             resitel_edit.zasilat = fcd['zasilat'] | ||||
|             if fcd.get('skola'): | ||||
|                 resitel_edit.skola = fcd['skola'] | ||||
|             else: | ||||
|                 # Unknown school - log it | ||||
|                 msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa']) | ||||
|             resitel_edit.save() | ||||
|             osoba_edit.save() | ||||
|             return HttpResponseRedirect('/thanks/') | ||||
|     else: | ||||
|         ## Stránka před odeslaním formuláře = předvyplněný formulář | ||||
|         return render(request, 'seminar/profil/edit.html', {'form': form}) | ||||
| 			## Změny v řešiteli | ||||
| 			resitel_edit.skola = fcd['skola'] | ||||
| 			resitel_edit.rok_maturity = fcd['rok_maturity'] | ||||
| 			resitel_edit.zasilat = fcd['zasilat'] | ||||
| 			if fcd.get('skola'): | ||||
| 				resitel_edit.skola = fcd['skola'] | ||||
| 			else: | ||||
| 				# Unknown school - log it | ||||
| 				msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa']) | ||||
| 			resitel_edit.save() | ||||
| 			osoba_edit.save() | ||||
| 			return formularOKView(request) | ||||
| 	else: | ||||
| 		## Stránka před odeslaním formuláře = předvyplněný formulář | ||||
| 		return render(request, 'seminar/profil/edit.html', {'form': form}) | ||||
| 
 | ||||
| def prihlaskaView(request): | ||||
| 	generic_logger = logging.getLogger('seminar.prihlaska') | ||||
|  | @ -1156,8 +1225,8 @@ def prihlaskaView(request): | |||
| 		if form.is_valid(): | ||||
| 			generic_logger.info("Form valid") | ||||
| 			fcd = form.cleaned_data | ||||
| 			form_hash = hash(fcd) | ||||
| 			form_logger.info(fcd,form_hash=form_hash) | ||||
| 			form_hash = hash(frozenset(fcd.items())) | ||||
| 			form_logger.info(str(fcd) + str(form_hash))  # TODO možná logovat jinak | ||||
| 			 | ||||
| 			with transaction.atomic(): | ||||
| 				u = User.objects.create_user( | ||||
|  | @ -1165,6 +1234,8 @@ def prihlaskaView(request): | |||
| 					password=fcd['password'], | ||||
| 					email = fcd['email']) | ||||
| 				u.save() | ||||
| 				resitel_perm = Permission.objects.filter(codename__exact='resitel').first() | ||||
| 				u.user_permissions.add(resitel_perm) | ||||
| 
 | ||||
| 				o = Osoba( | ||||
| 					jmeno = fcd['jmeno'], | ||||
|  | @ -1187,7 +1258,7 @@ def prihlaskaView(request): | |||
| 				else: | ||||
| 					# Unknown country - log it | ||||
| 					msg = "Unknown country {}".format(fcd['stat_text']) | ||||
| 					err_logger.warn(msg,form_hash=form_hash) | ||||
| 					err_logger.warn(msg + str(form_hash)) | ||||
| 
 | ||||
| 				o.save() | ||||
| 				o.user = u | ||||
|  | @ -1205,11 +1276,11 @@ def prihlaskaView(request): | |||
| 				else: | ||||
| 					# Unknown school - log it | ||||
| 					msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa']) | ||||
| 					err_logger.warn(msg,form_hash=form_hash) | ||||
| 					err_logger.warn(msg + str(form_hash)) | ||||
| 				r.save() | ||||
| 
 | ||||
| 
 | ||||
| 			return HttpResponseRedirect('/thanks/') | ||||
| 			return formularOKView(request) | ||||
| 
 | ||||
| 	# if a GET (or any other method) we'll create a blank form | ||||
| 	else: | ||||
|  | @ -1259,3 +1330,28 @@ class PasswordResetCompleteView(auth_views.PasswordResetCompleteView): | |||
| class PasswordChangeView(auth_views.PasswordChangeView): | ||||
| 	#template_name = 'seminar/password_change.html' | ||||
| 	success_url = reverse_lazy('titulni_strana') | ||||
| 
 | ||||
| 
 | ||||
| # Jen hloupé rozhazovátko | ||||
| def profilView(request): | ||||
| 	user = request.user | ||||
| 	if user.has_perm('auth.org'): | ||||
| 		return OrgoRozcestnikView.as_view()(request) | ||||
| 	if user.has_perm('auth.resitel'): | ||||
| 		return ResitelView.as_view()(request) | ||||
| 	else: | ||||
| 		return LoginView.as_view()(request) | ||||
| 
 | ||||
| # Interní, nemá se nikdy objevit v urls (jinak to účastníci vytrolí) | ||||
| def formularOKView(request): | ||||
| 	template_name = 'seminar/formular_ok.html' | ||||
| 	odkazy = [ | ||||
| 		# (Text, odkaz) | ||||
| 		('Vrátit se na titulní stránku', reverse('titulni_strana')), | ||||
| 		('Zobrazit aktuální zadání', reverse('seminar_aktualni_zadani')), | ||||
| 	] | ||||
| 	context = { | ||||
| 		'odkazy': odkazy, | ||||
| 	} | ||||
| 	return render(request, template_name, context) | ||||
| 
 | ||||
|  |  | |||
 Kateřina Č
						Kateřina Č