diff --git a/MIGRATIONS b/MIGRATIONS deleted file mode 100644 index 3cf73ac4..00000000 --- a/MIGRATIONS +++ /dev/null @@ -1,187 +0,0 @@ -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 - diff --git a/aesop/__init__.py b/aesop/__init__.py new file mode 100644 index 00000000..440e1492 --- /dev/null +++ b/aesop/__init__.py @@ -0,0 +1,3 @@ +""" +Obsahuje vše, co se týká aesopu (exportu, který po nás vyžaduje OPMK). +""" \ No newline at end of file diff --git a/aesop/apps.py b/aesop/apps.py new file mode 100644 index 00000000..c2d509f1 --- /dev/null +++ b/aesop/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AesopConfig(AppConfig): + name = 'aesop' diff --git a/dakosdump/__init__.py b/aesop/migrations/__init__.py similarity index 100% rename from dakosdump/__init__.py rename to aesop/migrations/__init__.py diff --git a/seminar/ovvpfile.py b/aesop/ovvpfile.py similarity index 100% rename from seminar/ovvpfile.py rename to aesop/ovvpfile.py diff --git a/aesop/urls.py b/aesop/urls.py new file mode 100644 index 00000000..f39a0ba8 --- /dev/null +++ b/aesop/urls.py @@ -0,0 +1,20 @@ +from django.urls import path +from aesop import views + +urlpatterns = [ + path( + 'aesop-export/mam-rocnik-.csv', + views.ExportRocnikView.as_view(), + name='seminar_export_rocnik' + ), + path( + 'aesop-export/mam-sous-.csv', + views.ExportSousView.as_view(), + name='seminar_export_sous' + ), + path( + 'aesop-export/index.csv', + views.ExportIndexView.as_view(), + name='seminar_export_index' + ), +] diff --git a/aesop/utils.py b/aesop/utils.py new file mode 100644 index 00000000..3ea62dce --- /dev/null +++ b/aesop/utils.py @@ -0,0 +1,16 @@ +import datetime + +from django.utils.encoding import force_text + +from aesop.ovvpfile import OvvpFile + + +def default_ovvpfile(event, rocnik): + of = OvvpFile() + of.headers['version'] = '1' + of.headers['event'] = event + of.headers['year'] = force_text(rocnik.prvni_rok) + of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + of.headers['id-scope'] = 'mam' + of.headers['id-generation'] = '1' + return of diff --git a/seminar/export.py b/aesop/views.py similarity index 83% rename from seminar/export.py rename to aesop/views.py index d2dcdd81..c46ab605 100644 --- a/seminar/export.py +++ b/aesop/views.py @@ -1,14 +1,12 @@ -import datetime, django -from django.shortcuts import get_object_or_404, render +import django +from django.shortcuts import get_object_or_404 from django.http import HttpResponse from django.urls import reverse from django.views import generic from django.utils.encoding import force_text -from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni -#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva -from .ovvpfile import OvvpFile -from seminar import views +from .utils import default_ovvpfile +from seminar.models import Rocnik, Soustredeni from seminar.views import vysledkovka from seminar.utils import aktivniResitele @@ -25,17 +23,6 @@ class ExportIndexView(generic.View): return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8') -def default_ovvpfile(event, rocnik): - of = OvvpFile() - of.headers['version'] = '1' - of.headers['event'] = event - of.headers['year'] = force_text(rocnik.prvni_rok) - of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - of.headers['id-scope'] = 'mam' - of.headers['id-generation'] = '1' - return of - - class ExportSousView(generic.View): def get(self, request, datum_zacatku=None): diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 00000000..4c5291cb --- /dev/null +++ b/api/__init__.py @@ -0,0 +1,3 @@ +""" +Obsahuje api = autocomplete + export škol. +""" diff --git a/api/apps.py b/api/apps.py new file mode 100644 index 00000000..d87006dd --- /dev/null +++ b/api/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + name = 'api' diff --git a/api/migrations/__init__.py b/api/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/api/tests/__init__.py b/api/tests/__init__.py new file mode 100644 index 00000000..7a6e81d2 --- /dev/null +++ b/api/tests/__init__.py @@ -0,0 +1 @@ +from .test_skola_autocomplete import * diff --git a/seminar/test_skola_autocomplete.py b/api/tests/test_skola_autocomplete.py similarity index 100% rename from seminar/test_skola_autocomplete.py rename to api/tests/test_skola_autocomplete.py diff --git a/api/urls.py b/api/urls.py new file mode 100644 index 00000000..e869df80 --- /dev/null +++ b/api/urls.py @@ -0,0 +1,19 @@ +from django.urls import path +from . import views +from seminar.utils import org_required + +urlpatterns = [ + # Export škol + path('api/export/skoly/', views.exportSkolView, name='export_skoly'), + + + # Autocomplete + path('api/autocomplete/skola/', views.SkolaAutocomplete.as_view(), name='autocomplete_skola'), + path('api/autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'), + path('api/autocomplete/problem/odevzdatelny', views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'), + + # Ceka na autocomplete v3 + # path('autocomplete/organizatori/', + # org_member_required(views.OrganizatorAutocomplete.as_view()), + # name='seminar_autocomplete_organizator') +] diff --git a/api/views/__init__.py b/api/views/__init__.py new file mode 100644 index 00000000..fc00554e --- /dev/null +++ b/api/views/__init__.py @@ -0,0 +1,2 @@ +from .autocomplete import * +from .exports import * diff --git a/seminar/views/autocomplete.py b/api/views/autocomplete.py similarity index 82% rename from seminar/views/autocomplete.py rename to api/views/autocomplete.py index 121ddefc..a97fbbab 100644 --- a/seminar/views/autocomplete.py +++ b/api/views/autocomplete.py @@ -5,16 +5,20 @@ from django.db.models import Q import seminar.models as m from .helpers import LoginRequiredAjaxMixin +# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr) class SkolaAutocomplete(autocomplete.Select2QuerySetView): def get_queryset(self): # Don't forget to filter out results depending on the visitor ! qs = m.Skola.objects.all() if self.q: - qs = qs.filter( - Q(nazev__istartswith=self.q)| - Q(kratky_nazev__istartswith=self.q)| - Q(ulice__istartswith=self.q)| - Q(mesto__istartswith=self.q)) + words = self.q.split(' ') #TODO re split podle bileho znaku + partq = Q() + for w in words: # Hledej po slovech, zahoď čárky a tečky z konců. + if w[-1] in (".",","): + w = w[:-1] + + partq &= (Q(nazev__icontains=w)|Q(kratky_nazev__icontains=w)|Q(ulice__icontains=w)|Q(mesto__icontains=w)) + qs = qs.filter(partq) return qs diff --git a/seminar/views/exports.py b/api/views/exports.py similarity index 100% rename from seminar/views/exports.py rename to api/views/exports.py diff --git a/seminar/views/helpers.py b/api/views/helpers.py similarity index 91% rename from seminar/views/helpers.py rename to api/views/helpers.py index 0b06c0eb..652344bc 100644 --- a/seminar/views/helpers.py +++ b/api/views/helpers.py @@ -1,4 +1,5 @@ -from dal import autocomplete +from django.http import JsonResponse + class LoginRequiredAjaxMixin(object): def dispatch(self, request, *args, **kwargs): diff --git a/dakosdump/README.md b/dakosdump/README.md deleted file mode 100644 index fbeef4c5..00000000 --- a/dakosdump/README.md +++ /dev/null @@ -1,308 +0,0 @@ -# Poznámky k exportu a reimportu MaM dat # - -### Dakos Oracle dump - postup ### - -Na lib. stroji na KAMu spustit: - - ORACLE_HOME=/nfs/nikam/sw/oracle-10.2/ora_home_10.2/ LC_ALL=C AESOP_PASSWD= perl oracle_dump - -Dumpne vsechny tabulky krom SYS.* - - from seminar.dksdump.helpers import read_all_tables, matchrows, onerow - ts = read_all_tables('seminar/dksdump/oracle_dks_dump/') - -Načte a vypíše všechny tabulky. Yay! -Pozor! V základu mají všechny podivný 2. řádek s bordelem! (čísla 3, 12, ...) - -Import do SQLite3 pomocí `.mode tabs` a `.import DKSROOT.V_SKOLY.csv DKSROOT_V_SKOLY`. - -### Postup pomocí sqlite3 s Dakos daty ### - -#### Řešitelé s něajkými úlohami ### - - r=(sqget(db, "select dr.ROKMATURITY, o.JMENO, o.PRIJMENI, dr.DATUMNAROZENI, o.POHLAVI from MAMOPER_MM_RESENI as res, DKSROOT_OSOBA as o, DKSROOT_RESITEL as dr where res.RESITEL=o.ID and dr.ID=o.ID group by o.ID")) - MAMID_FOR_DAKOSID = {} - -Překlad ID je potom: - - MAMID_FOR_DAKOSID = {u'18313': 501, u'25075': 595, u'15162': 453, u'14673': 441, u'218': 549, u'20414': 525, u'27538': 617, u'18733': 504, u'13935': 427, u'12074': 409, u'23855': 580, u'12372': 412, u'14950': 448, u'428': 620, u'14989': 451, u'26574': 609, u'24791': 590, u'26628': 610, u'26705': 615, u'17273': 486, u'12172': 410, u'1377': 426, u'19859': 517, u'25597': 603, u'21176': 543, u'20453': 527, u'19278': 509, u'14107': 429, u'19274': 508, u'14842': 445, u'14667': 440, u'25176': 597, u'17713': 490, u'15753': 463, u'2': 518, u'17393': 489, u'22673': 568, u'1553': 459, u'13600': 423, u'1556': 460, u'1708': 480, u'18753': 506, u'13609': 424, u'415': 619, u'19653': 516, u'13499': 418, u'22637': 557, u'25608': 604, u'15744': 462, u'21102': 539, u'15740': 461, u'21107': 541, u'22633': 553, u'22793': 573, u'22711': 572, u'14323': 434, u'22643': 563, u'22013': 551, u'22641': 561, u'22640': 560, u'22646': 566, u'20113': 520, u'22644': 564, u'21993': 550, u'22833': 574, u'24022': 583, u'24375': 587, u'21183': 544, u'26693': 614, u'1359': 422, u'21184': 545, u'26555': 608, u'14290': 430, u'22635': 555, u'12313': 411, u'17253': 485, u'18734': 505, u'15522': 458, u'19219': 507, u'25535': 599, u'22653': 567, u'25538': 600, u'17234': 484, u'17233': 483, u'1135': 403, u'381': 618, u'21453': 546, u'20433': 526, u'17133': 481, u'101': 402, u'21056': 536, u'14522': 437, u'19282': 510, u'19285': 511, u'21513': 547, u'11515': 404, u'17974': 499, u'16813': 478, u'1648': 477, u'17973': 498, u'14689': 442, u'15833': 464, u'21094': 537, u'15836': 466, u'15837': 467, u'15834': 465, u'22974': 577, u'15838': 468, u'15839': 469, u'24930': 593, u'459': 623, u'16333': 475, u'11948': 408, u'15087': 452, u'19617': 514, u'23655': 579, u'14387': 435, u'457': 622, u'14307': 431, u'24126': 585, u'21105': 540, u'24081': 584, u'15324': 455, u'23193': 578, u'24004': 582, u'26661': 612, u'1730': 488, u'24825': 592, u'17960': 497, u'11620': 405, u'1469': 443, u'250': 594, u'19290': 512, u'24296': 586, u'17887': 494, u'26235': 606, u'14962': 450, u'14961': 449, u'1358': 421, u'22636': 556, u'17274': 487, u'22634': 554, u'13965': 428, u'19622': 515, u'22638': 558, u'1350': 419, u'1357': 420, u'24637': 589, u'14878': 446, u'25556': 602, u'25555': 601, u'20475': 530, u'14314': 432, u'14315': 433, u'221': 552, u'20413': 524, u'15313': 454, u'1188': 407, u'21733': 548, u'26684': 613, u'26455': 607, u'17955': 496, u'25916': 605, u'22863': 575, u'21098': 538, u'1453': 438, u'26642': 611, u'20154': 521, u'14625': 439, u'15874': 472, u'14879': 447, u'1169': 406, u'16053': 473, u'12546': 413, u'22685': 570, u'20014': 519, u'16353': 476, u'17829': 492, u'22642': 562, u'20393': 523, u'469': 624, u'17949': 495, u'16193': 474, u'20313': 522, u'13468': 417, u'27476': 616, u'24442': 588, u'22681': 569, u'21036': 535, u'25111': 596, u'19420': 513, u'18633': 503, u'22645': 565, u'1293': 414, u'25495': 598, u'18133': 500, u'17193': 482, u'22639': 559, u'15841': 471, u'15840': 470, u'450': 621, u'17838': 493, u'20478': 533, u'20479': 534, u'22694': 571, u'17793': 491, u'21159': 542, u'20473': 528, u'23981': 581, u'20476': 531, u'20477': 532, u'20474': 529, u'17073': 479, u'22865': 576, u'13072': 415, u'13073': 416, u'14404': 436, u'15375': 457, u'15374': 456, u'24815': 591, u'1365': 425, u'1474': 444, u'18453': 502} - -#### Staří orgové `[MAMOPER_MM_ULOHA]` #### - - - for i in set([i.OPRAVUJICI for i in sqget(db, "select * from MAMOPER_MM_ULOHA")]): - if i and len(User.objects.filter(username=i))==0: User.objects.create_user(i) - -#### Staré úlohy `[MAMOPER_MM_ULOHA]` #### - -Temata (prořezávání opakujících se) - - r=sqget(db, "select * from MAMOPER_MM_ULOHA where KOD like 't%' ORDER BY CISLO") - seen = set() - for i in r: - if i.NAZEV in seen: - continue - seen.add(i.NAZEV) - o = User.objects.get(username=i.OPRAVUJICI) if i.OPRAVUJICI else None; - c = Cislo.objects.get(rocnik__rocnik=int(i.ROCNIK), cislo=i.CISLO); - t=Problem.TYP_ULOHA if i.KOD[0] == 'r' else Problem.TYP_TEMA; - Problem.objects.create(nazev=i.NAZEV, body=int(i.BODY) if i.BODY else None, typ=t, stav=Problem.STAV_ZADANY, opravovatel=o, - kod=i.KOD[1:], cislo_zadani=c, import_dakos_id='ULOHA:%s' % (i.ID, ), - text_problemu_org=u"Importováno z MAMOPER.MM_ULOHA\nKod: %s\nID: %s" % (i.KOD, i.ID, )) - -Ulohy - - r=sqget(db, "select * from MAMOPER_MM_ULOHA where KOD like 'r%'") - for i in r: - o = User.objects.get(username=i.OPRAVUJICI) if i.OPRAVUJICI else None; - c = Cislo.objects.get(rocnik__rocnik=int(i.ROCNIK), cislo=i.CISLO); - t=Problem.TYP_ULOHA if i.KOD[0] == 'r' else Problem.TYP_TEMA; - Problem.objects.create(nazev=i.NAZEV, body=int(i.BODY) if i.BODY else None, typ=t, stav=Problem.STAV_ZADANY, opravovatel=o, - kod=i.KOD[1:], cislo_zadani=c, import_dakos_id='ULOHA:%s' % (i.ID, ), - text_problemu_org=u"Importováno z MAMOPER.MM_ULOHA\nKod: %s\nID: %s" % (i.KOD, i.ID, )) - -A pak prořezání opakujících se témátek ... - -#### Stará řešení a body #### - - r=sqget(db, "select res.RESITEL, res.KDY, b.ULOHA, b.BODY, res.VYZVEDL, res.FORMA, res.POZNAMKA from MAMOPER_MM_RESENI as res, MAMOPER_MM_RESENI_BODY as b where res.RESITEL=b.RESITEL and res.ULOHA=b.ULOHA") - for i in r: - print i - p = Problem.objects.filter(import_dakos_id='ULOHA:%s' % (i.ULOHA, )); - g = sqget(db, "select * from MAMOPER_MM_ULOHA where ID='%s'" % (i.ULOHA, ))[0] - if not p: - assert g.KOD[0] == 't' - p = Problem.objects.filter(cislo_zadani__rocnik__rocnik=int(g.ROCNIK), typ=Problem.TYP_TEMA, kod=g.KOD[1:]).order_by('cislo_zadani__cislo') - if len(p) >= 2: - p = [p.filter(cislo_zadani__cislo__lte=g.CISLO).last()] - p = p[0] - c = Cislo.objects.get(rocnik__rocnik=int(g.ROCNIK), cislo=g.CISLO) - c2 = c.relativni_v_rocniku(2) or c.relativni_v_rocniku(1) - assert c2 - resitel=Resitel.objects.get(id=MAMID_FOR_DAKOSID[i.RESITEL]); - b = int(i.BODY) - Reseni.objects.create(problem=p, resitel=resitel, body=b, timestamp=transdate(i.KDY), - forma=Reseni.FORMA_EMAIL if i.FORMA=='e' else Reseni.FORMA_PAPIR, cislo_body=c2, - poznamka="Import z MAMOPER_MM_RESENI, MAMOPER_MM_RESENI_BODY\nVyzvedl: %s\nPuvodni poznamka: %s" % (i.VYZVEDL, i.POZNAMKA, )) - - -#### Novější problémy (znovu) `[MM_ZADANIA]` #### - -Pozn.: CISLO udává vždy nejen číslo zadání, ale zároveň určuje číslo řešení i u témat (+2). Témata jsou též zadána vícekrát, -jednou za každé číslo s výsledky (číslované (-2)). - -Úlohy a seriály: - - r = sqget(db, "select * from MAMOPER_MM_ZADANIA where TYP='1' order by CISLO") - r += sqget(db, "select * from MAMOPER_MM_ZADANIA where TYP='3' order by CISLO") - for i in r: - c = Cislo.objects.get(cislo=i.CISLO if i.CISLO!='9' else '1', rocnik__rocnik=int(i.ROCNIK)); - opravovatel = User.objects.get(username=i.OPRAVUJE) if i.OPRAVUJE else None; - Problem.objects.create(nazev=i.NAZOV, typ=typtable[i.TYP], stav=Problem.STAV_ZADANY, opravovatel=opravovatel, kod=i.ULOHA, - cislo_zadani=c, cislo_reseni=c.relativni_v_rocniku(2), body=int(i.MAX_BODY), - import_dakos_id='ZAD:%s.%s.%s.%s'%(i.ROCNIK, i.CISLO, i.ULOHA, i.TYP,), - text_problemu_org=u'Importováno z MAMOPER_MM_ZADANIA\nOpravuje: %s' % (i.OPRAVUJE, ) ) - -Témata: - - r = sqget(db, "select * from MAMOPER_MM_ZADANIA where TYP='2' order by CISLO") - for i in r: - c = Cislo.objects.get(cislo=i.CISLO if i.CISLO!='9' else '1', rocnik__rocnik=int(i.ROCNIK)); - opravovatel = User.objects.get(username=i.OPRAVUJE) if i.OPRAVUJE else None; - Problem.objects.create(nazev=i.NAZOV, typ=typtable[i.TYP], stav=Problem.STAV_ZADANY, opravovatel=opravovatel, kod=i.ULOHA, - cislo_zadani=c, body=None, import_dakos_id='ZAD:%s.%s.%s.%s'%(i.ROCNIK, i.CISLO, i.ULOHA, i.TYP,), - text_problemu_org=u'Importováno z MAMOPER_MM_ZADANIA\nOpravuje: %s' % (i.OPRAVUJE, ) ) if not Problem.objects.filter( - nazev=i.NAZOV, typ=Problem.TYP_TEMA, cislo_zadani__isnull=False) else None - - -#### Novější řešení (znovu) `[MM_RIESENIA]` #### - - r=sqget(db, "select * from MAMOPER_MM_RIESENIA") - for i in r: - print i - tstp = datetime.datetime.fromtimestamp(int(i.DORUCENA)); - res = Resitel.objects.get(import_mamoper_id=i.RIESITEL); - c = Cislo.objects.get(rocnik__rocnik=int(i.ROCNIK), cislo=i.CISLO if i.CISLO!='9' else '1') - if i.TYP == '2': - u = Problem.objects.filter(cislo_zadani__rocnik=c.rocnik, typ=Problem.TYP_TEMA, kod=i.ULOHA).order_by('cislo_zadani__cislo') - print c, res, u - if len(u) >= 2: - u = u.filter(cislo_zadani__cislo__lte=c.cislo).last() - else: - u = u[0] - else: - u = Problem.objects.get(import_dakos_id="ZAD:%s.%s.%s.%s" % (i.ROCNIK, i.CISLO, i.ULOHA, i.TYP,)); - cbod = c.relativni_v_rocniku(2) - if not cbod: - cbod = c.relativni_v_rocniku(1) - assert cbod - Reseni.objects.create(problem=u, resitel=res, body=int(i.POCET_BODOV) if i.POCET_BODOV else None, - forma=Reseni.FORMA_EMAIL if i.FORMA=='1' else Reseni.FORMA_PAPIR, timestamp=tstp, - poznamka='Zdroj: MM_RIESENIA\nForma: %s\n%s' % ({'1':'E', '2':'P'}[i.FORMA], i.POZNAMKA, ), - cislo_body=cbod) - - -#### Komentáře `[MAMOPER_MM_DOZ_DISKUSIA]` #### - - from django.contrib.contenttypes.models import ContentType - from django.utils.encoding import force_text - from django.conf import settings - import HTMLParser - - r = sqget(db, 'SELECT * from MAMOPER_MM_DOZ_DISKUSIA') - r = sorted(r, key=lambda x:x.ID_REAK) - tab_ID_REAK_to_ThrComment_id = {} - html_parser = HTMLParser.HTMLParser() - - for i in r: - print i - prb = Problem.objects.get(import_dakos_id='DOZ:%s' % (i.ID, )) - print prb.id - un = i.ORG - if un == u'Al\u010da': un = 'alca' - if un == u'Anet': un = 'anet' - user = User.objects.get(username=un) - parent = None if not i.ID_PARENT else ThreadedComment.objects.get(id=tab_ID_REAK_to_ThrComment_id[i.ID_PARENT]) - text = html_parser.unescape(i.TEXT_PRISPEVKU).replace('
', '\n').replace('
', '\n') - text = html_parser.unescape(text) - d = dict( - content_type=ContentType.objects.get_for_model(Problem), - object_pk=force_text(prb._get_pk_val()), - comment=text, - submit_date=transdate(i.DATUM), - site_id=settings.SITE_ID, - is_public=True, - is_removed=False, - parent=parent, - title="", - user=user, - ) - c = ThreadedComment.objects.create(**d) - tab_ID_REAK_to_ThrComment_id[i.ID_REAK] = c.id - - tab_ID_REAK_to_ThrComment_id = {u'344': 6884, u'345': 6885, u'346': 6886, u'347': 6887, u'340': 6880, u'341': 6881, u'342': 6882, u'343': 6883, u'810': 7402, u'811': 7403, u'812': 7404, u'813': 7405, u'348': 6888, u'349': 6889, u'816': 7408, u'817': 7409, u'595': 7162, u'719': 7300, u'718': 7299, u'717': 7298, u'716': 7297, u'715': 7296, u'714': 7295, u'713': 7294, u'712': 7293, u'711': 7292, u'710': 7291, u'915': 7517, u'914': 7516, u'606': 7175, u'917': 7519, u'594': 7161, u'736': 7319, u'916': 7518, u'911': 7513, u'619': 7189, u'910': 7512, u'913': 7515, u'298': 6832, u'299': 6833, u'296': 6830, u'297': 6831, u'294': 6828, u'295': 6829, u'292': 6826, u'293': 6827, u'290': 6824, u'291': 6825, u'591': 7158, u'590': 7157, u'593': 7160, u'592': 7159, u'199': 6722, u'198': 6721, u'597': 7164, u'596': 7163, u'195': 6718, u'194': 6717, u'197': 6720, u'196': 6719, u'191': 6714, u'190': 6713, u'193': 6716, u'192': 6715, u'270': 6802, u'271': 6803, u'272': 6804, u'273': 6805, u'274': 6806, u'275': 6807, u'276': 6808, u'277': 6809, u'278': 6810, u'279': 6811, u'738': 7321, u'524': 7084, u'525': 7085, u'526': 7086, u'527': 7087, u'520': 7080, u'521': 7081, u'522': 7082, u'523': 7083, u'599': 7166, u'528': 7088, u'529': 7089, u'449': 7000, u'448': 6999, u'443': 6994, u'442': 6993, u'441': 6992, u'440': 6991, u'447': 6998, u'446': 6997, u'445': 6996, u'444': 6995, u'108': 6622, u'109': 6623, u'102': 6616, u'103': 6617, u'100': 6614, u'101': 6615, u'106': 6620, u'107': 6621, u'104': 6618, u'105': 6619, u'902': 7503, u'903': 7504, u'39': 6934, u'38': 6923, u'906': 7507, u'907': 7508, u'904': 7505, u'905': 7506, u'33': 6868, u'32': 6857, u'31': 6846, u'30': 6835, u'37': 6912, u'36': 6901, u'35': 6890, u'34': 6879, u'641': 7214, u'640': 7213, u'643': 7216, u'642': 7215, u'645': 7218, u'644': 7217, u'438': 6988, u'439': 6989, u'436': 6986, u'437': 6987, u'434': 6984, u'435': 6985, u'432': 6982, u'433': 6983, u'430': 6980, u'431': 6981, u'339': 6878, u'338': 6877, u'335': 6874, u'334': 6873, u'337': 6876, u'336': 6875, u'331': 6870, u'330': 6869, u'333': 6872, u'332': 6871, u'89': 7488, u'744': 7328, u'745': 7329, u'854': 7450, u'818': 7410, u'856': 7451, u'857': 7452, u'850': 7446, u'851': 7447, u'852': 7448, u'819': 7411, u'858': 7453, u'859': 7454, u'748': 7332, u'6': 7167, u'900': 7501, u'848': 7443, u'99': 7589, u'98': 7588, u'844': 7439, u'91': 7511, u'90': 7500, u'93': 7533, u'92': 7522, u'95': 7555, u'94': 7544, u'97': 7577, u'96': 7566, u'814': 7406, u'815': 7407, u'740': 7324, u'741': 7325, u'742': 7326, u'743': 7327, u'559': 7122, u'558': 7121, u'746': 7330, u'747': 7331, u'555': 7118, u'554': 7117, u'557': 7120, u'556': 7119, u'551': 7114, u'550': 7113, u'553': 7116, u'552': 7115, u'238': 6766, u'239': 6767, u'234': 6762, u'235': 6763, u'236': 6764, u'237': 6765, u'230': 6758, u'231': 6759, u'232': 6760, u'233': 6761, u'1': 6612, u'614': 7184, u'146': 6664, u'147': 6665, u'144': 6662, u'145': 6663, u'142': 6660, u'143': 6661, u'140': 6658, u'141': 6659, u'612': 7182, u'613': 7183, u'610': 7180, u'611': 7181, u'616': 7186, u'617': 7187, u'148': 6666, u'149': 6667, u'912': 7514, u'951': 7557, u'948': 7553, u'949': 7554, u'946': 7551, u'947': 7552, u'944': 7549, u'945': 7550, u'942': 7547, u'943': 7548, u'940': 7545, u'941': 7546, u'768': 7354, u'689': 7266, u'688': 7265, u'685': 7262, u'684': 7261, u'687': 7264, u'686': 7263, u'681': 7258, u'680': 7257, u'683': 7260, u'682': 7259, u'623': 7194, u'622': 7193, u'133': 6650, u'132': 6649, u'131': 6648, u'130': 6647, u'137': 6654, u'136': 6653, u'135': 6652, u'134': 6651, u'494': 7050, u'495': 7051, u'139': 6656, u'138': 6655, u'490': 7046, u'491': 7047, u'492': 7048, u'493': 7049, u'24': 6768, u'25': 6779, u'26': 6790, u'27': 6801, u'20': 6724, u'21': 6735, u'22': 6746, u'23': 6757, u'927': 7530, u'28': 6812, u'29': 6823, u'407': 6954, u'406': 6953, u'405': 6952, u'404': 6951, u'403': 6950, u'402': 6949, u'401': 6948, u'400': 6947, u'933': 7537, u'932': 7536, u'931': 7535, u'930': 7534, u'937': 7541, u'629': 7200, u'409': 6956, u'408': 6955, u'628': 7199, u'758': 7343, u'379': 6922, u'378': 6921, u'829': 7422, u'828': 7421, u'371': 6914, u'370': 6913, u'373': 6916, u'372': 6915, u'375': 6918, u'374': 6917, u'377': 6920, u'376': 6919, u'708': 7288, u'709': 7289, u'704': 7284, u'705': 7285, u'706': 7286, u'707': 7287, u'700': 7280, u'618': 7188, u'702': 7282, u'703': 7283, u'393': 6938, u'392': 6937, u'391': 6936, u'390': 6935, u'397': 6942, u'396': 6941, u'395': 6940, u'394': 6939, u'82': 7412, u'83': 7423, u'399': 6944, u'398': 6943, u'86': 7455, u'87': 7466, u'84': 7434, u'85': 7445, u'797': 7386, u'796': 7385, u'795': 7384, u'794': 7383, u'793': 7382, u'792': 7381, u'791': 7380, u'790': 7379, u'799': 7388, u'798': 7387, u'7': 7278, u'601': 7170, u'607': 7176, u'586': 7152, u'587': 7153, u'584': 7150, u'585': 7151, u'582': 7148, u'583': 7149, u'580': 7146, u'581': 7147, u'588': 7154, u'589': 7155, u'245': 6774, u'244': 6773, u'247': 6776, u'246': 6775, u'241': 6770, u'240': 6769, u'243': 6772, u'242': 6771, u'615': 7185, u'249': 6778, u'248': 6777, u'924': 7527, u'970': 7578, u'925': 7528, u'519': 7078, u'518': 7077, u'926': 7529, u'511': 7070, u'510': 7069, u'513': 7072, u'512': 7071, u'515': 7074, u'514': 7073, u'517': 7076, u'516': 7075, u'458': 7010, u'459': 7011, u'621': 7192, u'620': 7191, u'627': 7198, u'626': 7197, u'625': 7196, u'624': 7195, u'450': 7002, u'451': 7003, u'452': 7004, u'453': 7005, u'454': 7006, u'455': 7007, u'456': 7008, u'457': 7009, u'179': 6700, u'178': 6699, u'177': 6698, u'176': 6697, u'175': 6696, u'174': 6695, u'173': 6694, u'172': 6693, u'171': 6692, u'170': 6691, u'977': 7585, u'656': 7230, u'975': 7583, u'974': 7582, u'973': 7581, u'972': 7580, u'971': 7579, u'657': 7231, u'654': 7228, u'979': 7587, u'978': 7586, u'182': 6704, u'183': 6705, u'180': 6702, u'181': 6703, u'186': 6708, u'187': 6709, u'184': 6706, u'185': 6707, u'886': 7484, u'652': 7226, u'188': 6710, u'189': 6711, u'658': 7232, u'653': 7227, u'650': 7224, u'651': 7225, u'764': 7350, u'11': 6624, u'10': 6613, u'13': 6646, u'12': 6635, u'15': 6668, u'14': 6657, u'17': 6690, u'16': 6679, u'19': 6712, u'18': 6701, u'863': 7459, u'862': 7458, u'865': 7461, u'864': 7460, u'867': 7463, u'866': 7462, u'884': 7482, u'938': 7542, u'659': 7233, u'883': 7481, u'753': 7338, u'881': 7479, u'880': 7478, u'887': 7485, u'831': 7425, u'885': 7483, u'752': 7337, u'928': 7531, u'62': 7190, u'888': 7486, u'950': 7556, u'756': 7341, u'929': 7532, u'63': 7201, u'809': 7400, u'322': 6860, u'323': 6861, u'320': 6858, u'321': 6859, u'326': 6864, u'327': 6865, u'324': 6862, u'325': 6863, u'328': 6866, u'329': 6867, u'759': 7344, u'201': 6726, u'200': 6725, u'203': 6728, u'202': 6727, u'205': 6730, u'204': 6729, u'207': 6732, u'206': 6731, u'209': 6734, u'208': 6733, u'779': 7366, u'778': 7365, u'889': 7487, u'77': 7356, u'76': 7345, u'75': 7334, u'74': 7323, u'73': 7312, u'72': 7301, u'71': 7290, u'70': 7279, u'655': 7229, u'79': 7378, u'78': 7367, u'2': 6723, u'805': 7396, u'804': 7395, u'669': 7244, u'668': 7243, u'667': 7242, u'666': 7241, u'665': 7240, u'664': 7239, u'663': 7238, u'662': 7237, u'661': 7236, u'660': 7235, u'769': 7355, u'692': 7270, u'693': 7271, u'690': 7268, u'691': 7269, u'696': 7274, u'697': 7275, u'694': 7272, u'695': 7273, u'698': 7276, u'699': 7277, u'542': 7104, u'543': 7105, u'540': 7102, u'541': 7103, u'546': 7108, u'547': 7109, u'544': 7106, u'545': 7107, u'8': 7389, u'548': 7110, u'549': 7111, u'68': 7256, u'598': 7165, u'869': 7465, u'868': 7464, u'120': 6636, u'121': 6637, u'122': 6638, u'123': 6639, u'124': 6640, u'125': 6641, u'126': 6642, u'127': 6643, u'128': 6644, u'129': 6645, u'765': 7351, u'69': 7267, u'414': 6962, u'415': 6963, u'416': 6964, u'417': 6965, u'410': 6958, u'411': 6959, u'412': 6960, u'413': 6961, u'920': 7523, u'498': 7054, u'922': 7525, u'923': 7526, u'418': 6966, u'419': 6967, u'776': 7363, u'499': 7055, u'319': 6856, u'318': 6855, u'313': 6850, u'312': 6849, u'311': 6848, u'310': 6847, u'317': 6854, u'316': 6853, u'315': 6852, u'314': 6851, u'861': 7457, u'921': 7524, u'496': 7052, u'832': 7426, u'833': 7427, u'830': 7424, u'497': 7053, u'836': 7430, u'837': 7431, u'834': 7428, u'835': 7429, u'838': 7432, u'839': 7433, u'808': 7399, u'3': 6834, u'368': 6910, u'369': 6911, u'366': 6908, u'367': 6909, u'364': 6906, u'365': 6907, u'362': 6904, u'363': 6905, u'360': 6902, u'361': 6903, u'959': 7565, u'952': 7558, u'882': 7480, u'380': 6924, u'381': 6925, u'382': 6926, u'383': 6927, u'384': 6928, u'385': 6929, u'386': 6930, u'387': 6931, u'388': 6932, u'389': 6933, u'784': 7372, u'785': 7373, u'786': 7374, u'787': 7375, u'780': 7368, u'781': 7369, u'782': 7370, u'783': 7371, u'788': 7376, u'789': 7377, u'860': 7456, u'605': 7174, u'579': 7144, u'578': 7143, u'604': 7173, u'573': 7138, u'572': 7137, u'571': 7136, u'570': 7135, u'577': 7142, u'576': 7141, u'575': 7140, u'574': 7139, u'60': 7168, u'61': 7179, u'258': 6788, u'259': 6789, u'64': 7212, u'65': 7223, u'66': 7234, u'67': 7245, u'252': 6782, u'253': 6783, u'250': 6780, u'251': 6781, u'256': 6786, u'257': 6787, u'254': 6784, u'255': 6785, u'603': 7172, u'602': 7171, u'939': 7543, u'731': 7314, u'730': 7313, u'733': 7316, u'732': 7315, u'735': 7318, u'734': 7317, u'508': 7066, u'509': 7067, u'506': 7064, u'507': 7065, u'504': 7062, u'505': 7063, u'502': 7060, u'503': 7061, u'500': 7058, u'501': 7059, u'630': 7202, u'631': 7203, u'632': 7204, u'633': 7205, u'469': 7022, u'468': 7021, u'636': 7208, u'637': 7209, u'465': 7018, u'464': 7017, u'467': 7020, u'466': 7019, u'461': 7014, u'460': 7013, u'463': 7016, u'462': 7015, u'901': 7502, u'168': 6688, u'169': 6689, u'164': 6684, u'165': 6685, u'166': 6686, u'167': 6687, u'160': 6680, u'161': 6681, u'162': 6682, u'163': 6683, u'964': 7571, u'965': 7572, u'966': 7573, u'967': 7574, u'960': 7567, u'961': 7568, u'962': 7569, u'963': 7570, u'968': 7575, u'969': 7576, u'936': 7540, u'935': 7539, u'934': 7538, u'908': 7509, u'909': 7510, u'600': 7169, u'878': 7475, u'879': 7476, u'876': 7473, u'877': 7474, u'874': 7471, u'875': 7472, u'872': 7469, u'873': 7470, u'870': 7467, u'871': 7468, u'9': 7499, u'890': 7489, u'891': 7490, u'892': 7491, u'893': 7492, u'894': 7493, u'647': 7220, u'896': 7495, u'897': 7496, u'898': 7497, u'899': 7498, u'646': 7219, u'649': 7222, u'648': 7221, u'357': 6898, u'356': 6897, u'355': 6896, u'354': 6895, u'353': 6894, u'352': 6893, u'351': 6892, u'350': 6891, u'803': 7394, u'802': 7393, u'801': 7392, u'800': 7391, u'807': 7398, u'806': 7397, u'359': 6900, u'358': 6899, u'216': 6742, u'217': 6743, u'214': 6740, u'215': 6741, u'212': 6738, u'213': 6739, u'210': 6736, u'211': 6737, u'762': 7348, u'763': 7349, u'760': 7346, u'761': 7347, u'766': 7352, u'767': 7353, u'218': 6744, u'219': 6745, u'957': 7563, u'956': 7562, u'289': 6822, u'288': 6821, u'4': 6945, u'281': 6814, u'280': 6813, u'283': 6816, u'282': 6815, u'285': 6818, u'284': 6817, u'287': 6820, u'286': 6819, u'678': 7254, u'679': 7255, u'674': 7250, u'675': 7251, u'676': 7252, u'677': 7253, u'670': 7246, u'671': 7247, u'672': 7248, u'673': 7249, u'263': 6794, u'262': 6793, u'261': 6792, u'260': 6791, u'267': 6798, u'266': 6797, u'265': 6796, u'264': 6795, u'269': 6800, u'268': 6799, u'701': 7281, u'59': 7156, u'58': 7145, u'55': 7112, u'54': 7101, u'57': 7134, u'56': 7123, u'51': 7068, u'50': 7057, u'53': 7090, u'52': 7079, u'537': 7098, u'536': 7097, u'535': 7096, u'534': 7095, u'533': 7094, u'532': 7093, u'531': 7092, u'530': 7091, u'539': 7100, u'538': 7099, u'775': 7362, u'774': 7361, u'777': 7364, u'115': 6630, u'114': 6629, u'117': 6632, u'116': 6631, u'111': 6626, u'110': 6625, u'113': 6628, u'112': 6627, u'771': 7358, u'119': 6634, u'118': 6633, u'770': 7357, u'773': 7360, u'772': 7359, u'953': 7559, u'429': 6978, u'428': 6977, u'919': 7521, u'918': 7520, u'421': 6970, u'420': 6969, u'423': 6972, u'422': 6971, u'425': 6974, u'424': 6973, u'427': 6976, u'426': 6975, u'308': 6844, u'309': 6845, u'300': 6836, u'301': 6837, u'302': 6838, u'303': 6839, u'304': 6840, u'305': 6841, u'306': 6842, u'307': 6843, u'895': 7494, u'825': 7418, u'824': 7417, u'827': 7420, u'847': 7442, u'846': 7441, u'845': 7440, u'826': 7419, u'843': 7438, u'842': 7437, u'841': 7436, u'840': 7435, u'821': 7414, u'853': 7449, u'849': 7444, u'820': 7413, u'823': 7416, u'822': 7415, u'954': 7560, u'568': 7132, u'569': 7133, u'751': 7336, u'750': 7335, u'757': 7342, u'737': 7320, u'755': 7340, u'754': 7339, u'560': 7124, u'561': 7125, u'562': 7126, u'563': 7127, u'564': 7128, u'565': 7129, u'566': 7130, u'567': 7131, u'739': 7322, u'229': 6756, u'228': 6755, u'227': 6754, u'226': 6753, u'225': 6752, u'224': 6751, u'223': 6750, u'222': 6749, u'221': 6748, u'220': 6747, u'88': 7477, u'726': 7308, u'727': 7309, u'724': 7306, u'725': 7307, u'722': 7304, u'723': 7305, u'720': 7302, u'721': 7303, u'728': 7310, u'729': 7311, u'151': 6670, u'150': 6669, u'153': 6672, u'152': 6671, u'155': 6674, u'154': 6673, u'157': 6676, u'156': 6675, u'159': 6678, u'158': 6677, u'609': 7178, u'608': 7177, u'976': 7584, u'634': 7206, u'80': 7390, u'635': 7207, u'749': 7333, u'958': 7564, u'81': 7401, u'48': 7034, u'49': 7045, u'46': 7012, u'47': 7023, u'44': 6990, u'45': 7001, u'42': 6968, u'43': 6979, u'40': 6946, u'41': 6957, u'638': 7210, u'5': 7056, u'639': 7211, u'489': 7044, u'488': 7043, u'487': 7042, u'486': 7041, u'485': 7040, u'484': 7039, u'483': 7038, u'482': 7037, u'481': 7036, u'480': 7035, u'955': 7561, u'472': 7026, u'473': 7027, u'470': 7024, u'471': 7025, u'476': 7030, u'477': 7031, u'474': 7028, u'475': 7029, u'478': 7032, u'479': 7033} - -#### Odstranění duplicit z Problem #### - -`AZAD:*` - - for i in Problem.objects.filter(import_dakos_id__contains='AZAD'): - p = Problem.objects.filter(kod=i.kod, cislo_zadani=i.cislo_zadani, typ=i.typ); - q = [j for j in p if j.import_dakos_id[:2] != 'AZ'] - if q: - print i.nazev==j.nazev, i.nazev, j.nazev - - - -### Konkrétní programy pro data (starší metoda) ### - -Používají ovvpfile pro načtení souborů. - -#### DAKOS ID pro nektere skoly #### - - for i in sk[1:]: - f = Skola.objects.filter(nazev=i['NAZEV'], izo=i['IZO']); - if len(f)==1: - f[0].dakos_id = i['ID']; f[0].save() - - -#### Resitel #### - - for i in ts['BW-resitelia-export']: - Resitel.objects.create(jmeno=i['jmeno'], prijmeni=i['prijmeni'], pohlavi_muz=(i['pohlavi']==u'mu\u017e'), - rok_maturity=int(i['rok_maturity']), email=i['email'], telefon=i['telefon'], zasilat=Resitel.ZASILAT_DOMU, - ulice=i['ulica']+' '+i['cislo'], mesto=i['obec'], psc=i['psc'], stat=i['stat'], dakos_id=i['rid'], - poznamka="{'skola': '%s', 'dakos_skola_id': '%s'}\n" % (i['skola'], i['dakos_skola_id'], )) - -Doplneni nekterych skol: - - ae = ts['Aesop-MaM-export-2014-10-20-mod'] - skoly = ts['Aesop-skoly-export-2015-05-14-mod'] - for i in ae: - r = Resitel.objects.get(jmeno=i['name'], prijmeni=i['surname']); - izo = i['school'].lstrip('izo:'); - aesop_id = [s for s in skoly if izo in repr(s)][0]['id-aesop']; - sch = Skola.objects.get(aesop_id='aesop:'+aesop_id); - r.skola=sch; r.save() - -#### Cisla #### - -Hlavne ze souboru `archiv/seznam.csv` -Navic nejaka data z DB, ale nic moc - - for i in ts['BW-archiv-cisla-copy-mod']: Cislo.objects.create(rocnik=Rocnik.objects.get(rocnik=int(i['rocnik'])), cislo=i['cislo']) - -#### Uzivatele #### - - for i in ts['MAMOPER.MM_PASSWD']: - if not User.objects.filter(username=i['LOGIN']): User.objects.create_user(i['LOGIN']) - -#### Problemy #### - -`MM_ZADANIA`: - - typtable={'1': Problem.TYP_ULOHA, '2':Problem.TYP_TEMA, '3':Problem.TYP_SERIAL} - for i in ts['MAMOPER.MM_ZADANIA']: - print i - c = Cislo.objects.get(cislo=i['CISLO'] if i['CISLO']!='9' else '1', rocnik__rocnik=int(i['ROCNIK'])) - opravovatel = User.objects.get(username=i['OPRAVUJE']) if i['OPRAVUJE'] else None - Problem.objects.create(nazev=i['NAZOV'], typ=typtable[i['TYP']], stav=Problem.STAV_ZADANY, opravovatel=opravovatel, - kod=i['ULOHA'], cislo_zadani=c, body=int(i['MAX_BODY']) if i['MAX_BODY'] else None, - dakos_id='ZAD:%s.%s.%s.%s'%(i['ROCNIK'], i['CISLO'], i['ULOHA'], i['TYP'],)) - -`MM_DOZ`: -Dekodovani stavu navrhu (MFIO - oblast, Tema, Konfera, Pouzita, Zamitnuta, Doplnit (?)) - - def dectag(x): return ["MFIOTKPZD"[bi] for bi in range(0, 9) if (int(x) & (1 << bi))] - from django.utils.html import escape - def transdate(s): - if '.' not in s: return None - d,m,r = s.split('.'); return datetime.date(int(r)+2000, int(m), int(d)) - for i in ts['MAMOPER.MM_DOZ']: - print i; - tags=dectag(i['ZARADENIE']); - autor = User.objects.get(username=i['ORG']) if i['ORG'] else None; - Problem.objects.create(nazev=i['NAZOV'], typ=Problem.TYP_TEMA if 'T' in tags else Problem.TYP_ULOHA, - stav=Problem.STAV_ZADANY if 'P' in tags else (Problem.STAV_SMAZANY if 'Z' in tags else Problem.STAV_NAVRH), - dakos_id='DOZ:%s'%(i['ID'], ), text_problemu_org=escape(i['ZADANIE']), timestamp=transdate(i['CAS'])) - -`MM_AZAD`: - - def romdec(rom): - if not rom: return 0 - if rom[0] == 'X': return 10 + romdec(rom[1:]) - if rom[-1] == 'X': return 10 - romdec(rom[:-1]) - if rom[0] == 'V': return 5 + romdec(rom[1:]) - if rom[-1] == 'V': return 5 - romdec(rom[:-1]) - if rom[0] == 'I': return 1 + romdec(rom[1:]) - assert False - for i in ts['MAMOPER.MM_AZAD'][1:]: - print i; - tags=dectag(i['ZAMERANIE']); - r = romdec(i['ROC_Z']); - c1 = Cislo.objects.filter(rocnik__rocnik=r, cislo=i['CIS_Z']); - c1 = c1[0] if len(c1) else None; - c2 = Cislo.objects.filter(rocnik__rocnik=r, cislo=i['CIS_V']); - c2 = c2[0] if len(c2) else None; - Problem.objects.create(nazev=i['NAZOV'], typ=Problem.TYP_TEMA if 'T' in tags else Problem.TYP_ULOHA, stav=Problem.STAV_ZADANY, - kod=i['ZADANIE'][1:], cislo_zadani=c1, cislo_reseni=c2, dakos_id='AZAD:%s'%(i['ID'], ), - text_problemu_org=escape(u'Abstrakt:\n'+i['ABSTRAKT'])) - for i in ts['MAMOPER.MM_AZAD'][1:]: - print i; tags=dectag(i['ZAMERANIE']); p = Problem.objects.get(dakos_id='AZAD:%s'%(i['ID'], )); - [p.zamereni.add(t) for t in tags if t in 'MFIO']; p.save() - -#### Reseni #### - -`MM_RIESENIA`: - - for i in ts['MAMOPER.MM_RIESENIA']: - tstp = datetime.datetime.fromtimestamp(int(i['DORUCENA'])); - print i, tstp; - r = Resitel.objects.get(dakos_id=i['RIESITEL']); - u = Problem.objects.get(dakos_id="ZAD:%s.%s.%s.%s" % (i['ROCNIK'], i['CISLO'], i['ULOHA'], i['TYP'],)); - Reseni.objects.create(problem=u, resitel=r, body=int(i['POCET_BODOV'] or '0'), - poznamka='Zdroj: MM_RIESENIA\nForma: %s\n%s' % ({'1':'E', '2':'P'}[i['FORMA']], i['POZNAMKA'], ), timestamp=tstp) - - - - diff --git a/dakosdump/helpers.py b/dakosdump/helpers.py deleted file mode 100644 index 05002cbf..00000000 --- a/dakosdump/helpers.py +++ /dev/null @@ -1,65 +0,0 @@ -import os -import datetime -import sqlite3 - -from django.utils.html import escape - -from seminar import ovvpfile -from seminar.models import Problem -from seminar.utils import roman, from_roman - - -# MM_ZADANIA.TYP -typtable={'1': Problem.TYP_ULOHA, '2':Problem.TYP_TEMA, '3':Problem.TYP_SERIAL} - -# MM_DOZ.ZARADENIE, MM_AZAD.ZAMERANIE -def dectag(x): - return ["MFIOTKPZD"[bi] for bi in range(0, 9) if (int(x) & (1 << bi))] - -# Datum z formatu "DD.MM.YY" -def transdate(s): - if '.' not in s: return None - d,m,r = map(int, s.split('.')) - return datetime.date(r + 2000 if r < 30 else r + 1900, m, d) - -class SQLiteRow(object): - def __unicode__(self): - return self.__dict__.__unicode__() - def __str__(self): - return self.__dict__.__str__() - def __repr__(self): - return self.__dict__.__str__() - -# sqlite3 helper -def sqget(db, sql, limit=None): - c = db.execute(sql) - rows = c.fetchmany(limit) if limit else c.fetchall() - res = [] - for row in rows: - o = SQLiteRow() - for coli in range(len(c.description)): - col = c.description[coli] - o.__setattr__(col[0], row[coli]) - res.append(o) - return res - -## ovvpfile - based import helpers (old) - -def read_all_tables(basedir): - tables = {} - for fn in os.listdir(basedir): - if fn.endswith('.csv'): - print "Reading %s ..." % (fn, ) - with open(os.path.join(basedir, fn), 'r') as f: - o = ovvpfile.parse(f, with_headers=False) - tables[fn[:-4]] = o.rows - print " %d lines, columns: %s" % (len(o.rows), ' '.join(o.columns), ) - return tables - -def matchrows(tab, key, val): - return [r for r in tab if r[key]==val] - -def onerow(tab, key, val): - t = matchrows(tab, key, val) - assert(len(t) == 1) - return t[0] diff --git a/dakosdump/oracle_dump b/dakosdump/oracle_dump deleted file mode 100644 index 9653539f..00000000 --- a/dakosdump/oracle_dump +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/perl - -# RUN AS: -# -# ORACLE_HOME=/nfs/nikam/sw/oracle-10.2/ora_home_10.2/ LC_ALL=C AESOP_PASSWD= perl oracle_dump -# - -use strict; -use warnings; -use utf8; - -use lib '/nfs/nikam/sw/oracle-10.2/perl/lib/perl'; -use DBI; -use DBD::Oracle qw(:ora_types); -$ENV{'NLS_LANG'}='CZECH.UTF8'; - - -my $pass = $ENV{'AESOP_PASSWD'} // die "You must set AESOP_PASSWD\n"; -my $dbh = DBI->connect('dbi:Oracle:host=mffout.karlov.mff.cuni.cz;service_name=mffout.karlov.mff.cuni.cz;port=1521', - 'mamoper', $pass, {ora_connect_with_default_signals => [ 'INT' ], 'LongReadLen' => 1000000 }) or die; - -$, = "\t"; -$\ = "\n"; -my $dump_directory = "oracle_dks_dump"; -mkdir $dump_directory unless -d $dump_directory; - -sub dump_table($){ - my $name = shift; - print $name; - my $filename = $dump_directory."/".$name.".csv"; - open(my $fh, ">:encoding(UTF-8)", $filename); - select $fh; - my $query = $dbh->prepare("SELECT * FROM $name"); - $query->execute; - print @{$query->{NAME}}; - print @{$query->{TYPE}}; - while (my @row = $query->fetchrow_array()) { - $_//='' for @row; - s/\t/\\t/g for @row; - s/\n/\\n/g for @row; - print @row; - } - select STDOUT; - close $fh; -} - -# my $query = $dbh->prepare("SELECT table_name, TABLESPACE_NAME FROM all_tables WHERE owner='MAMOPER'"); -my $query = $dbh->prepare("SELECT table_name, owner FROM all_tables"); -$query->execute; -while (my @row = $query->fetchrow_array()) { - if (!( $row[1] eq 'SYS')) { - dump_table "$row[1].$row[0]"; - } -} diff --git a/Schema_new.dia b/deploy_v2/Schema_new.dia similarity index 100% rename from Schema_new.dia rename to deploy_v2/Schema_new.dia diff --git a/admin_org_prava.json b/deploy_v2/admin_org_prava.json similarity index 100% rename from admin_org_prava.json rename to deploy_v2/admin_org_prava.json diff --git a/db_compare.py b/deploy_v2/db_compare.py old mode 100755 new mode 100644 similarity index 100% rename from db_compare.py rename to deploy_v2/db_compare.py diff --git a/init_local.sh b/init_local.sh deleted file mode 100755 index ab373c38..00000000 --- a/init_local.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -set -e # Spadni pokud něco spadne - -# Check venvu -# NOTE: zkontroluje i správnou složku -- existencí Makefilu -make venv_check - -# Vygenerujeme testdata -./manage.py testdata - -# Nahrajeme statický obsah modelů -./manage.py loaddata flat.json sitetree_new.json - -# Posbíráme statické soubory -./manage.py collectstatic diff --git a/mamweb/settings_common.py b/mamweb/settings_common.py index f4e9ac89..3c850245 100644 --- a/mamweb/settings_common.py +++ b/mamweb/settings_common.py @@ -135,6 +135,9 @@ INSTALLED_APPS = ( 'prednasky', 'header_fotky', 'various', + 'various.autentizace', + 'api', + 'aesop', # Admin upravy: diff --git a/mamweb/urls.py b/mamweb/urls.py index 2f5aeea9..2fdbff45 100644 --- a/mamweb/urls.py +++ b/mamweb/urls.py @@ -23,6 +23,15 @@ urlpatterns = [ # Prednaskova aplikace (ma vlastni podadresare) path('', include('prednasky.urls')), + # Autentizační aplikace (ma vlastni podadresare) + path('', include('various.autentizace.urls')), + + # Api (ma vlastni podadresare) (autocomplete apod.) + path('', include('api.urls')), + + # Aesop (ma vlastni podadresare) + path('', include('aesop.urls')), + # Comments (interni i verejne) path('comments_dj/', include('django_comments.urls')), path('comments_fl/', include('fluent_comments.urls')), diff --git a/seminar/admin.py b/seminar/admin.py index cdfcb413..3ee14541 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -10,9 +10,7 @@ from django_reverse_admin import ReverseModelAdmin from solo.admin import SingletonModelAdmin from django.utils.safestring import mark_safe -from seminar.views.vysledkovka import hlavni_problem -# TODO Přesunout do utils - +from seminar.utils import hlavni_problem # Todo: reversion diff --git a/seminar/forms.py b/seminar/forms.py index cfc013ec..19ed8d9f 100644 --- a/seminar/forms.py +++ b/seminar/forms.py @@ -27,16 +27,6 @@ class TelInput(forms.TextInput): input_type = 'tel' input_pattern="^[+]?[()/0-9. -]{9,}$" -class LoginForm(forms.Form): - username = forms.CharField(label='Přihlašovací jméno', - max_length=256, - required=True) - password = forms.CharField( - label='Heslo', - max_length=256, - required=True, - widget=forms.PasswordInput()) - class PrihlaskaForm(PasswordResetForm): username = forms.CharField(label='Přihlašovací jméno', diff --git a/seminar/management/commands/importschools.py b/seminar/management/commands/importschools.py deleted file mode 100644 index ef761179..00000000 --- a/seminar/management/commands/importschools.py +++ /dev/null @@ -1,125 +0,0 @@ -# -*- coding: utf-8 -*- - -import datetime -import os -import random -#import argparse -from optparse import make_option - - -from django.core.management.base import BaseCommand -from django.core.management import call_command -from django.conf import settings -from django.db import transaction -import django.contrib.auth -from django.utils.encoding import force_unicode - -from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni -from seminar.testutils import create_test_data -from seminar import ovvpfile - -User = django.contrib.auth.get_user_model() - - -class Command(BaseCommand): - help = "Import (add / notice changes) schools from a ovvp-format file (skoly.csv)" - - option_list = BaseCommand.option_list + ( - make_option('-n', '--dry_run', dest='dry_run', default=False, - action='store_true', help="No changes to DB."), - ) -# def add_arguments(self, parser): -# parser.add_argument('file', nargs='?', type=argparse.FileType('r', encoding='utf8'), default=sys.stdin) -# parser.add_argument('-n', '--dry_run', dest='dry_run', default=False, -# action='store_true', type=bool, help="No changes to DB.") - - def school_diffs(self, ovvpskola, dbskola): - def compare(ovvpcol, dbcol, t=unicode): - v1 = t(dbskola.__getattribute__(dbcol)) - v2 = ovvpskola[ovvpcol] - if unicode(v1) != unicode(v2): - return "%s: '%s'->'%s', " % (ovvpcol, v1, v2, ) - return "" - - diff = "" - diff += compare('name','nazev') - diff += compare('street','ulice') - diff += compare('town','mesto') - diff += compare('postcode','psc') - return diff - - def handle(self, *args, **options): - assert len(args) == 1 - - filename = args[0] - self.stdout.write( - 'Parsing OVVP/OPMK-format file \'%s\' ...' % (filename, ) - ) - with open(filename, "r") as f: - o = ovvpfile.parse(f) - - assert o.headers['version'] == '1' - self.stdout.write('Read %d schools with columns: %s' % (len(o.rows), o.columns, )) - self.stdout.write('Export created: %s' % (o.headers.get('date', 'N/A'), )) - assert 'id-aesop' in o.columns - - same = 0 - modified = 0 - new = 0 - - with transaction.atomic(): - for skola in o.rows: - aesop_id = 'aesop:%s' % (skola['id-aesop'], ) - found = Skola.objects.filter(aesop_id=aesop_id) - assert len(found) <= 1 - - if found: - fs = found[0] - diff = self.school_diffs(skola, fs) - if diff: - modified += 1 - self.stdout.write(u"M %11s %s" % (aesop_id, diff, )) # TODO - else: - same += 1 - if int(skola['is-SS']) > int(fs.je_ss): - fs.je_ss = True - fs.save() - - if int(skola['is-ZS']) > int(fs.je_zs): - fs.je_zs = True - fs.save() - - else: - new += 1 - # Name duplicates? - by_name = Skola.objects.filter(nazev=skola['name'], mesto=skola['town'], ulice=skola['street']) - if len(by_name) > 0: - self.stdout.write(u"W Same [name, street, town] for %s and %s (%s, %s, %s)" % ( - by_name[0].aesop_id, aesop_id, skola['name'], skola['street'], skola['town'], )) - else: - self.stdout.write(u"+ %11s %s, %s, %s" % (aesop_id, skola['name'], skola['town'], skola['country'], )) - if not options['dry_run']: - newskola = Skola.objects.create( - aesop_id=aesop_id, nazev=skola['name'], kratky_nazev=skola['name'], izo=skola.get('id-izo', ''), - ulice=skola['street'], mesto=skola['town'], psc=skola['postcode'], stat=skola['country'], - je_zs=int(skola['is-ZS']), je_ss=int(skola['is-SS']), - ) - - self.stdout.write("Result: %d same, %d different, %d new schools" % (same, modified, new, )) - - - - - - - - - - - - - - - - - diff --git a/seminar/models.py b/seminar/models.py index c9e44885..d4c3ad81 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -1720,83 +1720,6 @@ class ReseniNode(TreeNode): def getOdkazStr(self): return str(self.reseni) -## FIXME: Logiku přesunout do views. -#class VysledkyBase(SeminarModelBase): -# -# class Meta: -# verbose_name = 'Řádek výsledkovky' -# verbose_name_plural = 'Řádky výsledkovky' -# ordering = ['body'] -# abstract = True -# managed = False -# -# dummy_id = models.CharField('dummy ID pro view', max_length=32, primary_key=True, -# db_column='id') -# -# cislo = models.ForeignKey(Cislo, verbose_name='číslo pro body', db_column='cislo_id', -# on_delete=models.DO_NOTHING) -# -# resitel = models.ForeignKey(Resitel, verbose_name='řešitel', db_column='resitel_id', -# on_delete=models.DO_NOTHING) -# -# body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body', -# verbose_name='body za číslo') -# -# def __str__(self): -# return "%s: %sb (%s)".format(self.resitel.plne_jmeno(), self.body, -# str(self.poradi)) -# # NOTE: DB zatez pri vypisu (ale nepouzivany) - - -## FIXME: Logiku přesunout do views. -#class VysledkyZaCislo(VysledkyBase): -# -# class Meta: -# db_table = 'seminar_body_za_cislo' -# abstract = False -# managed = False -# -# -## FIXME: Logiku přesunout do views. -#class VysledkyKCisluZaRocnik(VysledkyBase): -# -# class Meta: -# db_table = 'seminar_body_k_cislu_rocnik' -# abstract = False -# managed = False -# -## body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body', -## verbose_name='body do čísla (za ročník)') -# -# -## FIXME: Logiku přesunout do views. -#class VysledkyKCisluOdjakziva(VysledkyBase): -# -# class Meta: -# db_table = 'seminar_body_k_cislu_odjakziva' -# abstract = False -# managed = False -# -## body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body', -## verbose_name='body do čísla (i minulé ročníky)') -# -# -## FIXME: Logiku přesunout do views. -#class VysledkyCelkemKCislu(VysledkyBase): -# -# class Meta: -# db_table = 'seminar_body_celkem_k_cislu' -# abstract = False -# managed = False -# -# body_celkem = models.DecimalField(max_digits=8, decimal_places=1, db_column='body_celkem', -# verbose_name='body celkem do čísla včetně minulých ročníků') -# -# def __str__(self): -# # NOTE: DB HOG (ale nepouzivany) -# return "%s: %sb / %sb (do %s)" % (self.resitel.plne_jmeno(), self.body, self.body_celkem, str(self.poradi)) -##mozna potreba upravit - @reversion.register(ignore_duplicates=True) class Nastaveni(SingletonModel): @@ -1855,35 +1778,3 @@ class Novinky(models.Model): return '[' + str(self.datum) + '] ' + self.text[0:50] else: return '[' + str(self.datum) + '] ' - - - - -# FIXME: Tohle nepatří do aplikace 'seminar' -# Nefunkční alternativa vestavěného Usera, který má jméno a mail v přidružené Osobě -# from django.contrib.auth.models import User as Django_User -# -# class Uzivatel(Django_User): -# class Meta: -# proxy = True -# -# @property -# def first_name(self): -# osoby = Osoba.objects.filter(user=self) -# if len(osoby) == 0: -# return None -# return osoby.first().krestni_jmeno -# -# @property -# def last_name(self): -# osoby = Osoba.objects.filter(user=self) -# if len(osoby) == 0: -# return None -# return osoby.first().prijmeni -# -# @property -# def email(self): -# osoby = Osoba.objects.filter(user=self) -# if len(osoby) == 0: -# return None -# return osoby.first().email diff --git a/seminar/old_tests.py b/seminar/old_tests.py deleted file mode 100644 index a5e74f01..00000000 --- a/seminar/old_tests.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- - -import datetime -import random -import django.contrib.auth -from unittest import TestCase -from django.test import Client -from django.core.urlresolvers import reverse, resolve -from django.core.management import call_command - -from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Soustredeni, Nastaveni -from seminar.testutils import create_test_data -from seminar import ovvpfile -from seminar import utils - -class SeminarBasicTests(TestCase): - def setUp(self): - create_test_data(size=2) - self.client = Client() - - def tearDown(self): - call_command('flush', noinput=True, verbosity=0, interactive=False) - self.cleint = None - - def test_rocniky(self): - r19 = Rocnik.objects.get(rocnik=21) - self.assertEqual(r19.roman(), 'XXI') - - def test_render_cislo_e2e(self): - cs = Cislo.objects.all() - for c in cs[:4]: - url = c.verejne_url() - r = self.client.get(url) - assert r.status_code == 200 - assert len(r.content) >= 100 - # TODO: Validate cntent as HTML - - def test_render_problem_e2e(self): - ps = Problem.objects.all() - for p in ps[:4]: - url = p.verejne_url() - r = self.client.get(url) - assert r.status_code == 200 - assert len(r.content) >= 100 - # TODO: Validate cntent as HTML - - def test_export_e2e(self): - i_url = '/aesop-export/index.csv' - i_r = self.client.get(i_url) - assert i_r.status_code == 200 - ls = i_r.content.strip().split('\n') - - for u in [ls[0], ls[-1]]: - ex_r = self.client.get('/aesop-export/' + u) - assert ex_r.status_code == 200 - assert len(ex_r.content) >= 100 - o = ovvpfile.parse(ex_r.content) - assert o.headers['version'] == '1' - - def test_admin_url(self): - for m in [Skola, Resitel, Rocnik, Cislo, Problem, Reseni, Nastaveni]: - o = m.objects.first() - url = o.admin_url() - assert url - view = resolve(url) - assert view - - def test_verejne_url(self): - for m in [Rocnik, Cislo, Problem]: - p = Problem.objects.first() - url = p.verejne_url() - assert url - view = resolve(url) - assert view - - def test_ovvpfile(self): - filetext = "H1\ta\nH2\tb\tc\n\nx\ty\tz\n0\t1\t2\n3\t4\t5\n" - o = ovvpfile.parse(filetext) - assert len(o.headers) == 2 - assert o.headers['H2'] == 'b\tc' - - assert o.columns == ['x','y','z'] - assert len(o.rows) == 2 - assert o.rows[0]['z'] == '2' - - t = o.to_string() - assert t == filetext - - def test_roman(self): - for i in [0, 1, 23, 2015, 1999, 42, 4, 400, 78, 4321, 8765, 999]: - r = utils.roman(i) - fr = utils.from_roman(r) - assert fr == i - diff --git a/seminar/old_views.py b/seminar/old_views.py deleted file mode 100644 index f904d137..00000000 --- a/seminar/old_views.py +++ /dev/null @@ -1,71 +0,0 @@ -# Tento soubor slouží k odkládání aktuálně nepotřebného kódu, který by -# se však v budoucnu mohl opět hodit. - -################################################################### - -## Prispevek byl zrusen, mozna ale bude podobny nahled na neco jineho. -#class PrispevekView(generic.DetailView): -# model = Prispevek -# template_name = 'seminar/archiv/prispevek.html' -# -# # Vlastni ziskavani objektu z databaze podle prispevku -# # pokud je prispevek neverejny zobrazi se jenom orgum -# def get_object(self, queryset=None): -# if queryset is None: -# queryset = self.get_queryset() -# problem_arg = self.kwargs.get('pk') -# prispevek_arg = self.kwargs.get('prispevek') -# queryset = queryset.filter(pk=prispevek_arg) -# -# try: -# obj = queryset.get() -# except queryset.model.DoesNotExist: -# raise Http404(_("No %(verbose_name)s found matching the query") % -# {'verbose_name': queryset.model._meta.verbose_name}) -# -# if self.request.user.is_staff or obj.zverejnit: -# return obj -# else: -# raise Http404() -# -# def get_context_data(self, **kwargs): -# context = super(PrispevekView, self).get_context_data(**kwargs) -# # snaho o ziskani titulu -# titul = '' -# try: -# resitel = context['prispevek'].reseni.resitel -# cislo = context['prispevek'].reseni.cislo_body -# body = VysledkyKCisluOdjakziva.objects.get(resitel=resitel, -# cislo=cislo).body -# titul = resitel.get_titul(body) -# except: -# pass -# context['titul'] = titul -# return context - -#################################################################### - -## Stvrzenky aktuálně nevydáváme, ale možná časem zase budeme. -#def soustredeniStvrzenkyExportView(request,soustredeni,first_num): -# first_num = int(first_num) -# soustredeni = get_object_or_404(Soustredeni,id = soustredeni) -# ucastnici = Resitel.objects.filter(soustredeni=soustredeni) -# for (idx,u) in enumerate(ucastnici): -# u.cislo_stvrzenky = first_num+idx; -# tex = render(request,'seminar/soustredeni/ucastnici.tex', {'ucastnici': ucastnici, 'datum':soustredeni.datum_zacatku }).content -# -# tempdir = tempfile.mkdtemp() -# with open(tempdir+"/ucastnici.tex","w") as texfile: -# # Pokud TeX chce ISO Latin, tak se da encode nastavit -# texfile.write(tex.decode("utf-8").encode("utf-8")) -# shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenka.sty'),tempdir) -# shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenky.tex'),tempdir) -# subprocess.call(["cslatex","stvrzenky.tex"],cwd = tempdir) -# subprocess.call(["dvipdf","stvrzenky.dvi"],cwd = tempdir) -# -# with open(tempdir+"/stvrzenky.pdf","rb") as pdffile: -# response = HttpResponse(pdffile.read(),content_type='application/pdf') -# shutil.rmtree(tempdir) -# return response - - diff --git a/seminar/templates/seminar/odevzdavatko/detail.html b/seminar/templates/seminar/odevzdavatko/detail.html index 17be0e0f..04e8c550 100644 --- a/seminar/templates/seminar/odevzdavatko/detail.html +++ b/seminar/templates/seminar/odevzdavatko/detail.html @@ -85,7 +85,7 @@ $(document).ready(function(){

Žádné přílohy

{% endif %} -
+ {# Poznámka #}

Poznámka:

{{ poznamka_form.poznamka }}

@@ -99,12 +99,14 @@ $(document).ready(function(){ {% for subform in form %} + + {% endfor %}
ProblémBodyČíslo pro body
{{ subform.problem }} {{ subform.body }} {{ subform.cislo_body }} Smazat
@@ -121,4 +123,19 @@ $(document).ready(function(){ + + + {% endblock %} diff --git a/seminar/urls.py b/seminar/urls.py index 141453c7..8a6aacf4 100644 --- a/seminar/urls.py +++ b/seminar/urls.py @@ -1,8 +1,7 @@ from django.urls import path, include, re_path from django.contrib.auth.decorators import login_required -from . import views, export +from . import views from .utils import org_required, resitel_required, viewMethodSwitch, resitel_or_org_required -from django.views.generic.base import RedirectView urlpatterns = [ # path('aktualni/temata/', views.TemataRozcestnikView), @@ -68,23 +67,6 @@ urlpatterns = [ path('archiv/clanky/', views.ClankyResitelView.as_view(), name='clanky_resitel'), #path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'), - # Aesop - path( - 'aesop-export/mam-rocnik-.csv', - export.ExportRocnikView.as_view(), - name='seminar_export_rocnik' - ), - path( - 'aesop-export/mam-sous-.csv', - export.ExportSousView.as_view(), - name='seminar_export_sous' - ), - path( - 'aesop-export/index.csv', - export.ExportIndexView.as_view(), - name='seminar_export_index' - ), - # Stranky viditelne pouze pro orgy: path( 'rocnik//vysledkovka.tex', @@ -133,17 +115,9 @@ urlpatterns = [ ), path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'), - path('prihlasit/', views.LoginView.as_view(), name='login'), - path('login/', RedirectView.as_view(pattern_name='login', permanent=True, query_string=True)), - path('odhlasit/', views.LogoutView.as_view(), name='logout'), - path('logout/', RedirectView.as_view(pattern_name='logout', permanent=True, query_string=True)), - path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'), + path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'), - path('reset-hesla/', views.PasswordResetView.as_view(), name='reset_password'), - path('zmena-hesla/', views.PasswordChangeView.as_view(), name='change_password'), - path('reset-hesla/2/', views.PasswordResetDoneView.as_view(), name='reset_password_done'), - path('reset-hesla/potvrzeni///', views.PasswordResetConfirmView.as_view(), name='reset_password_confirm'), - path('reset-hesla/hotovo/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'), + path( 'resitel/osobni-udaje/', login_required(views.resitelEditView), @@ -153,14 +127,6 @@ urlpatterns = [ # Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku path('profil/', views.profilView, name='profil'), - # Autocomplete - path('api/autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'), - path('api/autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'), - path('api/autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'), - - # Export škol - path('api/export/skoly/', views.exportSkolView, name='export_skoly'), - path('org/add_solution', org_required(views.AddSolutionView.as_view()), name='seminar_vloz_reseni'), path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'), @@ -170,11 +136,6 @@ urlpatterns = [ path('', views.TitulniStranaView.as_view(), name='titulni_strana'), path('jak-resit/', views.JakResitView.as_view(), name='jak_resit'), - # Ceka na autocomplete v3 - # path('autocomplete/organizatori/', - # org_member_required(views.OrganizatorAutocomplete.as_view()), - # name='seminar_autocomplete_organizator') - path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'), path('org/reseni/rocnik//', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'), path('org/reseni///', org_required(views.ReseniProblemuView.as_view()), name='odevzdavatko_reseni_resitele_k_problemu'), diff --git a/seminar/views/__init__.py b/seminar/views/__init__.py index f84d99d7..785102e5 100644 --- a/seminar/views/__init__.py +++ b/seminar/views/__init__.py @@ -1,9 +1,6 @@ from .views_all import * -from .autocomplete import * from .views_rest import * from .odevzdavatko import * -from .exports import * - # Dočsasné views from .docasne import * diff --git a/seminar/views/utils.py b/seminar/views/utils.py deleted file mode 100644 index 1fa28827..00000000 --- a/seminar/views/utils.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- - -import datetime -from django.contrib.auth.decorators import user_passes_test -from html.parser import HTMLParser - -import seminar.models as m - -class FirstTagParser(HTMLParser): - def __init__(self, *args, **kwargs): - self.firstTag = None - super().__init__(*args, **kwargs) - def handle_data(self, data): - if self.firstTag == None: - self.firstTag = data - -def histogram(seznam): - d = {} - for i in seznam: - if i not in d: - d[i] = 0 - d[i] += 1 - return d - - -roman_numerals = zip((1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1), - ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')) - -def roman(num): - res = "" - for i, n in roman_numerals: - res += n * (num // i) - num %= i - return res - -def from_roman(rom): - if not rom: - return 0 - for i, n in roman_numerals: - if rom.upper().startswith(n): - return i + from_roman(rom[len(n):]) - raise Exception('Invalid roman numeral: "%s"', rom) - - -def seznam_problemu(): - problemy = [] - - # Pomocna fce k formatovani problemovych hlasek - def prb(cls, msg, objs=None): - s = u'%s: %s' % (cls.__name__, msg) - if objs: - s += u' [' - for o in objs: - try: - url = o.admin_url() - except: - url = None - if url: - s += u'%s, ' % (url, o.pk, ) - else: - s += u'%s, ' % (o.pk, ) - s = s[:-2] + u']' - problemy.append(s) - - # Duplicita jmen - jmena = {} - for r in m.Resitel.objects.all(): - j = r.plne_jmeno() - if j not in jmena: - jmena[j] = [] - jmena[j].append(r) - for j in jmena: - if len(jmena[j]) > 1: - prb(m.Resitel, u'Duplicitní jméno "%s"' % (j, ), jmena[j]) - - # Data maturity a narození - for r in m.Resitel.objects.all(): - if not r.rok_maturity: - prb(m.Resitel, u'Neznámý rok maturity', [r]) - if r.rok_maturity and (r.rok_maturity < 1990 or r.rok_maturity > datetime.date.today().year + 10): - prb(m.Resitel, u'Podezřelé datum maturity', [r]) - if r.datum_narozeni and (r.datum_narozeni.year < 1970 or r.datum_narozeni.year > datetime.date.today().year - 12): - prb(m.Resitel, u'Podezřelé datum narození', [r]) -# if not r.email: -# prb(Resitel, u'Neznámý email', [r]) - - return problemy - - diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index 6b037fcf..56e2aaae 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -1,12 +1,8 @@ -from django.contrib.auth.tokens import PasswordResetTokenGenerator -from django.contrib.sites.shortcuts import get_current_site 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 from django.core.mail import send_mail -from django.utils.encoding import force_bytes -from django.utils.http import urlsafe_base64_encode from django.views import generic from django.utils.translation import ugettext as _ from django.http import Http404,HttpResponseBadRequest,HttpResponseRedirect @@ -15,8 +11,6 @@ from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.debug import sensitive_post_parameters from django.views.generic.edit import FormView, CreateView from django.views.generic.base import TemplateView, RedirectView -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, Permission, Group from django.contrib.auth.mixins import LoginRequiredMixin from django.db import transaction @@ -29,7 +23,7 @@ import seminar.models as m from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek, Osoba, Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci #from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva from seminar import utils, treelib -from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm, PoMaturiteProfileEditForm +from seminar.forms import PrihlaskaForm, ProfileEditForm, PoMaturiteProfileEditForm import seminar.forms as f import seminar.templatetags.treenodes as tnltt import seminar.views.views_rest as vr @@ -54,6 +48,8 @@ import logging import time from seminar.utils import aktivniResitele, resi_v_rocniku, problemy_rocniku, cisla_rocniku, hlavni_problemy_f +from various.autentizace.views import LoginView +from various.autentizace.utils import posli_reset_hesla # ze starého modelu #def verejna_temata(rocnik): @@ -1336,30 +1332,7 @@ def prihlaskaView(request): if diffattrs: err_logger.warning(f'Different fields when matching Řešitel id {r.id} or Osoba id {o.id}: {diffattrs}') - uid = urlsafe_base64_encode(force_bytes(u.pk)) - token = PasswordResetTokenGenerator().make_token(u) - url = "https://%s%s" % ( - str(get_current_site(request)), - str(reverse_lazy("reset_password_confirm", args=[uid, token])) - ) - - u.email_user( - subject="Vítej mezi řešiteli M&M!", - message="""Milý řešiteli, milá řešitelko, - -tvůj e-mail byl právě zaregistrován na mam.matfyz.cz. Heslo si prosím nastav na: %s - -Těšíme se na tvé příspěvky do našeho semináře, -Organizátoři M&M - --- - -Tento e-mail byl vygenerován automaticky, chceš-li nás kontaktovat, napiš nám na adresu mam@matfyz.cz. -""" % url, - # TODO: templates/seminar/registrace a django/contrib/auth/forms.py říkají, jak na to lépe - from_email="registrace@mam.mff.cuni.cz", # FIXME: Chceme to mít radši tady, nebo v nastavení? - ) - + posli_reset_hesla(u, request) return formularOKView(request, text='Na tvůj e-mail jsme právě poslali odkaz pro nastavení hesla.') # if a GET (or any other method) we'll create a blank form @@ -1368,42 +1341,6 @@ Tento e-mail byl vygenerován automaticky, chceš-li nás kontaktovat, napiš n return render(request, 'seminar/profil/prihlaska.html', {'form': form}) -# FIXME: Tohle asi vlastně vůbec nepatří do aplikace 'seminar' -class LoginView(auth_views.LoginView): - # Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL - template_name = 'seminar/profil/login.html' - -class LogoutView(auth_views.LogoutView): - # Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL - template_name = 'seminar/profil/logout.html' - # Pavel: Vůbec nevím, proč to s _lazy funguje, ale bez toho to bylo rozbité. - next_page = reverse_lazy('titulni_strana') - -# Nejsem si jistý, který view co dostává, tak zahazuji všechny POSTy -class PasswordResetView(auth_views.PasswordResetView): - """ Chci resetovat heslo. """ - template_name = 'seminar/registrace/reset_hesla.html' - success_url = reverse_lazy('reset_password_done') - from_email = 'login@mam.mff.cuni.cz' - email_template_name = 'seminar/registrace/password_reset_email.html' - subject_template_name = 'seminar/registrace/password_reset_subject.txt' - -class PasswordResetDoneView(auth_views.PasswordResetDoneView): - """ Poslali jsme e-mail (pokud bylo kam)). """ - template_name = 'seminar/registrace/reset_poslan.html' - -class PasswordResetConfirmView(auth_views.PasswordResetConfirmView): - """ Vymysli si heslo. """ - template_name = 'seminar/registrace/nove_heslo.html' - success_url = reverse_lazy('reset_password_complete') - -class PasswordResetCompleteView(auth_views.PasswordResetCompleteView): - """ Heslo se asi změnilo.""" - template_name = 'seminar/registrace/nove_nastaveno.html' - -class PasswordChangeView(auth_views.PasswordChangeView): - #template_name = 'seminar/password_change.html' - success_url = reverse_lazy('titulni_strana') class VueTestView(generic.TemplateView): template_name = 'seminar/vuetest.html' diff --git a/seminar/views/vysledkovka.py b/seminar/views/vysledkovka.py index e3238efb..182943b0 100644 --- a/seminar/views/vysledkovka.py +++ b/seminar/views/vysledkovka.py @@ -380,7 +380,7 @@ def vysledkovka_cisla(cislo, context=None): ## TODO možná chytřeji vybírat aktivní řešitele # aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají # u alespoň jedné hodnoty něco jiného než NULL - aktivni_resitele = list(aktivniResitele(cislo)) + aktivni_resitele = list(resi_v_rocniku(cislo.rocnik)) # získáme body za číslo hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) diff --git a/various/autentizace/__init__.py b/various/autentizace/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/various/autentizace/models.py b/various/autentizace/models.py new file mode 100644 index 00000000..6b7590f2 --- /dev/null +++ b/various/autentizace/models.py @@ -0,0 +1,27 @@ +# Nefunkční alternativa vestavěného Usera, který má jméno a mail v přidružené Osobě +# from django.contrib.auth.models import User as Django_User +# +# class Uzivatel(Django_User): +# class Meta: +# proxy = True +# +# @property +# def first_name(self): +# osoby = Osoba.objects.filter(user=self) +# if len(osoby) == 0: +# return None +# return osoby.first().krestni_jmeno +# +# @property +# def last_name(self): +# osoby = Osoba.objects.filter(user=self) +# if len(osoby) == 0: +# return None +# return osoby.first().prijmeni +# +# @property +# def email(self): +# osoby = Osoba.objects.filter(user=self) +# if len(osoby) == 0: +# return None +# return osoby.first().email \ No newline at end of file diff --git a/seminar/templates/seminar/profil/login.html b/various/autentizace/templates/autentizace/login.html similarity index 100% rename from seminar/templates/seminar/profil/login.html rename to various/autentizace/templates/autentizace/login.html diff --git a/seminar/templates/seminar/profil/logout.html b/various/autentizace/templates/autentizace/logout.html similarity index 100% rename from seminar/templates/seminar/profil/logout.html rename to various/autentizace/templates/autentizace/logout.html diff --git a/seminar/templates/seminar/registrace/nove_heslo.html b/various/autentizace/templates/autentizace/nove_heslo.html similarity index 100% rename from seminar/templates/seminar/registrace/nove_heslo.html rename to various/autentizace/templates/autentizace/nove_heslo.html diff --git a/seminar/templates/seminar/registrace/nove_nastaveno.html b/various/autentizace/templates/autentizace/nove_nastaveno.html similarity index 100% rename from seminar/templates/seminar/registrace/nove_nastaveno.html rename to various/autentizace/templates/autentizace/nove_nastaveno.html diff --git a/seminar/templates/seminar/registrace/password_reset_email.html b/various/autentizace/templates/autentizace/password_reset_email.html similarity index 100% rename from seminar/templates/seminar/registrace/password_reset_email.html rename to various/autentizace/templates/autentizace/password_reset_email.html diff --git a/seminar/templates/seminar/registrace/password_reset_subject.txt b/various/autentizace/templates/autentizace/password_reset_subject.txt similarity index 100% rename from seminar/templates/seminar/registrace/password_reset_subject.txt rename to various/autentizace/templates/autentizace/password_reset_subject.txt diff --git a/seminar/templates/seminar/registrace/reset_hesla.html b/various/autentizace/templates/autentizace/reset_hesla.html similarity index 100% rename from seminar/templates/seminar/registrace/reset_hesla.html rename to various/autentizace/templates/autentizace/reset_hesla.html diff --git a/seminar/templates/seminar/registrace/reset_poslan.html b/various/autentizace/templates/autentizace/reset_poslan.html similarity index 100% rename from seminar/templates/seminar/registrace/reset_poslan.html rename to various/autentizace/templates/autentizace/reset_poslan.html diff --git a/various/autentizace/urls.py b/various/autentizace/urls.py new file mode 100644 index 00000000..83c8e50e --- /dev/null +++ b/various/autentizace/urls.py @@ -0,0 +1,15 @@ +from django.urls import path +from . import views +from django.views.generic.base import RedirectView + +urlpatterns = [ + path('prihlasit/', views.LoginView.as_view(), name='login'), + path('login/', RedirectView.as_view(pattern_name='login', permanent=True, query_string=True)), + path('odhlasit/', views.LogoutView.as_view(), name='logout'), + path('logout/', RedirectView.as_view(pattern_name='logout', permanent=True, query_string=True)), + path('reset-hesla/', views.PasswordResetView.as_view(), name='reset_password'), + path('zmena-hesla/', views.PasswordChangeView.as_view(), name='change_password'), + path('reset-hesla/2/', views.PasswordResetDoneView.as_view(), name='reset_password_done'), + path('reset-hesla/potvrzeni///', views.PasswordResetConfirmView.as_view(), name='reset_password_confirm'), + path('reset-hesla/hotovo/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'), +] diff --git a/various/autentizace/utils.py b/various/autentizace/utils.py new file mode 100644 index 00000000..2341fbdd --- /dev/null +++ b/various/autentizace/utils.py @@ -0,0 +1,31 @@ +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.contrib.sites.shortcuts import get_current_site +from django.urls import reverse_lazy +from django.utils.encoding import force_bytes +from django.utils.http import urlsafe_base64_encode + + +def posli_reset_hesla(u, request=None): + uid = urlsafe_base64_encode(force_bytes(u.pk)) + token = PasswordResetTokenGenerator().make_token(u) + url = "https://%s%s" % ( + str(get_current_site(request)), + str(reverse_lazy("reset_password_confirm", args=[uid, token])) + ) + + u.email_user( + subject="Vítej mezi řešiteli M&M!", + message="""Milý řešiteli, milá řešitelko, + +tvůj e-mail byl právě zaregistrován na mam.matfyz.cz. Heslo si prosím nastav na: %s + +Těšíme se na tvé příspěvky do našeho semináře, +Organizátoři M&M + +-- + +Tento e-mail byl vygenerován automaticky, chceš-li nás kontaktovat, napiš nám na adresu mam@matfyz.cz. +""" % url, + # TODO: templates/autentizace a django/contrib/auth/forms.py říkají, jak na to lépe + from_email="registrace@mam.mff.cuni.cz", # FIXME: Chceme to mít radši tady, nebo v nastavení? + ) \ No newline at end of file diff --git a/various/autentizace/views.py b/various/autentizace/views.py new file mode 100644 index 00000000..85ed3528 --- /dev/null +++ b/various/autentizace/views.py @@ -0,0 +1,45 @@ +from django.urls import reverse_lazy +from django.contrib.auth import views as auth_views + + +class LoginView(auth_views.LoginView): + # Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL + template_name = 'autentizace/login.html' + + +class LogoutView(auth_views.LogoutView): + # Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL + template_name = 'autentizace/logout.html' + # Pavel: Vůbec nevím, proč to s _lazy funguje, ale bez toho to bylo rozbité. + next_page = reverse_lazy('titulni_strana') + + +# Nejsem si jistý, který view co dostává, tak zahazuji všechny POSTy +class PasswordResetView(auth_views.PasswordResetView): + """ Chci resetovat heslo. """ + template_name = 'autentizace/reset_hesla.html' + success_url = reverse_lazy('reset_password_done') + from_email = 'login@mam.mff.cuni.cz' + email_template_name = 'autentizace/password_reset_email.html' + subject_template_name = 'autentizace/password_reset_subject.txt' + + +class PasswordResetDoneView(auth_views.PasswordResetDoneView): + """ Poslali jsme e-mail (pokud bylo kam)). """ + template_name = 'autentizace/reset_poslan.html' + + +class PasswordResetConfirmView(auth_views.PasswordResetConfirmView): + """ Vymysli si heslo. """ + template_name = 'autentizace/nove_heslo.html' + success_url = reverse_lazy('reset_password_complete') + + +class PasswordResetCompleteView(auth_views.PasswordResetCompleteView): + """ Heslo se asi změnilo.""" + template_name = 'autentizace/nove_nastaveno.html' + + +class PasswordChangeView(auth_views.PasswordChangeView): + # template_name = 'seminar/password_change.html' + success_url = reverse_lazy('titulni_strana')