From 342c791700daae6da923b13d2ce12a46e16d8338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 11:25:53 +0200 Subject: [PATCH 01/72] Model pro deadline --- deploy_v2/admin_org_prava.json | 15 ++++++ seminar/admin.py | 9 ++++ seminar/migrations/0103_deadline.py | 72 +++++++++++++++++++++++++++++ seminar/models/tvorba.py | 39 ++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 seminar/migrations/0103_deadline.py diff --git a/deploy_v2/admin_org_prava.json b/deploy_v2/admin_org_prava.json index f1b6445d..2d07cf83 100644 --- a/deploy_v2/admin_org_prava.json +++ b/deploy_v2/admin_org_prava.json @@ -633,5 +633,20 @@ "codename": "view_fotkaurlvazba", "ct_app_label": "header_fotky", "ct_model": "fotkaurlvazba" + }, + { + "codename": "add_deadline", + "ct_app_label": "seminar", + "ct_model": "deadline" + }, + { + "codename": "change_deadline", + "ct_app_label": "seminar", + "ct_model": "deadline" + }, + { + "codename": "view_deadline", + "ct_app_label": "seminar", + "ct_model": "deadline" } ] diff --git a/seminar/admin.py b/seminar/admin.py index 49464771..3008b3bd 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -15,6 +15,14 @@ import seminar.models as m admin.site.register(m.Rocnik) +admin.site.register(m.Deadline) + + +class DeadlineAdminInline(admin.TabularInline): + model = m.Deadline + extra = 0 + + class CisloForm(ModelForm): class Meta: model = m.Cislo @@ -65,6 +73,7 @@ class CisloForm(ModelForm): class CisloAdmin(admin.ModelAdmin): form = CisloForm actions = ['force_publish'] + inlines = (DeadlineAdminInline,) def force_publish(self,request,queryset): for cislo in queryset: diff --git a/seminar/migrations/0103_deadline.py b/seminar/migrations/0103_deadline.py new file mode 100644 index 00000000..b79f6bd3 --- /dev/null +++ b/seminar/migrations/0103_deadline.py @@ -0,0 +1,72 @@ +# Generated by Django 3.2.15 on 2022-10-01 08:44 + +import datetime +from django.db import migrations, models +import django.db.models.deletion +from django.utils import timezone + +import seminar.models as m + + +def vytvor_deadliny(apps, schema_editor): + Cislo = apps.get_model('seminar', 'Cislo') + Deadline = apps.get_model('seminar', 'Deadline') + + for cislo in Cislo.objects.all(): + if cislo.datum_deadline_soustredeni and cislo.datum_deadline_soustredeni == cislo.datum_preddeadline: + d = Deadline() + d.cislo = cislo + d.typ = m.Deadline.TYP_PRVNI_A_SOUS + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline_soustredeni, datetime.time.max)) + d.verejna_vysledkovka = cislo.verejna_vysledkovka + d.save() + else: + if cislo.datum_deadline_soustredeni: + d = Deadline() + d.cislo = cislo + d.typ = m.Deadline.TYP_SOUS + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline_soustredeni, datetime.time.max)) + d.verejna_vysledkovka = cislo.verejna_vysledkovka + d.save() + if cislo.datum_preddeadline: + d = Deadline() + d.cislo = cislo + d.typ = m.Deadline.TYP_PRVNI + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_preddeadline, datetime.time.max)) + d.verejna_vysledkovka = cislo.verejna_vysledkovka + d.save() + + if cislo.datum_deadline: + d = Deadline() + d.cislo = cislo + d.typ = m.Deadline.TYP_CISLA + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline, datetime.time.max)) + d.verejna_vysledkovka = cislo.verejna_vysledkovka + d.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0102_osoba_jak_se_dozvedeli'), + ] + + operations = [ + migrations.CreateModel( + name='Deadline', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('deadline', models.DateTimeField(default=timezone.make_aware(datetime.datetime.combine(timezone.now(), datetime.time.max)))), + ('typ', models.CharField(choices=[('cisla', 'Deadline celého čísla'), ('prvni', 'První deadline'), ('prvniasous', 'Sousový a první deadline'), ('sous', 'Sousový deadline')], max_length=32, verbose_name='typ deadlinu')), + ('verejna_vysledkovka', models.BooleanField(db_column='verejna_vysledkovka', default=False, verbose_name='veřejná výsledkovka')), + ('cislo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='deadline_v_cisle', to='seminar.cislo', verbose_name='deadline v čísle')), + ], + options={ + 'verbose_name': 'Deadline', + 'verbose_name_plural': 'Deadliny', + 'db_table': 'seminar_deadliny', + 'ordering': ['deadline'], + }, + ), + migrations.RunPython(vytvor_deadliny, migrations.RunPython.noop), + ] diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index e34b7681..7da4139c 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +import datetime import os import subprocess import pathlib @@ -328,6 +329,44 @@ class Cislo(SeminarModelBase): raise ValidationError({'datum_deadline_soustredeni': "Soustřeďkový deadline musí předcházet finálnímu deadlinu"}) +class Deadline(SeminarModelBase): + class Meta: + db_table = 'seminar_deadliny' + verbose_name = 'Deadline' + verbose_name_plural = 'Deadliny' + ordering = ['deadline'] + + id = models.AutoField(primary_key=True) + + deadline = models.DateTimeField(blank=False, default=timezone.make_aware(datetime.datetime.combine(timezone.now(), datetime.time.max))) + + cislo = models.ForeignKey(Cislo, verbose_name='deadline v čísle', + related_name='deadline_v_cisle', blank=False, + on_delete=models.CASCADE) + + TYP_CISLA = 'cisla' + TYP_PRVNI_A_SOUS = 'prvniasous' + TYP_PRVNI = 'prvni' + TYP_SOUS = 'sous' + TYP_CHOICES = [ + (TYP_CISLA, 'Deadline celého čísla'), + (TYP_PRVNI, 'První deadline'), + (TYP_PRVNI_A_SOUS, 'Sousový a první deadline'), + (TYP_SOUS, 'Sousový deadline'), + ] + CHOICES_MAP = dict(TYP_CHOICES) + typ = models.CharField('typ deadlinu', max_length=32, + choices=TYP_CHOICES, blank=False) + + verejna_vysledkovka = models.BooleanField('veřejná výsledkovka', + db_column='verejna_vysledkovka', + default=False) + + def __str__(self): + return self.CHOICES_MAP[self.typ] + " " + str(self.cislo) + + + @reversion.register(ignore_duplicates=True) # Pozor na následující řádek. *Nekrmit, asi kouše!* class Problem(SeminarModelBase,PolymorphicModel): From e33a80b16de0e1cfe7b79f9c4b969346ccdae5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 11:39:59 +0200 Subject: [PATCH 02/72] =?UTF-8?q?Deadline=20u=20hodnocen=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0104_hodnoceni_deadline_body.py | 35 +++++++++++++++++++ seminar/models/odevzdavatko.py | 3 ++ 2 files changed, 38 insertions(+) create mode 100644 seminar/migrations/0104_hodnoceni_deadline_body.py diff --git a/seminar/migrations/0104_hodnoceni_deadline_body.py b/seminar/migrations/0104_hodnoceni_deadline_body.py new file mode 100644 index 00000000..7f797a11 --- /dev/null +++ b/seminar/migrations/0104_hodnoceni_deadline_body.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.15 on 2022-10-01 09:28 + +from django.db import migrations, models +import django.db.models.deletion +from logging import getLogger + +log = getLogger(__name__) + +def prirad_deadliny(apps, schema_editor): + Hodnoceni = apps.get_model('seminar', 'Hodnoceni') + Deadline = apps.get_model('seminar', 'Deadline') + + for h in Hodnoceni.objects.all(): + d = Deadline.objects.filter(deadline__gte=h.reseni.cas_doruceni).first() + h.deadline_body = d + h.save() + + if h.cislo_body and int(h.deadline_body.cislo.poradi) + 1 != int(h.cislo_body.poradi[0]): + log.error(f"Hodnocení {h.id} se špatně změnilo číslo z {h.cislo_body} na {h.deadline_body.cislo}") + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0103_deadline'), + ] + + operations = [ + migrations.AddField( + model_name='hodnoceni', + name='deadline_body', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='hodnoceni', to='seminar.deadline', verbose_name='deadline pro body'), + ), + migrations.RunPython(prirad_deadliny, migrations.RunPython.noop), + ] diff --git a/seminar/models/odevzdavatko.py b/seminar/models/odevzdavatko.py index 343f92f0..ed16166f 100644 --- a/seminar/models/odevzdavatko.py +++ b/seminar/models/odevzdavatko.py @@ -101,6 +101,9 @@ class Hodnoceni(bm.SeminarModelBase): cislo_body = models.ForeignKey(am.Cislo, verbose_name='číslo pro body', related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT) + deadline_body = models.ForeignKey(am.Deadline, verbose_name='deadline pro body', + related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT) + reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE) problem = models.ForeignKey(am.Problem, verbose_name='problém', From d9912671ff18025887cc3a05ff04f7b3f1b5fdac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 12:43:16 +0200 Subject: [PATCH 03/72] =?UTF-8?q?Dopln=C4=9Bn=C3=AD=20deadlin=C5=AF,=20v?= =?UTF-8?q?=C4=9Bt=C5=A1=C3=AD=20rozptyl=20kontroly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/migrations/0103_deadline.py | 15 +++++++++++---- .../migrations/0104_hodnoceni_deadline_body.py | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/seminar/migrations/0103_deadline.py b/seminar/migrations/0103_deadline.py index b79f6bd3..337f6365 100644 --- a/seminar/migrations/0103_deadline.py +++ b/seminar/migrations/0103_deadline.py @@ -3,6 +3,7 @@ import datetime from django.db import migrations, models import django.db.models.deletion +from django.db.models import F from django.utils import timezone import seminar.models as m @@ -11,13 +12,19 @@ import seminar.models as m def vytvor_deadliny(apps, schema_editor): Cislo = apps.get_model('seminar', 'Cislo') Deadline = apps.get_model('seminar', 'Deadline') + Hodnoceni = apps.get_model('seminar', 'Hodnoceni') for cislo in Cislo.objects.all(): + if not (cislo.datum_deadline or cislo.datum_deadline_soustredeni or cislo.datum_preddeadline): + h = Hodnoceni.objects.filter(cislo_body=cislo).order_by(F("reseni__cas_doruceni")).last() + if h is not None: + cislo.datum_deadline = h.reseni.cas_doruceni.date() + cislo.save() if cislo.datum_deadline_soustredeni and cislo.datum_deadline_soustredeni == cislo.datum_preddeadline: d = Deadline() d.cislo = cislo d.typ = m.Deadline.TYP_PRVNI_A_SOUS - d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline_soustredeni, datetime.time.max)) + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline_soustredeni, datetime.time.min)) + datetime.timedelta(days=1) d.verejna_vysledkovka = cislo.verejna_vysledkovka d.save() else: @@ -25,14 +32,14 @@ def vytvor_deadliny(apps, schema_editor): d = Deadline() d.cislo = cislo d.typ = m.Deadline.TYP_SOUS - d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline_soustredeni, datetime.time.max)) + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline_soustredeni, datetime.time.min)) + datetime.timedelta(days=1) d.verejna_vysledkovka = cislo.verejna_vysledkovka d.save() if cislo.datum_preddeadline: d = Deadline() d.cislo = cislo d.typ = m.Deadline.TYP_PRVNI - d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_preddeadline, datetime.time.max)) + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_preddeadline, datetime.time.min)) + datetime.timedelta(days=1) d.verejna_vysledkovka = cislo.verejna_vysledkovka d.save() @@ -40,7 +47,7 @@ def vytvor_deadliny(apps, schema_editor): d = Deadline() d.cislo = cislo d.typ = m.Deadline.TYP_CISLA - d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline, datetime.time.max)) + d.deadline = timezone.make_aware(datetime.datetime.combine(cislo.datum_deadline, datetime.time.min)) + datetime.timedelta(days=1) d.verejna_vysledkovka = cislo.verejna_vysledkovka d.save() diff --git a/seminar/migrations/0104_hodnoceni_deadline_body.py b/seminar/migrations/0104_hodnoceni_deadline_body.py index 7f797a11..bc662479 100644 --- a/seminar/migrations/0104_hodnoceni_deadline_body.py +++ b/seminar/migrations/0104_hodnoceni_deadline_body.py @@ -15,7 +15,7 @@ def prirad_deadliny(apps, schema_editor): h.deadline_body = d h.save() - if h.cislo_body and int(h.deadline_body.cislo.poradi) + 1 != int(h.cislo_body.poradi[0]): + if h.cislo_body and (int(h.deadline_body.cislo.poradi) + 2 < int(h.cislo_body.poradi[0]) or int(h.deadline_body.cislo.poradi) > int(h.cislo_body.poradi[0])): log.error(f"Hodnocení {h.id} se špatně změnilo číslo z {h.cislo_body} na {h.deadline_body.cislo}") From 87e51ac7449ad0c36d59c9aeb7920653696483b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 14:01:29 +0200 Subject: [PATCH 04/72] =?UTF-8?q?J=C3=A1=20u=C5=BE=20nev=C3=ADm,=20jak=20u?= =?UTF-8?q?r=C4=8Dovat=20deadliny=20=C5=99e=C5=A1en=C3=AD=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/migrations/0103_deadline.py | 7 +++- .../0104_hodnoceni_deadline_body.py | 41 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/seminar/migrations/0103_deadline.py b/seminar/migrations/0103_deadline.py index 337f6365..406c7200 100644 --- a/seminar/migrations/0103_deadline.py +++ b/seminar/migrations/0103_deadline.py @@ -16,10 +16,15 @@ def vytvor_deadliny(apps, schema_editor): for cislo in Cislo.objects.all(): if not (cislo.datum_deadline or cislo.datum_deadline_soustredeni or cislo.datum_preddeadline): - h = Hodnoceni.objects.filter(cislo_body=cislo).order_by(F("reseni__cas_doruceni")).last() + h = Hodnoceni.objects.filter(problem__uloha__cislo_zadani=cislo).order_by(F("reseni__cas_doruceni")).last() + + if h is None: + h = Hodnoceni.objects.filter(cislo_body=cislo).order_by(F("reseni__cas_doruceni")).last() + if h is not None: cislo.datum_deadline = h.reseni.cas_doruceni.date() cislo.save() + if cislo.datum_deadline_soustredeni and cislo.datum_deadline_soustredeni == cislo.datum_preddeadline: d = Deadline() d.cislo = cislo diff --git a/seminar/migrations/0104_hodnoceni_deadline_body.py b/seminar/migrations/0104_hodnoceni_deadline_body.py index bc662479..66d8e61f 100644 --- a/seminar/migrations/0104_hodnoceni_deadline_body.py +++ b/seminar/migrations/0104_hodnoceni_deadline_body.py @@ -11,11 +11,50 @@ def prirad_deadliny(apps, schema_editor): Deadline = apps.get_model('seminar', 'Deadline') for h in Hodnoceni.objects.all(): + p = h.problem + + try: + u = p.uloha + if u.cislo_zadani is not None: + d = Deadline.objects.filter(cislo=u.cislo_zadani, deadline__gte=h.reseni.cas_doruceni).first() + h.deadline_body = d + h.save() + continue + + except Exception: + pass + + try: + c = p.clanek + if c.cislo is not None: + d = Deadline.objects.filter(cislo=c.cislo, deadline__gte=h.reseni.cas_doruceni).first() + h.deadline_body = d + h.save() + continue + + except Exception: + pass + + try: + t = p.tema + d = Deadline.objects.filter(cislo__rocnik=t.rocnik, deadline__gte=h.reseni.cas_doruceni).first() + + if d is None: + d = Deadline.objects.filter(cislo__rocnik=t.rocnik).last() + + h.deadline_body = d + h.save() + + except Exception: + pass + + log.warning(f"Deadline hodnocení {h.id} se nepodařil určit exaktnějším způsobem. Zkouším další.") + d = Deadline.objects.filter(deadline__gte=h.reseni.cas_doruceni).first() h.deadline_body = d h.save() - if h.cislo_body and (int(h.deadline_body.cislo.poradi) + 2 < int(h.cislo_body.poradi[0]) or int(h.deadline_body.cislo.poradi) > int(h.cislo_body.poradi[0])): + if h.cislo_body and (int(h.deadline_body.cislo.poradi[0]) + 2 < int(h.cislo_body.poradi[0]) or int(h.deadline_body.cislo.poradi[0]) > int(h.cislo_body.poradi[0])): log.error(f"Hodnocení {h.id} se špatně změnilo číslo z {h.cislo_body} na {h.deadline_body.cislo}") From 261f2447e3303649d1164cfab0b2e09feff2f79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 14:11:29 +0200 Subject: [PATCH 05/72] =?UTF-8?q?J=C3=A1=20u=C5=BE=20nev=C3=ADm,=20jak=20u?= =?UTF-8?q?r=C4=8Dovat=20deadliny=20=C5=99e=C5=A1en=C3=AD=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0104_hodnoceni_deadline_body.py | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/seminar/migrations/0104_hodnoceni_deadline_body.py b/seminar/migrations/0104_hodnoceni_deadline_body.py index 66d8e61f..74992fb8 100644 --- a/seminar/migrations/0104_hodnoceni_deadline_body.py +++ b/seminar/migrations/0104_hodnoceni_deadline_body.py @@ -14,39 +14,44 @@ def prirad_deadliny(apps, schema_editor): p = h.problem try: - u = p.uloha - if u.cislo_zadani is not None: - d = Deadline.objects.filter(cislo=u.cislo_zadani, deadline__gte=h.reseni.cas_doruceni).first() - h.deadline_body = d - h.save() - continue + t = p.tema + d = Deadline.objects.filter(cislo__rocnik=t.rocnik, deadline__gte=h.reseni.cas_doruceni).first() + + if d is None: + d = Deadline.objects.filter(cislo__rocnik=t.rocnik).last() + + h.deadline_body = d + h.save() except Exception: pass + + cislo = None + + try: + u = p.uloha + cislo = u.cislo_zadani + except Exception: + pass + try: c = p.clanek if c.cislo is not None: - d = Deadline.objects.filter(cislo=c.cislo, deadline__gte=h.reseni.cas_doruceni).first() - h.deadline_body = d - h.save() - continue - + cislo = c.cislo except Exception: pass - try: - t = p.tema - d = Deadline.objects.filter(cislo__rocnik=t.rocnik, deadline__gte=h.reseni.cas_doruceni).first() + if cislo is None: + cislo = h.cislo_body + if cislo is not None: + d = Deadline.objects.filter(cislo=cislo, deadline__gte=h.reseni.cas_doruceni).first() if d is None: - d = Deadline.objects.filter(cislo__rocnik=t.rocnik).last() - + d = Deadline.objects.filter(cislo=cislo).last() h.deadline_body = d h.save() - - except Exception: - pass + continue log.warning(f"Deadline hodnocení {h.id} se nepodařil určit exaktnějším způsobem. Zkouším další.") From 05047d547a263e56422b59436ed1f9762022f6b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 14:22:12 +0200 Subject: [PATCH 06/72] Fix migrace --- seminar/migrations/0104_hodnoceni_deadline_body.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/seminar/migrations/0104_hodnoceni_deadline_body.py b/seminar/migrations/0104_hodnoceni_deadline_body.py index 74992fb8..fe118b60 100644 --- a/seminar/migrations/0104_hodnoceni_deadline_body.py +++ b/seminar/migrations/0104_hodnoceni_deadline_body.py @@ -20,8 +20,10 @@ def prirad_deadliny(apps, schema_editor): if d is None: d = Deadline.objects.filter(cislo__rocnik=t.rocnik).last() - h.deadline_body = d - h.save() + if d is not None: + h.deadline_body = d + h.save() + continue except Exception: pass @@ -49,9 +51,10 @@ def prirad_deadliny(apps, schema_editor): d = Deadline.objects.filter(cislo=cislo, deadline__gte=h.reseni.cas_doruceni).first() if d is None: d = Deadline.objects.filter(cislo=cislo).last() - h.deadline_body = d - h.save() - continue + if d is not None: + h.deadline_body = d + h.save() + continue log.warning(f"Deadline hodnocení {h.id} se nepodařil určit exaktnějším způsobem. Zkouším další.") From 79d9636c28ba960c09f2199e07fcdb56c16fed1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 14:41:47 +0200 Subject: [PATCH 07/72] =?UTF-8?q?Automatick=C3=A9=20nastaven=C3=AD=20deadl?= =?UTF-8?q?inu=20u=20Hodnocen=C3=AD,=20orgovsk=C3=A1=20=C3=BAprava=20deadl?= =?UTF-8?q?in=C5=AF=20u=20Hodnocen=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- odevzdavatko/forms.py | 2 +- odevzdavatko/templates/odevzdavatko/detail.html | 6 +++--- .../templates/odevzdavatko/detail_resitele.html | 4 ++-- odevzdavatko/views.py | 11 ++++++----- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/odevzdavatko/forms.py b/odevzdavatko/forms.py index 14639b65..0f243f82 100644 --- a/odevzdavatko/forms.py +++ b/odevzdavatko/forms.py @@ -87,7 +87,7 @@ ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni, class JednoHodnoceniForm(forms.ModelForm): class Meta: model = m.Hodnoceni - fields = ('problem', 'body', 'cislo_body') + fields = ('problem', 'body', 'deadline_body') widgets = { 'problem': autocomplete.ModelSelect2( url='autocomplete_problem_odevzdatelny', # FIXME: Dovolit i starší? diff --git a/odevzdavatko/templates/odevzdavatko/detail.html b/odevzdavatko/templates/odevzdavatko/detail.html index 233d703d..b5402001 100644 --- a/odevzdavatko/templates/odevzdavatko/detail.html +++ b/odevzdavatko/templates/odevzdavatko/detail.html @@ -97,13 +97,13 @@ $(document).ready(function(){ {{ form.management_form }} - + {% for subform in form %} - + @@ -118,7 +118,7 @@ $(document).ready(function(){ - +
ProblémBodyČíslo pro body
ProblémBodyDeadline pro body
{{ subform.problem }} {{ subform.body }}{{ subform.cislo_body }}{{ subform.deadline_body }} Smazat
{{ form.empty_form.problem }} {{ form.empty_form.body }}{{ form.empty_form.cislo_body }}{{ form.empty_form.deadline_body }} Smazat
diff --git a/odevzdavatko/templates/odevzdavatko/detail_resitele.html b/odevzdavatko/templates/odevzdavatko/detail_resitele.html index 4e5d7848..c1741f1c 100644 --- a/odevzdavatko/templates/odevzdavatko/detail_resitele.html +++ b/odevzdavatko/templates/odevzdavatko/detail_resitele.html @@ -37,12 +37,12 @@ {# Hodnocení: #}

Hodnocení:

-{# #} +{# #} {% for h in hodnoceni %} -{# #} +{# #} {% endfor %}
ProblémBodyČíslo pro body
ProblémBodyDeadline pro body
{{ h.problem }} {{ h.body }}{{ h.cislo_body }}{{ h.deadline_body }}
diff --git a/odevzdavatko/views.py b/odevzdavatko/views.py index 5c1fc5b4..04db1e5b 100644 --- a/odevzdavatko/views.py +++ b/odevzdavatko/views.py @@ -216,12 +216,12 @@ class DetailReseniView(DetailView): def aktualni_hodnoceni(self): self.reseni = get_object_or_404(m.Reseni, id=self.kwargs['pk']) - result = [] # Slovníky s klíči problem, body, cislo_body -- initial data pro f.OhodnoceniReseniFormSet + result = [] # Slovníky s klíči problem, body, deadline_body -- initial data pro f.OhodnoceniReseniFormSet for hodn in m.Hodnoceni.objects.filter(reseni=self.reseni): result.append( {"problem": hodn.problem, "body": hodn.body, - "cislo_body": hodn.cislo_body, + "deadline_body": hodn.deadline_body, }) return result @@ -260,11 +260,11 @@ def hodnoceniReseniView(request, pk, *args, **kwargs): for form in formset: problem = form.cleaned_data['problem'] body = form.cleaned_data['body'] - cislo_body = form.cleaned_data['cislo_body'] + deadline_body = form.cleaned_data['deadline_body'] hodnoceni = m.Hodnoceni( problem=problem, body=body, - cislo_body=cislo_body, + deadline_body=deadline_body, reseni=reseni, ) logger.info(f"Creating Hodnoceni: {hodnoceni}") @@ -285,7 +285,7 @@ class ResitelReseniView(DetailView): { "problem": hodn.problem, "body": hodn.body, - # "cislo_body": hodn.cislo_body, + # "deadline_body": hodn.deadline_body, } ) return result @@ -412,6 +412,7 @@ class NahrajReseniView(LoginRequiredMixin, CreateView): self.object = form.save() self.object.resitele.add(m.Resitel.objects.get(osoba__user = self.request.user)) self.object.cas_doruceni = timezone.now() + self.object.deadline = m.Deadline.objects.filter(deadline__gte=self.object.cas_doruceni).first() self.object.forma = m.Reseni.FORMA_UPLOAD self.object.save() From ba7e3409a2b5db1895231ed42368c033f09e9b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sat, 1 Oct 2022 21:47:15 +0200 Subject: [PATCH 08/72] =?UTF-8?q?P=C5=99eps=C3=A1n=C3=AD=20v=C3=BDsledkove?= =?UTF-8?q?k=20v1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- personalni/views.py | 2 +- seminar/models/personalni.py | 4 +- seminar/models/tvorba.py | 10 + .../seminar/archiv/cislo_vysledkovka.tex | 6 +- seminar/templates/seminar/archiv/rocnik.html | 4 +- .../seminar/archiv/rocnik_vysledkovka.tex | 8 +- .../seminar/zadani/AktualniVysledkovka.html | 4 +- seminar/utils.py | 10 +- seminar/views/views_all.py | 37 +- .../vysledkovky/vysledkovka_cisla.html | 34 +- .../vysledkovky/vysledkovka_rocnik.html | 6 +- .../vysledkovka_rocnik_neverejna.html | 1 - vysledkovky/utils.py | 873 +++++++++--------- vysledkovky/views.py | 37 - 14 files changed, 490 insertions(+), 546 deletions(-) delete mode 100644 vysledkovky/templates/vysledkovky/vysledkovka_rocnik_neverejna.html delete mode 100644 vysledkovky/views.py diff --git a/personalni/views.py b/personalni/views.py index 00e6b389..94b90dea 100644 --- a/personalni/views.py +++ b/personalni/views.py @@ -40,7 +40,7 @@ class OrgoRozcestnikView(TemplateView): # přes treenody (a dát si přitom pozor na MezicisloNode) neobodovana_reseni = s.Hodnoceni.objects.filter(body__isnull=True) - reseni_mimo_cislo = s.Hodnoceni.objects.filter(cislo_body__isnull=True) + reseni_mimo_cislo = s.Hodnoceni.objects.filter(deadline_body__isnull=True) context['pocet_neobodovanych_reseni'] = neobodovana_reseni.count() context['pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.count() diff --git a/seminar/models/personalni.py b/seminar/models/personalni.py index 97bb808b..28deec4d 100644 --- a/seminar/models/personalni.py +++ b/seminar/models/personalni.py @@ -323,7 +323,7 @@ class Resitel(SeminarModelBase): # - proto se započítávají dvojnásobně a byly posunuté hranice titulů # - staré tituly se ale nemají odebrat, pokud řešitel v t.č. minulém (26.) ročníku měl titul, má ho mít pořád. from .odevzdavatko import Hodnoceni - hodnoceni_do_25_rocniku = Hodnoceni.objects.filter(cislo_body__rocnik__rocnik__lte=25,reseni__in=self.reseni_set.all()) + hodnoceni_do_25_rocniku = Hodnoceni.objects.filter(deadline_body__cislo__rocnik__rocnik__lte=25,reseni__in=self.reseni_set.all()) novejsi_hodnoceni = Hodnoceni.objects.filter(reseni__in=self.reseni_set.all()).difference(hodnoceni_do_25_rocniku) def body_z_hodnoceni(hh : list): @@ -361,7 +361,7 @@ class Resitel(SeminarModelBase): return Titul.akad from .odevzdavatko import Hodnoceni - hodnoceni_do_26_rocniku = Hodnoceni.objects.filter(cislo_body__rocnik__rocnik__lte=26,reseni__in=self.reseni_set.all()) + hodnoceni_do_26_rocniku = Hodnoceni.objects.filter(deadline_body__cislo__rocnik__rocnik__lte=26,reseni__in=self.reseni_set.all()) novejsi_body = body_z_hodnoceni( Hodnoceni.objects.filter(reseni__in=self.reseni_set.all()) .difference(hodnoceni_do_26_rocniku) diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index 7da4139c..2e68f74c 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -8,6 +8,7 @@ import logging from django.contrib.sites.shortcuts import get_current_site from django.db import models +from django.db.models import Q from django.utils import timezone from django.conf import settings from django.urls import reverse @@ -328,6 +329,9 @@ class Cislo(SeminarModelBase): if self.datum_deadline_soustredeni is not None and self.datum_deadline_soustredeni > self.datum_deadline: raise ValidationError({'datum_deadline_soustredeni': "Soustřeďkový deadline musí předcházet finálnímu deadlinu"}) + def zlomovy_deadline_pro_papirove_cislo(self): + return Deadline.objects.filter(Q(typ=Deadline.TYP_PRVNI) | Q(typ=Deadline.TYP_PRVNI_A_SOUS), cislo=self).first() + class Deadline(SeminarModelBase): class Meta: @@ -365,6 +369,12 @@ class Deadline(SeminarModelBase): def __str__(self): return self.CHOICES_MAP[self.typ] + " " + str(self.cislo) + def next(self): + return Deadline.objects.filter(gt=self).first() + + def previous(self): + return Deadline.objects.filter(lt=self).last() + @reversion.register(ignore_duplicates=True) diff --git a/seminar/templates/seminar/archiv/cislo_vysledkovka.tex b/seminar/templates/seminar/archiv/cislo_vysledkovka.tex index 38eeea01..36404486 100644 --- a/seminar/templates/seminar/archiv/cislo_vysledkovka.tex +++ b/seminar/templates/seminar/archiv/cislo_vysledkovka.tex @@ -1,9 +1,9 @@ \setlength{\tabcolsep}{3pt} -\begin{longtable}{|r|l|c|r|{% for p in problemy %}c@{\hskip.5em}{% endfor %}|r|r|}\hline -& & & & \multicolumn{ {{ problemy|length}} }{c|}{\textbf{Témata}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in problemy %}\textbf{ {{ p.kod_v_rocniku }} }&{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline +\begin{longtable}{|r|l|c|r|{% for p in vysledkovka.temata_a_spol %}c@{\hskip.5em}{% endfor %}|r|r|}\hline +& & & & \multicolumn{ {{ vysledkovka.temata_a_spol|length}} }{c|}{\textbf{Témata}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in vysledkovka.temata_a_spol %}\textbf{ {{ p.kod_v_rocniku }} }&{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline \endhead \hline \endfoot -{% for rv in radky_vysledkovky %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.osoba.jmeno|slice:":1"}}. {{rv.resitel.osoba.prijmeni}}&{{rv.rocnik_resitele|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_problemy_sezn %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_rocnik|default:0}}\\ +{% for rv in vysledkovka.radky_vysledkovky %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.osoba.jmeno|slice:":1"}}. {{rv.resitel.osoba.prijmeni}}&{{rv.rocnik_resitele|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_problemy_sezn %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_rocnik|default:0}}\\ {% endfor %} \end{longtable} diff --git a/seminar/templates/seminar/archiv/rocnik.html b/seminar/templates/seminar/archiv/rocnik.html index 757984cf..825ce37e 100644 --- a/seminar/templates/seminar/archiv/rocnik.html +++ b/seminar/templates/seminar/archiv/rocnik.html @@ -112,7 +112,7 @@ {% endif %} - {% if vysledkovka %} + {% if vysledkovka.radky_vysledkovky %}

Výsledková listina

{% include "vysledkovky/vysledkovka_rocnik.html" %} {% endif %} @@ -123,7 +123,7 @@ {# FIXME: Sice to sem asi nepatří sémanticky, ale bylo to nejjednodušší… #}

CSV export řešitelů

Výsledková listina včetně neveřejných bodů

- {% include "vysledkovky/vysledkovka_rocnik_neverejna.html" %} + {% include "vysledkovky/vysledkovka_rocnik.html" with vysledkovka=vysledkovka_neverejna %} {% endif %} diff --git a/seminar/templates/seminar/archiv/rocnik_vysledkovka.tex b/seminar/templates/seminar/archiv/rocnik_vysledkovka.tex index 217127de..ee9b2608 100644 --- a/seminar/templates/seminar/archiv/rocnik_vysledkovka.tex +++ b/seminar/templates/seminar/archiv/rocnik_vysledkovka.tex @@ -1,13 +1,13 @@ {% with lb="{" %} {% with rb="}" %} -{% with radky_vysledkovky=radky_vysledkovky_s_neverejnymi cisla=cisla_s_neverejnymi %} +{% with vysledkovka=vysledkovka_neverejna %} \setlength{\tabcolsep}{3pt} -\begin{longtable}{|r|l|c|r|{% for cislo in cisla %}c{% if not forloop.last %}@{\hskip.5em}{% endif %}{% endfor %}|r|}\hline -& & & & \multicolumn{{ lb }}{{ cisla|length }}}{c|}{\textbf{Číslo}} & \\\textbf{Poř.} & \textbf{Jméno} & \textbf{R.} & \raisebox{0.7mm}{$\sum_{-1}$} & {% for cislo in cisla %}\textbf{{ lb }}{{ cislo.poradi }}{{ rb }} & {% endfor %}\raisebox{0.7mm}{$\sum_1$} \\\hline +\begin{longtable}{|r|l|c|r|{% for cislo in vysledkovka.cisla_rocniku %}c{% if not forloop.last %}@{\hskip.5em}{% endif %}{% endfor %}|r|}\hline +& & & & \multicolumn{{ lb }}{{ vysledkovka.cisla_rocniku|length }}}{c|}{\textbf{Číslo}} & \\\textbf{Poř.} & \textbf{Jméno} & \textbf{R.} & \raisebox{0.7mm}{$\sum_{-1}$} & {% for cislo in vysledkovka.cisla_rocniku %}\textbf{{ lb }}{{ cislo.poradi }}{{ rb }} & {% endfor %}\raisebox{0.7mm}{$\sum_1$} \\\hline \endhead \hline \endfoot -{% for rv in radky_vysledkovky %}{{ rv.poradi }} & {% if rv.titul %}\titul{{ lb }}{{ rv.titul }}}~{% endif %}{{ rv.resitel.osoba.jmeno|slice:":1" }}.~{{ rv.resitel.osoba.prijmeni }} & {% if rv.rocnik_resitele %}{{ rv.rocnik_resitele }}{% endif %} & {{ rv.body_celkem_odjakziva }} {% for b in rv.body_cisla_sezn %} & {{ b }}{% endfor %} & {{ rv.body_rocnik }} \\ +{% for rv in vysledkovka.radky_vysledkovky %}{{ rv.poradi }} & {% if rv.titul %}\titul{{ lb }}{{ rv.titul }}}~{% endif %}{{ rv.resitel.osoba.jmeno|slice:":1" }}.~{{ rv.resitel.osoba.prijmeni }} & {% if rv.rocnik_resitele %}{{ rv.rocnik_resitele }}{% endif %} & {{ rv.body_celkem_odjakziva }} {% for b in rv.body_cisla_sezn %} & {{ b }}{% endfor %} & {{ rv.body_rocnik }} \\ {% endfor %}\end{longtable} {% endwith %} {% endwith %} diff --git a/seminar/templates/seminar/zadani/AktualniVysledkovka.html b/seminar/templates/seminar/zadani/AktualniVysledkovka.html index c447d135..20e81ac7 100644 --- a/seminar/templates/seminar/zadani/AktualniVysledkovka.html +++ b/seminar/templates/seminar/zadani/AktualniVysledkovka.html @@ -8,7 +8,7 @@ {% endblock %} - {% if radky_vysledkovky %} + {% if vysledkovka.radky_vysledkovky %} {% include "vysledkovky/vysledkovka_rocnik.html" %} {% else %}

V tomto ročníku zatím žádné výsledky nejsou.

@@ -22,7 +22,7 @@ {% if user.je_org and vysledkovka_s_neverejnymi %}

Výsledky včetně neveřejných

- {% include "vysledkovky/vysledkovka_rocnik_neverejna.html" %} + {% include "vysledkovky/vysledkovka_rocnik.html" with vysledkovka=vysledkovka_neverejna %}
{% endif %} diff --git a/seminar/utils.py b/seminar/utils.py index 176831cb..f4a598eb 100644 --- a/seminar/utils.py +++ b/seminar/utils.py @@ -179,11 +179,11 @@ def resi_v_rocniku(rocnik, cislo=None): if cislo is None: # filtrujeme pouze podle ročníku return m.Resitel.objects.filter(rok_maturity__gte=rocnik.druhy_rok(), - reseni__hodnoceni__cislo_body__rocnik=rocnik).distinct() + reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik).distinct() else: # filtrujeme podle ročníku i čísla return m.Resitel.objects.filter(rok_maturity__gte=rocnik.druhy_rok(), - reseni__hodnoceni__cislo_body__rocnik=rocnik, - reseni__hodnoceni__cislo_body__poradi__lte=cislo.poradi).distinct() + reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik, + reseni__hodnoceni__deadline_body__cislo__poradi__lte=cislo.poradi).distinct() def aktivniResitele(cislo, pouze_letosni=False): @@ -269,11 +269,11 @@ def hlavni_problem(problem): return problem def problemy_rocniku(rocnik, jen_verejne=True): - return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(cislo_body__in = cisla_rocniku(rocnik, jen_verejne))).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem') + return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(deadline_body__cislo__in = cisla_rocniku(rocnik, jen_verejne))).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem') def problemy_cisla(cislo): """ Vrátí seznam všech problémů s body v daném čísle. """ - return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(cislo_body = cislo)).distinct().non_polymorphic().select_related('nadproblem').select_related('nadproblem__nadproblem') + return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(deadline_body__cislo = cislo)).distinct().non_polymorphic().select_related('nadproblem').select_related('nadproblem__nadproblem') def hlavni_problemy_f(problemy=None): diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index 49327aa3..b5ab6b06 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -17,8 +17,8 @@ from seminar import utils from treenode import treelib import treenode.templatetags as tnltt import treenode.serializers as vr -from vysledkovky.utils import body_resitelu -from vysledkovky.views import vysledkovka_rocniku, vysledkovka_cisla +from vysledkovky.utils import body_resitelu, VysledkovkaCisla, \ + VysledkovkaRocniku from datetime import date, datetime from django.utils import timezone @@ -206,26 +206,17 @@ def ZadaniAktualniVysledkovkaView(request): nastaveni = get_object_or_404(Nastaveni) # Aktualni verejna vysledkovka rocnik = nastaveni.aktualni_rocnik - context = vysledkovka_rocniku( - rocnik=rocnik, - request=request, - sneverejnou=True - ) + context = {'vysledkovka': VysledkovkaRocniku(rocnik, True)} # kdyz neni verejna vysledkovka, tak zobraz starou - if len(context['cisla']) == 0: + if len(context['vysledkovka'].cisla_rocniku) == 0: try: minuly_rocnik = Rocnik.objects.get( - prvni_rok=(rocnik.prvni_rok-1)) + rocnik=(rocnik.rocnik-1)) rocnik = minuly_rocnik # Přepíšeme prázdnou výsledkovku výsledkovkou z minulého ročníku - context = vysledkovka_rocniku( - rocnik=rocnik, - context=context, - request=request, - sneverejnou=True - ) + context['vysledkovka'] = VysledkovkaRocniku(rocnik, True) except ObjectDoesNotExist: pass @@ -377,17 +368,10 @@ class RocnikView(generic.DetailView): return get_object_or_404(queryset,rocnik=self.kwargs.get('rocnik')) def get_context_data(self, **kwargs): - start = time.time() context = super(RocnikView, self).get_context_data(**kwargs) - context = vysledkovka_rocniku( - rocnik=context["rocnik"], - context=context, - request=self.request, - sneverejnou=True - ) - end = time.time() - print("Kontext:", end-start) - + context["vysledkovka"] = VysledkovkaRocniku(context["rocnik"], True) + context["neprazdna_vysledkovka"] = len(context['vysledkovka'].cisla_rocniku) != 0 + context["vysledkovka_neverejna"] = VysledkovkaRocniku(context["rocnik"], False) return context def resiteleRocnikuCsvExportView(request, rocnik): @@ -453,7 +437,8 @@ class CisloView(generic.DetailView): cislo = context['cislo'] context['prevcislo'] = Cislo.objects.filter((Q(rocnik__lt=self.object.rocnik) | Q(poradi__lt=self.object.poradi))&Q(rocnik__lte=self.object.rocnik)).first() # vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky - return vysledkovka_cisla(cislo, context) + context['vysledkovka'] = VysledkovkaCisla(cislo, not self.request.user.je_org) + return context class ArchivTemataView(generic.ListView): diff --git a/vysledkovky/templates/vysledkovky/vysledkovka_cisla.html b/vysledkovky/templates/vysledkovky/vysledkovka_cisla.html index 6243c32b..6c3fb416 100644 --- a/vysledkovky/templates/vysledkovky/vysledkovka_cisla.html +++ b/vysledkovky/templates/vysledkovky/vysledkovka_cisla.html @@ -3,21 +3,21 @@ # Jméno - {% for p in problemy %} + {% for p in vysledkovka.temata_a_spol%} {# #}{{ p.kod_v_rocniku }}{# #} {# TODELETE #} - {% for podproblemy in podproblemy_iter.next %} + {% for podproblemy in vysledkovka.podproblemy_iter.next %} {# #}{{ podproblemy.kod_v_rocniku }}{# #} {% endfor %} {# TODELETE #} {% endfor %} - {% if ostatni %}Ostatní {% endif %} + {% if vysledkovka.ostatni %}Ostatní {% endif %} {# TODELETE #} {% for podproblemy in podproblemy_iter.next %} - {# #}{{ podproblemy.kod_v_rocniku }}{# #} + {# #}{{ podproblemy.kod_v_rocniku }}{# #} {% endfor %} {# TODELETE #} @@ -25,7 +25,7 @@ Za číslo Za ročník Odjakživa - {% for rv in radky_vysledkovky %} + {% for rv in vysledkovka.radky_vysledkovky %} {% autoescape off %}{{ rv.poradi }}{% endautoescape %} @@ -33,14 +33,12 @@ {{ rv.titul }}MM {% endif %} {{ rv.resitel.osoba.plne_jmeno }} - {% for b in rv.body_problemy_sezn %} + {% for b in rv.body_hlavni_problemy_seznam %} {{ b }} - {# TODELETE #} {% for body_podproblemu in rv.body_podproblemy_iter.next %} {{ body_podproblemu }} {% endfor %} - {# TODELETE #} {% endfor %} {{ rv.body_cislo }} @@ -55,7 +53,7 @@ {# TODELETE #}