Browse Source

Merge branch 'develop' into test

middleware_test
Jonas Havelka 3 years ago
parent
commit
b7463638a5
  1. 187
      MIGRATIONS
  2. 3
      aesop/__init__.py
  3. 5
      aesop/apps.py
  4. 0
      aesop/migrations/__init__.py
  5. 0
      aesop/ovvpfile.py
  6. 20
      aesop/urls.py
  7. 16
      aesop/utils.py
  8. 21
      aesop/views.py
  9. 3
      api/__init__.py
  10. 5
      api/apps.py
  11. 0
      api/migrations/__init__.py
  12. 1
      api/tests/__init__.py
  13. 0
      api/tests/test_skola_autocomplete.py
  14. 19
      api/urls.py
  15. 2
      api/views/__init__.py
  16. 14
      api/views/autocomplete.py
  17. 0
      api/views/exports.py
  18. 3
      api/views/helpers.py
  19. 308
      dakosdump/README.md
  20. 65
      dakosdump/helpers.py
  21. 54
      dakosdump/oracle_dump
  22. 0
      deploy_v2/Schema_new.dia
  23. 0
      deploy_v2/admin_org_prava.json
  24. 0
      deploy_v2/db_compare.py
  25. 16
      init_local.sh
  26. 3
      mamweb/settings_common.py
  27. 9
      mamweb/urls.py
  28. 4
      seminar/admin.py
  29. 10
      seminar/forms.py
  30. 125
      seminar/management/commands/importschools.py
  31. 109
      seminar/models.py
  32. 94
      seminar/old_tests.py
  33. 71
      seminar/old_views.py
  34. 19
      seminar/templates/seminar/odevzdavatko/detail.html
  35. 45
      seminar/urls.py
  36. 3
      seminar/views/__init__.py
  37. 89
      seminar/views/utils.py
  38. 71
      seminar/views/views_all.py
  39. 2
      seminar/views/vysledkovka.py
  40. 0
      various/autentizace/__init__.py
  41. 27
      various/autentizace/models.py
  42. 0
      various/autentizace/templates/autentizace/login.html
  43. 0
      various/autentizace/templates/autentizace/logout.html
  44. 0
      various/autentizace/templates/autentizace/nove_heslo.html
  45. 0
      various/autentizace/templates/autentizace/nove_nastaveno.html
  46. 0
      various/autentizace/templates/autentizace/password_reset_email.html
  47. 0
      various/autentizace/templates/autentizace/password_reset_subject.txt
  48. 0
      various/autentizace/templates/autentizace/reset_hesla.html
  49. 0
      various/autentizace/templates/autentizace/reset_poslan.html
  50. 15
      various/autentizace/urls.py
  51. 31
      various/autentizace/utils.py
  52. 45
      various/autentizace/views.py

187
MIGRATIONS

@ -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

3
aesop/__init__.py

@ -0,0 +1,3 @@
"""
Obsahuje vše, co se týká aesopu (exportu, který po nás vyžaduje OPMK).
"""

5
aesop/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class AesopConfig(AppConfig):
name = 'aesop'

0
dakosdump/__init__.py → aesop/migrations/__init__.py

0
seminar/ovvpfile.py → aesop/ovvpfile.py

20
aesop/urls.py

@ -0,0 +1,20 @@
from django.urls import path
from aesop import views
urlpatterns = [
path(
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
views.ExportRocnikView.as_view(),
name='seminar_export_rocnik'
),
path(
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
views.ExportSousView.as_view(),
name='seminar_export_sous'
),
path(
'aesop-export/index.csv',
views.ExportIndexView.as_view(),
name='seminar_export_index'
),
]

16
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

21
seminar/export.py → 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):

3
api/__init__.py

@ -0,0 +1,3 @@
"""
Obsahuje api = autocomplete + export škol.
"""

5
api/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ApiConfig(AppConfig):
name = 'api'

0
api/migrations/__init__.py

1
api/tests/__init__.py

@ -0,0 +1 @@
from .test_skola_autocomplete import *

0
seminar/test_skola_autocomplete.py → api/tests/test_skola_autocomplete.py

19
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')
]

2
api/views/__init__.py

@ -0,0 +1,2 @@
from .autocomplete import *
from .exports import *

14
seminar/views/autocomplete.py → 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

0
seminar/views/exports.py → api/views/exports.py

3
seminar/views/helpers.py → 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):

308
dakosdump/README.md

File diff suppressed because one or more lines are too long

65
dakosdump/helpers.py

@ -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]

54
dakosdump/oracle_dump

@ -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=<password-of-MAMOPER> 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]";
}
}

0
Schema_new.dia → deploy_v2/Schema_new.dia

0
admin_org_prava.json → deploy_v2/admin_org_prava.json

0
db_compare.py → deploy_v2/db_compare.py

16
init_local.sh

@ -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

3
mamweb/settings_common.py

@ -135,6 +135,9 @@ INSTALLED_APPS = (
'prednasky',
'header_fotky',
'various',
'various.autentizace',
'api',
'aesop',
# Admin upravy:

9
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')),

4
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

10
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',

125
seminar/management/commands/importschools.py

@ -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, ))

109
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

94
seminar/old_tests.py

@ -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

71
seminar/old_views.py

@ -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

19
seminar/templates/seminar/odevzdavatko/detail.html

@ -85,7 +85,7 @@ $(document).ready(function(){
<p>Žádné přílohy</p>
{% endif %}
<form method=post>
<form method=post onsubmit="return zkontroluj_hodnoceni();">
{# Poznámka #}
<h3>Poznámka:</h3>
<p>{{ poznamka_form.poznamka }}</p>
@ -99,12 +99,14 @@ $(document).ready(function(){
<table id="form_set">
<tr><th>Problém</th><th>Body</th><th>Číslo pro body</th></tr>
{% for subform in form %}
<tbody>
<tr class="hodnoceni">
<td>{{ subform.problem }}</td>
<td>{{ subform.body }}</td>
<td>{{ subform.cislo_body }}</td>
<td><a href="#" class="smazat_hodnoceni" id="id_{{subform.prefix}}-jsremove"><img src="{% static "seminar/cross.png" %}" alt="Smazat"></a></td>
</tr>
</tbody>
{% endfor %}
</table>
@ -121,4 +123,19 @@ $(document).ready(function(){
</tr>
</table>
<script type="text/javascript">
function zkontroluj_hodnoceni() {
const pocet = document.getElementById("form_set").childElementCount;
if (pocet === 1) { {# vydím pouze plusko #}
const vysledek = confirm("Odstranil jsi všechny problémy tohoto řešení. Nepůjde tedy dohledat přes problémy, co řeší, tj. například v došlých řešeních. Přesto odeslat?");
if (!vysledek) {
event.preventDefault();
return false;
}
}
return true;
}
</script>
{% endblock %}

45
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-<int:prvni_rok>.csv',
export.ExportRocnikView.as_view(),
name='seminar_export_rocnik'
),
path(
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
export.ExportSousView.as_view(),
name='seminar_export_sous'
),
path(
'aesop-export/index.csv',
export.ExportIndexView.as_view(),
name='seminar_export_index'
),
# Stranky viditelne pouze pro orgy:
path(
'rocnik/<int: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/<uidb64>/<token>/', 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/<int:rocnik>/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
path('org/reseni/<int:problem>/<int:resitel>/', org_required(views.ReseniProblemuView.as_view()), name='odevzdavatko_reseni_resitele_k_problemu'),

3
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 *

89
seminar/views/utils.py

@ -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'<b>%s:</b> %s' % (cls.__name__, msg)
if objs:
s += u' ['
for o in objs:
try:
url = o.admin_url()
except:
url = None
if url:
s += u'<a href="%s">%s</a>, ' % (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

71
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'

2
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)

0
various/autentizace/__init__.py

27
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

0
seminar/templates/seminar/profil/login.html → various/autentizace/templates/autentizace/login.html

0
seminar/templates/seminar/profil/logout.html → various/autentizace/templates/autentizace/logout.html

0
seminar/templates/seminar/registrace/nove_heslo.html → various/autentizace/templates/autentizace/nove_heslo.html

0
seminar/templates/seminar/registrace/nove_nastaveno.html → various/autentizace/templates/autentizace/nove_nastaveno.html

0
seminar/templates/seminar/registrace/password_reset_email.html → various/autentizace/templates/autentizace/password_reset_email.html

0
seminar/templates/seminar/registrace/password_reset_subject.txt → various/autentizace/templates/autentizace/password_reset_subject.txt

0
seminar/templates/seminar/registrace/reset_hesla.html → various/autentizace/templates/autentizace/reset_hesla.html

0
seminar/templates/seminar/registrace/reset_poslan.html → various/autentizace/templates/autentizace/reset_poslan.html

15
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/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='reset_password_confirm'),
path('reset-hesla/hotovo/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'),
]

31
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í?
)

45
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')
Loading…
Cancel
Save