Browse Source

Merge branch 'data_migrations' into test

middleware_test
Jonas Havelka 4 years ago
parent
commit
f7a234b0c6
  1. 34
      data/sitetree.json
  2. 1
      mamweb/settings_common.py
  3. 8
      mamweb/static/css/mamweb.css
  4. BIN
      mamweb/static/images/MSMT_logo_bez_textu_black.eps
  5. 354
      mamweb/static/images/mozaika-footer.svg
  6. 8
      mamweb/templates/graph.svg
  7. 5
      seminar/export.py
  8. 37
      seminar/forms.py
  9. 14
      seminar/models.py
  10. 16
      seminar/templates/seminar/odevzdavatko/resitel_prehled.html
  11. 2
      seminar/templates/seminar/profil/edit.html
  12. 4
      seminar/templates/seminar/profil/login.html
  13. 21
      seminar/templatetags/deadliny.py
  14. 3
      seminar/test_deadlines.py
  15. 3
      seminar/urls.py
  16. 14
      seminar/utils.py
  17. 2
      seminar/views/odevzdavatko.py
  18. 47
      seminar/views/views_all.py

34
data/sitetree.json

@ -334,7 +334,7 @@
"inmenu": true, "inmenu": true,
"insitetree": true, "insitetree": true,
"parent": 3, "parent": 3,
"sort_order": 33, "sort_order": 43,
"title": "Výsledková listina", "title": "Výsledková listina",
"tree": 1, "tree": 1,
"url": "seminar_aktualni_vysledky", "url": "seminar_aktualni_vysledky",
@ -695,13 +695,13 @@
"alias": null, "alias": null,
"description": "", "description": "",
"hidden": false, "hidden": false,
"hint": "To, co ŘEŠITELÉ poslali", "hint": "",
"inbreadcrumbs": true, "inbreadcrumbs": true,
"inmenu": true, "inmenu": true,
"insitetree": true, "insitetree": true,
"parent": 21, "parent": 21,
"sort_order": 38, "sort_order": 37,
"title": "Došlá řešení", "title": "Odevzdaná řešení",
"tree": 1, "tree": 1,
"url": "odevzdavatko_tabulka", "url": "odevzdavatko_tabulka",
"urlaspattern": true "urlaspattern": true
@ -724,7 +724,7 @@
"inmenu": true, "inmenu": true,
"insitetree": true, "insitetree": true,
"parent": 21, "parent": 21,
"sort_order": 42, "sort_order": 38,
"title": "Odhlásit se", "title": "Odhlásit se",
"tree": 1, "tree": 1,
"url": "logout", "url": "logout",
@ -832,5 +832,29 @@
}, },
"model": "sitetree.treeitem", "model": "sitetree.treeitem",
"pk": 42 "pk": 42
},
{
"fields": {
"access_guest": false,
"access_loggedin": false,
"access_perm_type": 1,
"access_permissions": [],
"access_restricted": false,
"alias": null,
"description": "",
"hidden": false,
"hint": "",
"inbreadcrumbs": true,
"inmenu": true,
"insitetree": true,
"parent": 3,
"sort_order": 33,
"title": "Aktuální ročník",
"tree": 1,
"url": "seminar_aktualni_rocnik",
"urlaspattern": true
},
"model": "sitetree.treeitem",
"pk": 43
} }
] ]

1
mamweb/settings_common.py

@ -44,6 +44,7 @@ STATICFILES_FINDERS = (
# Where redirect for login required services # Where redirect for login required services
LOGIN_URL = 'login' LOGIN_URL = 'login'
LOGIN_REDIRECT_URL = 'profil'
# Modules configuration # Modules configuration

8
mamweb/static/css/mamweb.css

@ -1149,11 +1149,13 @@ div.gdpr {
} }
/* tabulka odevzdaných řešení */ /* tabulka odevzdaných řešení */
.dosla_reseni tr th {
text-align: center;
}
.dosla_reseni tr th, .dosla_reseni tr td { .dosla_reseni tr th, .dosla_reseni tr td {
border: 1px solid black; border: 1px solid black;
padding: 1px 10px 1px 10px; padding: 1px 10px 1px 10px;
border-collapse: collapse; border-collapse: collapse;
text-align: center;
}
.dosla_reseni tr td#problem {
text-align: left;
} }

BIN
mamweb/static/images/MSMT_logo_bez_textu_black.eps

Binary file not shown.

354
mamweb/static/images/mozaika-footer.svg

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 128 KiB

8
mamweb/templates/graph.svg

@ -409,7 +409,7 @@
</g> </g>
</a> </a>
<a <a
href="/aktualni/temata/" href="/aktualni/zadani/"
id="temata" id="temata"
transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)"> transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)">
<g <g
@ -439,7 +439,7 @@
</g> </g>
</a> </a>
<a <a
href="/aktualni/temata/" href="/aktualni/zadani/"
id="a74" id="a74"
transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)"> transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)">
<g <g
@ -469,7 +469,7 @@
</g> </g>
</a> </a>
<a <a
href="/aktualni/temata/" href="/aktualni/zadani/"
id="a80" id="a80"
transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)"> transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)">
<g <g
@ -499,7 +499,7 @@
</g> </g>
</a> </a>
<a <a
href="/aktualni/temata/" href="/aktualni/zadani/"
id="a86" id="a86"
transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)"> transform="matrix(0.70138313,0,0,0.7462289,-192.38886,20.298351)">
<g <g

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

5
seminar/export.py

@ -9,6 +9,7 @@ from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva #from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from .ovvpfile import OvvpFile from .ovvpfile import OvvpFile
from seminar import views from seminar import views
from seminar.views import vysledkovka
from seminar.utils import aktivniResitele from seminar.utils import aktivniResitele
class ExportIndexView(generic.View): class ExportIndexView(generic.View):
@ -78,8 +79,8 @@ class ExportRocnikView(generic.View):
rocnik = get_object_or_404(Rocnik, prvni_rok=pr, exportovat=True) rocnik = get_object_or_404(Rocnik, prvni_rok=pr, exportovat=True)
cislo = rocnik.posledni_zverejnena_vysledkovka_cislo() cislo = rocnik.posledni_zverejnena_vysledkovka_cislo()
resitele = aktivniResitele(cislo, True) resitele = aktivniResitele(cislo, True)
slovnik_body = views.secti_body_za_rocnik(cislo, resitele) slovnik_body = vysledkovka.secti_body_za_rocnik(cislo, resitele, False)
_, setrizeni_resitele, setrizene_body = views.setrid_resitele_a_body(slovnik_body) _, setrizeni_resitele, body = vysledkovka.setrid_resitele_a_body(slovnik_body)
of = default_ovvpfile('MaM.rocnik', rocnik) of = default_ovvpfile('MaM.rocnik', rocnik)
of.headers['comment'] = u'MaM-Web export aktivnich resitelu rocniku {rocnik} do cisla {cislo}'.format(rocnik=rocnik, cislo=cislo) of.headers['comment'] = u'MaM-Web export aktivnich resitelu rocniku {rocnik} do cisla {cislo}'.format(rocnik=rocnik, cislo=cislo)

37
seminar/forms.py

@ -142,28 +142,6 @@ class PrihlaskaForm(forms.Form):
elif data.get('skola_adresa')=='': elif data.get('skola_adresa')=='':
self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy')) self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy'))
# Editační formulář bez řešitele.
class ProfileEditFormPoMaturite(forms.Form):
username = forms.CharField(label='Přihlašovací jméno',
max_length=256,
required=True)
jmeno = forms.CharField(label='Jméno', max_length=256, required=True)
prijmeni = forms.CharField(label='Příjmení', max_length=256, required=True)
pohlavi_muz = forms.ChoiceField(label='Pohlaví',
choices = ((True,'muž'),(False,'žena')), required=True)
email = forms.EmailField(label='E-mail',max_length=256, required=True)
telefon = forms.CharField(widget=TelInput(),label='Telefon',max_length=256, required=False)
datum_narozeni = forms.DateField(widget=DateInput(),label='Datum narození', required=False)
ulice = forms.CharField(label='Ulice', max_length=256, required=False)
mesto = forms.CharField(label='Město', max_length=256, required=False)
psc = forms.CharField(label='PSČ', max_length=32, required=False)
stat = forms.ChoiceField(label='Stát',
choices = (('CZ', 'Česká Republika'),
('SK', 'Slovenská Republika'),
('other', 'Jiné')),
required=False)
stat_text = forms.CharField(label='Stát', max_length=256, required=False)
class ProfileEditForm(forms.Form): class ProfileEditForm(forms.Form):
username = forms.CharField(label='Přihlašovací jméno', username = forms.CharField(label='Přihlašovací jméno',
@ -203,7 +181,7 @@ class ProfileEditForm(forms.Form):
rok_maturity = forms.IntegerField( rok_maturity = forms.IntegerField(
label='Rok maturity', label='Rok maturity',
min_value=date.today().year, min_value=date.today().year,
max_value=date.today().year+8, max_value=date.today().year+8,
required=True) required=True)
zasilat = forms.ChoiceField(label='Kam zasílat čísla a řešení',choices = Resitel.ZASILAT_CHOICES, required=True) zasilat = forms.ChoiceField(label='Kam zasílat čísla a řešení',choices = Resitel.ZASILAT_CHOICES, required=True)
@ -255,6 +233,11 @@ class ProfileEditForm(forms.Form):
# elif data.get('skola_adresa')=='': # elif data.get('skola_adresa')=='':
# self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy')) # self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy'))
class PoMaturiteProfileEditForm(ProfileEditForm):
rok_maturity = forms.IntegerField(
label='Rok maturity',
required=True)
class VlozReseniForm(forms.Form): class VlozReseniForm(forms.Form):
#FIXME jen podproblémy daného problému #FIXME jen podproblémy daného problému
problem = forms.ModelChoiceField(label='Problém',queryset=m.Problem.objects.all()) problem = forms.ModelChoiceField(label='Problém',queryset=m.Problem.objects.all())
@ -284,16 +267,16 @@ class VlozReseniForm(forms.Form):
#forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, #forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False,
# default=FORMA_EMAIL) # default=FORMA_EMAIL)
poznamka = forms.CharField(label='Neveřejná poznámka') poznamka = forms.CharField(label='Neveřejná poznámka', required=False)
#poznamka = models.TextField('neveřejná poznámka', blank=True, #poznamka = models.TextField('neveřejná poznámka', blank=True,
# help_text='Neveřejná poznámka k řešení (plain text)') # help_text='Neveřejná poznámka k řešení (plain text)')
#TODO body do cisla #TODO body do cisla
#TODO prilohy #TODO prilohy
def __init__(self, *args, **kwargs): ##def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) ## super().__init__(*args, **kwargs)
#self.fields['favorite_color'] = forms.ChoiceField(choices=[(color.id, color.name) for color in Resitel.objects.all()]) ## #self.fields['favorite_color'] = forms.ChoiceField(choices=[(color.id, color.name) for color in Resitel.objects.all()])
class NahrajReseniForm(forms.ModelForm): class NahrajReseniForm(forms.ModelForm):
class Meta: class Meta:

14
seminar/models.py

@ -525,17 +525,17 @@ class Cislo(SeminarModelBase):
datum_vydani = models.DateField('datum vydání', blank=True, null=True, datum_vydani = models.DateField('datum vydání', blank=True, null=True,
help_text='Datum vydání finální verze') help_text='Datum vydání finální verze')
datum_deadline = models.DateField('datum deadline', blank=True, null=True,
help_text='Datum pro příjem řešení úloh zadaných v tomto čísle')
datum_preddeadline = models.DateField('datum předdeadline', blank=True, null=True,
help_text='Datum pro příjem řešení, která se otisknou v dalším čísle')
datum_deadline_soustredeni = models.DateField( datum_deadline_soustredeni = models.DateField(
'datum deadline soustředění', 'datum deadline soustředění',
blank=True, null=True, blank=True, null=True,
help_text='Datum pro příjem řešení pro účast na soustředění') help_text='Datum pro příjem řešení pro účast na soustředění')
datum_preddeadline = models.DateField('datum předdeadline', blank=True, null=True,
help_text='Datum pro příjem řešení, která se otisknou v dalším čísle')
datum_deadline = models.DateField('datum deadline', blank=True, null=True,
help_text='Datum pro příjem řešení úloh zadaných v tomto čísle')
verejne_db = models.BooleanField('číslo zveřejněno', verejne_db = models.BooleanField('číslo zveřejněno',
db_column='verejne', default=False) db_column='verejne', default=False)

16
seminar/templates/seminar/odevzdavatko/resitel_prehled.html

@ -3,6 +3,15 @@
{% load deadliny %} {% load deadliny %}
{% block content %} {% block content %}
<h3>Označení deadlinů</h3>
<ul>
<li>Ⓢ deadline pro účast na soustředění</li>
<li>♲ 1. deadline</li>
<li>✓ 2. deadline</li>
</ul>
<br>
{% for rocnik, hodnoceni in podle_rocniku %} {% for rocnik, hodnoceni in podle_rocniku %}
<h1>Ročník {{ rocnik }}</h1> <h1>Ročník {{ rocnik }}</h1>
<table class="dosla_reseni"> <table class="dosla_reseni">
@ -14,12 +23,15 @@
</tr> </tr>
{% for hodn in hodnoceni %} {% for hodn in hodnoceni %}
<tr> <tr>
<td>{{ hodn.reseni.cas_doruceni }}</td> <td>{{ hodn.reseni.cas_doruceni | date:"d.m.Y H:i"}}</td>
<td>{{ hodn.problem }}</td> <td id="problem"><span title="{{ hodn.problem.nazev }}">{{ hodn.problem.nazev | zkrat_nazev_problemu }}</span></td>
<td>{{ hodn.body|default_if_none:"---" }}</td> <td>{{ hodn.body|default_if_none:"---" }}</td>
<td>{{ hodn.reseni.cas_doruceni | deadline_html }}</td> <td>{{ hodn.reseni.cas_doruceni | deadline_html }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<br>
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

2
seminar/templates/seminar/profil/edit.html

@ -61,7 +61,6 @@
{% include "seminar/profil/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} {% include "seminar/profil/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%}
</table> </table>
{% if not po_maturite %} {# Vysloužilým účastníkům skrýt editaci školy apod. #}
<hr> <hr>
<h4> <h4>
@ -96,7 +95,6 @@
</table> </table>
<hr> <hr>
{% endif %}
<input type="submit" value="Změnit"> <input type="submit" value="Změnit">
</form> </form>

4
seminar/templates/seminar/profil/login.html

@ -8,6 +8,10 @@
Přihlášení Přihlášení
{% endblock %}{% endblock %} {% endblock %}{% endblock %}
</h1> </h1>
{# Obšlehnuto z Admina :-) #}
{% if user.is_authenticated %}
<p>K této stránce nejspíš nemáte přístup. Můžete se zkusit přihlásit jako uživatel, který přístup má.</p>
{% endif %}
<form action="{% url 'login' %}" method="post"> <form action="{% url 'login' %}" method="post">
{% csrf_token %} {% csrf_token %}
<table class="form"> <table class="form">

21
seminar/templatetags/deadliny.py

@ -5,6 +5,8 @@ register = template.Library()
@register.filter(name='deadline') @register.filter(name='deadline')
def deadline_text(datum): def deadline_text(datum):
if deadline(datum) is None:
return 'Neznámý deadline'
typ, cislo, dl = deadline(datum) typ, cislo, dl = deadline(datum)
strings = { strings = {
TypDeadline.PredDeadline: f"1. deadline čísla {cislo} ({dl})", TypDeadline.PredDeadline: f"1. deadline čísla {cislo} ({dl})",
@ -15,16 +17,20 @@ def deadline_text(datum):
@register.filter(name='deadline_kratseji') @register.filter(name='deadline_kratseji')
def deadline_kratsi_text(datum): def deadline_kratsi_text(datum):
if deadline(datum) is None:
return 'NONE'
typ, cislo, dl = deadline(datum) typ, cislo, dl = deadline(datum)
strings = { strings = {
TypDeadline.PredDeadline: f"1. deadline {cislo}", TypDeadline.PredDeadline: f"{cislo}",
TypDeadline.SousDeadline: f"Soustřeďkový deadline {cislo}", TypDeadline.SousDeadline: f"{cislo}",
TypDeadline.FinalDeadline: f"Finální deadline {cislo}", TypDeadline.FinalDeadline: f"{cislo}",
} }
return strings[typ] return strings[typ]
@register.filter(name='deadline_html') @register.filter(name='deadline_html')
def deadline_html(datum): def deadline_html(datum):
if deadline(datum) is None:
return 'Neznámý deadline'
typ, _, _ = deadline(datum) typ, _, _ = deadline(datum)
text = deadline_kratsi_text(datum) text = deadline_kratsi_text(datum)
classes = { classes = {
@ -33,3 +39,12 @@ def deadline_html(datum):
TypDeadline.FinalDeadline: 'final_deadline', TypDeadline.FinalDeadline: 'final_deadline',
} }
return mark_safe(f'<span class="{classes[typ]}">{text}</span>') return mark_safe(f'<span class="{classes[typ]}">{text}</span>')
@register.filter(name='zkrat_nazev_problemu')
def zkrat_nazev_problemu(nazev):
if len(nazev) > 10:
if nazev[9] == " ":
nazev = nazev[:9] + "..."
else:
nazev = nazev[:10] + "..."
return nazev

3
seminar/test_deadlines.py

@ -144,3 +144,6 @@ class DeadlineTestCase(TestCase):
def test_deadline_pro_datetime(self): def test_deadline_pro_datetime(self):
"""Testuje, že i pro datetime dostáváme správné deadliny""" """Testuje, že i pro datetime dostáváme správné deadliny"""
self.skipTest('Chybí implementace testu') self.skipTest('Chybí implementace testu')
def test_moc_pozdni_deadline(self):
self.assertIsNone(deadline(date.max))

3
seminar/urls.py

@ -61,6 +61,7 @@ urlpatterns = [
path('aktualni/zadani/', views.AktualniZadaniView, name='seminar_aktualni_zadani'), path('aktualni/zadani/', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
#path('aktualni/temata/', views.ZadaniTemataView, name='seminar_temata'), #path('aktualni/temata/', views.ZadaniTemataView, name='seminar_temata'),
path('aktualni/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_aktualni_vysledky'), path('aktualni/vysledkova-listina/', views.ZadaniAktualniVysledkovkaView, name='seminar_aktualni_vysledky'),
path('aktualni/rocnik/', views.AktualniRocnikRedirectView.as_view(), name='seminar_aktualni_rocnik'),
path('stare-novinky/', views.StareNovinkyView.as_view(), name='stare_novinky'), path('stare-novinky/', views.StareNovinkyView.as_view(), name='stare_novinky'),
# Clanky # Clanky
@ -133,7 +134,9 @@ urlpatterns = [
path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'), path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'),
path('prihlasit/', views.LoginView.as_view(), name='login'), 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('odhlasit/', views.LogoutView.as_view(), name='logout'),
path('logout/', RedirectView.as_view(pattern_name='login', permanent=True, query_string=True)),
path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'), path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'),
path('resitel/odevzdana_reseni/', resitel_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'), path('resitel/odevzdana_reseni/', resitel_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'),
path('reset-hesla/', views.PasswordResetView.as_view(), name='reset_password'), path('reset-hesla/', views.PasswordResetView.as_view(), name='reset_password'),

14
seminar/utils.py

@ -14,11 +14,15 @@ from django.core.exceptions import ObjectDoesNotExist
from enum import Enum from enum import Enum
from enum import auto from enum import auto
import logging
import seminar.models as m import seminar.models as m
import seminar.treelib as t import seminar.treelib as t
org_required = permission_required('auth.org', raise_exception=True) logger = logging.getLogger(__name__)
resitel_required = permission_required('auth.resitel', raise_exception=True)
org_required = permission_required('auth.org')
resitel_required = permission_required('auth.resitel')
User = get_user_model() User = get_user_model()
# Není to úplně hezké, ale budeme doufat, že to je funkční... # Není to úplně hezké, ale budeme doufat, že to je funkční...
User.je_org = property(lambda self: self.has_perm('auth.org')) User.je_org = property(lambda self: self.has_perm('auth.org'))
@ -312,11 +316,12 @@ def deadline_v_rocniku(datum, rocnik):
if datum <= dl[2]: if datum <= dl[2]:
# První takový deadline je ten nejtěsnější # První takový deadline je ten nejtěsnější
return dl return dl
logger.error(f'Pro datum {datum} v ročníku {rocnik} neexistuje deadline.')
def deadline(datum): def deadline(datum):
"""Funkce pro dohledání, ke kterému deadlinu se datum váže. """Funkce pro dohledání, ke kterému deadlinu se datum váže.
Vrací trojici (TypDeadline, Cislo, datumDeadline: date). Vrací trojici (TypDeadline, Cislo, datumDeadline: date). Pokud se deadline nenajde, vrátí None
""" """
if isinstance(datum, datetime.datetime): if isinstance(datum, datetime.datetime):
@ -338,9 +343,12 @@ def deadline(datum):
# Seznam čísel je potřeba ručně setřídit chronologicky, protože Model říká, že se řadí od nejnovějšího # Seznam čísel je potřeba ručně setřídit chronologicky, protože Model říká, že se řadí od nejnovějšího
posledni_deadline_drivejsiho_rocniku = m.Cislo.objects.filter(rocnik=drivejsi_rocnik, datum_deadline__isnull=False).order_by('poradi').last().datum_deadline posledni_deadline_drivejsiho_rocniku = m.Cislo.objects.filter(rocnik=drivejsi_rocnik, datum_deadline__isnull=False).order_by('poradi').last().datum_deadline
logger.debug(f'Nalezené ročníky: {drivejsi_rocnik}, {pozdejsi_rocnik}')
if drivejsi_rocnik is not None and datum <= posledni_deadline_drivejsiho_rocniku: if drivejsi_rocnik is not None and datum <= posledni_deadline_drivejsiho_rocniku:
logger.debug(f'Hledám v dřívějším ročníku: {drivejsi_rocnik}')
return deadline_v_rocniku(datum, drivejsi_rocnik) return deadline_v_rocniku(datum, drivejsi_rocnik)
else: else:
logger.debug(f'Hledám v pozdějším ročníku: {pozdejsi_rocnik}')
return deadline_v_rocniku(datum, pozdejsi_rocnik) return deadline_v_rocniku(datum, pozdejsi_rocnik)

2
seminar/views/odevzdavatko.py

@ -257,7 +257,7 @@ class PrehledOdevzdanychReseni(ListView):
# Ročník určujeme podle čísla, do jehož deadlinu došlo řešení. # Ročník určujeme podle čísla, do jehož deadlinu došlo řešení.
# Chceme to mít seřazené, takže místo comphrerehsion ručně postavíme pole polí. Django templates neumí použít OrderedDict :-/ # Chceme to mít seřazené, takže místo comphrerehsion ručně postavíme pole polí. Django templates neumí použít OrderedDict :-/
podle_rocniku = [] podle_rocniku = []
for rocnik, hodnoceni in groupby(ctx['object_list'], lambda ho: deadline(ho.reseni.cas_doruceni)[1].rocnik): for rocnik, hodnoceni in groupby(ctx['object_list'], lambda ho: deadline(ho.reseni.cas_doruceni)[1].rocnik if deadline(ho.reseni.cas_doruceni) is not None else None):
podle_rocniku.append((rocnik, list(hodnoceni))) podle_rocniku.append((rocnik, list(hodnoceni)))
ctx['podle_rocniku'] = reversed(podle_rocniku) # Od nejnovějšího ročníku ctx['podle_rocniku'] = reversed(podle_rocniku) # Od nejnovějšího ročníku
# TODO: Umožnit stažení / zobrazení řešení # TODO: Umožnit stažení / zobrazení řešení

47
seminar/views/views_all.py

@ -11,7 +11,7 @@ from django.http import Http404,HttpResponseBadRequest,HttpResponseRedirect
from django.db.models import Q, Sum, Count from django.db.models import Q, Sum, Count
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic.edit import FormView, CreateView from django.views.generic.edit import FormView, CreateView
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView, RedirectView
from django.contrib.auth import authenticate, login, get_user_model, logout from django.contrib.auth import authenticate, login, get_user_model, logout
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.contrib.auth.models import User, Permission from django.contrib.auth.models import User, Permission
@ -26,7 +26,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 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 .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from seminar import utils, treelib from seminar import utils, treelib
from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm, ProfileEditFormPoMaturite from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm, PoMaturiteProfileEditForm
import seminar.forms as f import seminar.forms as f
import seminar.templatetags.treenodes as tnltt import seminar.templatetags.treenodes as tnltt
import seminar.views.views_rest as vr import seminar.views.views_rest as vr
@ -1026,7 +1026,20 @@ class ResitelView(LoginRequiredMixin,generic.DetailView):
class AddSolutionView(LoginRequiredMixin, FormView): class AddSolutionView(LoginRequiredMixin, FormView):
template_name = 'seminar/org/vloz_reseni.html' template_name = 'seminar/org/vloz_reseni.html'
form_class = f.VlozReseniForm form_class = f.VlozReseniForm
success_url = '/'
def form_valid(self, form):
data = form.cleaned_data
nove_reseni = m.Reseni.objects.create(
cas_doruceni=data['cas_doruceni'],
forma=data['forma'],
poznamka=data['poznamka'],
)
nove_reseni.resitele.add(data['resitel'])
nove_reseni.problem.add(data['problem'])
nove_reseni.save()
# Chtěl jsem, aby bylo vidět, že se to uložilo, tak přesměrovávám na profil.
return redirect(reverse('profil'))
class NahrajReseniView(LoginRequiredMixin, CreateView): class NahrajReseniView(LoginRequiredMixin, CreateView):
model = s.Reseni model = s.Reseni
@ -1095,21 +1108,21 @@ def resitelEditView(request):
user_edit = osoba_edit.user user_edit = osoba_edit.user
## Vytvoření slovníku, kterým předvyplním formulář ## Vytvoření slovníku, kterým předvyplním formulář
prefill_1=model_to_dict(user_edit) prefill_1=model_to_dict(user_edit)
if resitel_edit and resitel_edit.rok_maturity >= date.today().year: if resitel_edit:
prefill_2=model_to_dict(resitel_edit) prefill_2=model_to_dict(resitel_edit)
prefill_1.update(prefill_2) prefill_1.update(prefill_2)
prefill_3=model_to_dict(osoba_edit) prefill_3=model_to_dict(osoba_edit)
prefill_1.update(prefill_3) prefill_1.update(prefill_3)
if 'datum_narozeni' in prefill_1: if 'datum_narozeni' in prefill_1:
prefill_1['datum_narozeni'] = str(prefill_1['datum_narozeni']) prefill_1['datum_narozeni'] = str(prefill_1['datum_narozeni'])
if resitel_edit and resitel_edit.rok_maturity < date.today().year: if 'rok_maturity' not in prefill_1 or prefill_1['rok_maturity'] < date.today().year:
form = ProfileEditFormPoMaturite(initial=prefill_1) form = PoMaturiteProfileEditForm(initial=prefill_1)
else: else:
form = ProfileEditForm(initial=prefill_1) form = ProfileEditForm(initial=prefill_1)
## Změna údajů a jejich uložení ## Změna údajů a jejich uložení
if request.method == 'POST': if request.method == 'POST':
if resitel_edit and resitel_edit.rok_maturity < date.today().year: if 'rok_maturity' not in prefill_1 or prefill_1['rok_maturity'] < date.today().year:
form = ProfileEditFormPoMaturite(request.POST) form = PoMaturiteProfileEditForm(request.POST)
else: else:
form = ProfileEditForm(request.POST) form = ProfileEditForm(request.POST)
if form.is_valid(): if form.is_valid():
@ -1133,7 +1146,7 @@ def resitelEditView(request):
## Neznámá země ## Neznámá země
msg = "Unknown country {}".format(fcd['stat_text']) msg = "Unknown country {}".format(fcd['stat_text'])
if resitel_edit and resitel_edit.rok_maturity >= date.today().year: if resitel_edit:
## Změny v řešiteli ## Změny v řešiteli
resitel_edit.skola = fcd['skola'] resitel_edit.skola = fcd['skola']
resitel_edit.rok_maturity = fcd['rok_maturity'] resitel_edit.rok_maturity = fcd['rok_maturity']
@ -1149,7 +1162,7 @@ def resitelEditView(request):
return formularOKView(request) return formularOKView(request)
else: else:
## Stránka před odeslaním formuláře = předvyplněný formulář ## Stránka před odeslaním formuláře = předvyplněný formulář
return render(request, 'seminar/profil/edit.html', {'form': form, 'po_maturite': resitel_edit and resitel_edit.rok_maturity < date.today().year}) return render(request, 'seminar/profil/edit.html', {'form': form})
def prihlaskaView(request): def prihlaskaView(request):
generic_logger = logging.getLogger('seminar.prihlaska') generic_logger = logging.getLogger('seminar.prihlaska')
@ -1230,12 +1243,6 @@ class LoginView(auth_views.LoginView):
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL # Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL
template_name = 'seminar/profil/login.html' template_name = 'seminar/profil/login.html'
# Přesměrovací URL má být v kontextu:
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['next'] = reverse('profil')
return ctx
class LogoutView(auth_views.LogoutView): class LogoutView(auth_views.LogoutView):
# Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL # Jen vezmeme vestavěný a dáme mu vhodný template a přesměrovací URL
template_name = 'seminar/profil/logout.html' template_name = 'seminar/profil/logout.html'
@ -1327,3 +1334,11 @@ class JakResitView(generic.ListView):
def get_queryset(self): def get_queryset(self):
return None return None
class AktualniRocnikRedirectView(RedirectView):
permanent=False
pattern_name = 'seminar_rocnik'
def get_redirect_url(self, *args, **kwargs):
aktualni_rocnik = m.Nastaveni.get_solo().aktualni_rocnik.rocnik
return super().get_redirect_url(rocnik=aktualni_rocnik, *args, **kwargs)

Loading…
Cancel
Save