From df2e4f086a9a0e12dfb77cb0a809cbf07a153984 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:20:24 +0100 Subject: [PATCH 01/59] Unmanage seminar.Nastaveni MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sry, nebudu to psát česky :-) --- .../migrations/0115_alter_nastaveni_options.py | 17 +++++++++++++++++ seminar/models/tvorba.py | 1 + 2 files changed, 18 insertions(+) create mode 100644 seminar/migrations/0115_alter_nastaveni_options.py diff --git a/seminar/migrations/0115_alter_nastaveni_options.py b/seminar/migrations/0115_alter_nastaveni_options.py new file mode 100644 index 00000000..9153bc4d --- /dev/null +++ b/seminar/migrations/0115_alter_nastaveni_options.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.23 on 2023-12-11 19:14 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0114_related_name_se_zmenilo_a_django_chce_migraci_tak_dostane_migraci'), + ] + + operations = [ + migrations.AlterModelOptions( + name='nastaveni', + options={'managed': False, 'verbose_name': 'Nastavení semináře'}, + ), + ] diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index 1c1a3285..bc5636b8 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -730,6 +730,7 @@ class Nastaveni(SingletonModel): class Meta: db_table = 'seminar_nastaveni' verbose_name = 'Nastavení semináře' + managed = False # aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name='aktuální ročník', # null=False, on_delete=models.PROTECT) From f19726127154d1b946f08d65e4085e2f87178424 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:20:48 +0100 Subject: [PATCH 02/59] =?UTF-8?q?Opraven=C3=AD=20related=5Fname?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tohle by mělo být nezávislé, nemůžeme vyrobit foreign key na něco, co už existuje… ERRORS: seminar.Nastaveni.aktualni_cislo: (fields.E304) Reverse accessor for 'seminar.Nastaveni.aktualni_cislo' clashes with reverse accessor for 'various.Nastaveni.aktualni_cislo'. HINT: Add or change a related_name argument to the definition for 'seminar.Nastaveni.aktualni_cislo' or 'various.Nastaveni.aktualni_cislo'. various.Nastaveni.aktualni_cislo: (fields.E304) Reverse accessor for 'various.Nastaveni.aktualni_cislo' clashes with reverse accessor for 'seminar.Nastaveni.aktualni_cislo'. HINT: Add or change a related_name argument to the definition for 'various.Nastaveni.aktualni_cislo' or 'seminar.Nastaveni.aktualni_cislo'. --- seminar/models/tvorba.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index bc5636b8..8049d8cf 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -736,7 +736,7 @@ class Nastaveni(SingletonModel): # null=False, on_delete=models.PROTECT) aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo', - null=False, on_delete=models.PROTECT) + null=False, on_delete=models.PROTECT, related_name='aktualni_cislo_old') cena_sous = models.IntegerField(null=False, verbose_name="Účastnický poplatek za soustředění", From 6a5390cdf6463ec2908fa8fa4f965b4f82698d93 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:21:27 +0100 Subject: [PATCH 03/59] =?UTF-8?q?P=C5=99id=C3=A1n=C3=AD=20Nastaveni=20do?= =?UTF-8?q?=20various?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- various/migrations/0001_initial.py | 26 ++++++++++++++++++++ various/models.py | 38 +++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 various/migrations/0001_initial.py diff --git a/various/migrations/0001_initial.py b/various/migrations/0001_initial.py new file mode 100644 index 00000000..5d1232cf --- /dev/null +++ b/various/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.23 on 2023-12-11 19:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Nastaveni', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cena_sous', models.IntegerField(default=1000, verbose_name='Účastnický poplatek za soustředění')), + ], + options={ + 'verbose_name': 'Nastavení semináře', + 'db_table': 'seminar_nastaveni', + 'managed': False, + }, + ), + ] diff --git a/various/models.py b/various/models.py index 71a83623..28a33057 100644 --- a/various/models.py +++ b/various/models.py @@ -1,3 +1,39 @@ from django.db import models -# Create your models here. +from reversion import revisions as reversion +from solo.models import SingletonModel + +from seminar.models import Cislo + +from django.urls import reverse + +@reversion.register(ignore_duplicates=True) +class Nastaveni(SingletonModel): + + class Meta: + db_table = 'seminar_nastaveni' + verbose_name = 'Nastavení semináře' + managed = False + +# aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name='aktuální ročník', +# null=False, on_delete=models.PROTECT) + + aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo', + null=False, on_delete=models.PROTECT) + + cena_sous = models.IntegerField(null=False, + verbose_name="Účastnický poplatek za soustředění", + default=1000) + + @property + def aktualni_rocnik(self): + return self.aktualni_cislo.rocnik + + def __str__(self): + return 'Nastavení semináře' + + def admin_url(self): + return reverse('admin:seminar_nastaveni_change', args=(self.id, )) + + def verejne(self): + return False From 0bbb860b163809ba1d3e745079cb530ec092d8df Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:25:33 +0100 Subject: [PATCH 04/59] =?UTF-8?q?Zru=C5=A1en=C3=AD=20seminar.Nastaveni?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/migrations/0116_delete_nastaveni.py | 16 +++++++++++ seminar/models/__init__.py | 2 ++ seminar/models/tvorba.py | 32 --------------------- 3 files changed, 18 insertions(+), 32 deletions(-) create mode 100644 seminar/migrations/0116_delete_nastaveni.py diff --git a/seminar/migrations/0116_delete_nastaveni.py b/seminar/migrations/0116_delete_nastaveni.py new file mode 100644 index 00000000..b820ea16 --- /dev/null +++ b/seminar/migrations/0116_delete_nastaveni.py @@ -0,0 +1,16 @@ +# Generated by Django 3.2.23 on 2023-12-11 19:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0115_alter_nastaveni_options'), + ] + + operations = [ + migrations.DeleteModel( + name='Nastaveni', + ), + ] diff --git a/seminar/models/__init__.py b/seminar/models/__init__.py index 34712ee4..6df1478f 100644 --- a/seminar/models/__init__.py +++ b/seminar/models/__init__.py @@ -6,3 +6,5 @@ from .soustredeni import * from .pomocne import * from .treenode import * from .novinky import * + +from various.models import Nastaveni diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index 8049d8cf..41def9c4 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -722,35 +722,3 @@ class Pohadka(SeminarModelBase): except ObjectDoesNotExist: # Neexistující *Node nemá smysl aktualizovat. pass - - -@reversion.register(ignore_duplicates=True) -class Nastaveni(SingletonModel): - - class Meta: - db_table = 'seminar_nastaveni' - verbose_name = 'Nastavení semináře' - managed = False - -# aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name='aktuální ročník', -# null=False, on_delete=models.PROTECT) - - aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo', - null=False, on_delete=models.PROTECT, related_name='aktualni_cislo_old') - - cena_sous = models.IntegerField(null=False, - verbose_name="Účastnický poplatek za soustředění", - default=1000) - - @property - def aktualni_rocnik(self): - return self.aktualni_cislo.rocnik - - def __str__(self): - return 'Nastavení semináře' - - def admin_url(self): - return reverse('admin:seminar_nastaveni_change', args=(self.id, )) - - def verejne(self): - return False From f7382fb9464cf116ae01d306cf5df9664a6a962e Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:28:10 +0100 Subject: [PATCH 05/59] =?UTF-8?q?Zapomenut=C3=A1=20z=C3=A1vislost?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ještě mi chybí jedna :-/ --- seminar/migrations/0116_delete_nastaveni.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seminar/migrations/0116_delete_nastaveni.py b/seminar/migrations/0116_delete_nastaveni.py index b820ea16..21d90b63 100644 --- a/seminar/migrations/0116_delete_nastaveni.py +++ b/seminar/migrations/0116_delete_nastaveni.py @@ -7,6 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('seminar', '0115_alter_nastaveni_options'), + ('various', '0001_initial'), ] operations = [ From 158c0e4d90711c19ee83e976e5a70ecc98a49ed5 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:28:58 +0100 Subject: [PATCH 06/59] =?UTF-8?q?Druh=C3=A1=20zapomenut=C3=A1=20z=C3=A1vis?= =?UTF-8?q?lost?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- various/migrations/0001_initial.py | 1 + 1 file changed, 1 insertion(+) diff --git a/various/migrations/0001_initial.py b/various/migrations/0001_initial.py index 5d1232cf..08bc1ea0 100644 --- a/various/migrations/0001_initial.py +++ b/various/migrations/0001_initial.py @@ -8,6 +8,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('seminar', '0115_alter_nastaveni_options'), ] operations = [ From ca0bbb124736168855b94eacc951e10cc6a78253 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 20:32:22 +0100 Subject: [PATCH 07/59] Manage --- .../migrations/0002_alter_nastaveni_options.py | 18 ++++++++++++++++++ various/models.py | 1 - 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 various/migrations/0002_alter_nastaveni_options.py diff --git a/various/migrations/0002_alter_nastaveni_options.py b/various/migrations/0002_alter_nastaveni_options.py new file mode 100644 index 00000000..6ef9c285 --- /dev/null +++ b/various/migrations/0002_alter_nastaveni_options.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.23 on 2023-12-11 19:30 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('various', '0001_initial'), + ('seminar', '0116_delete_nastaveni'), + ] + + operations = [ + migrations.AlterModelOptions( + name='nastaveni', + options={'verbose_name': 'Nastavení semináře'}, + ), + ] diff --git a/various/models.py b/various/models.py index 28a33057..6fc48e44 100644 --- a/various/models.py +++ b/various/models.py @@ -13,7 +13,6 @@ class Nastaveni(SingletonModel): class Meta: db_table = 'seminar_nastaveni' verbose_name = 'Nastavení semináře' - managed = False # aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name='aktuální ročník', # null=False, on_delete=models.PROTECT) From 37586d7433969d4a06b8818338265463dd8d777e Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 11 Dec 2023 21:31:54 +0100 Subject: [PATCH 08/59] =?UTF-8?q?Opraven=C3=AD=20pr=C3=A1v?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO: je na těch ContentTypech navěšené ještě něco dalšího? Pro nastavení asi ne, ale co ostatní aplikace? --- various/migrations/0003_fix_permissions.py | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 various/migrations/0003_fix_permissions.py diff --git a/various/migrations/0003_fix_permissions.py b/various/migrations/0003_fix_permissions.py new file mode 100644 index 00000000..2364f160 --- /dev/null +++ b/various/migrations/0003_fix_permissions.py @@ -0,0 +1,41 @@ +# Generated by Django 3.2.23 on 2023-12-11 19:40 + +from django.db import migrations + +def oprav_prava_k_nastaveni(apps, schema_editor): + # Tohle je trošku hnus, nešlo by to snáz? + ContentType = apps.get_model('contenttypes', 'ContentType') + Permission = apps.get_model('auth', 'Permission') + Group = apps.get_model('auth', 'Group') + old_ct = ContentType.objects.get_by_natural_key('seminar', 'nastaveni') + new_ct = ContentType.objects.get_by_natural_key('various', 'nastaveni') + old_perms = Permission.objects.filter(content_type=old_ct) + new_perms = Permission.objects.filter(content_type=new_ct) + for g in Group.objects.filter(permissions__in=old_perms): + old_codenames = Permission.objects.filter(group__in=[g], content_type=old_ct).values('codename') + g.permissions.add(*new_perms.filter(codename__in=old_codenames)) + g.permissions.remove(*old_perms) + +def obnov_prava_k_nastaveni(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + Permission = apps.get_model('auth', 'Permission') + Group = apps.get_model('auth', 'Group') + old_ct = ContentType.objects.get_by_natural_key('seminar', 'nastaveni') + new_ct = ContentType.objects.get_by_natural_key('various', 'nastaveni') + old_perms = Permission.objects.filter(content_type=old_ct) + new_perms = Permission.objects.filter(content_type=new_ct) + for g in Group.objects.filter(permissions__in=old_perms): + new_codenames = Permission.objects.filter(group__in=[g], content_type=new_ct).values('codename') + g.permissions.add(*old_perms.filter(codename__in=new_codenames)) + g.permissions.remove(*new_perms) + + +class Migration(migrations.Migration): + + dependencies = [ + ('various', '0002_alter_nastaveni_options'), + ] + + operations = [ + migrations.RunPython(oprav_prava_k_nastaveni, obnov_prava_k_nastaveni), + ] From f41d5587fc05585da214e122f8926941a1ca95a9 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 18 Dec 2023 21:21:17 +0100 Subject: [PATCH 09/59] =?UTF-8?q?Pokus=20o=20hack:=20p=C5=99i=20v=C3=BDrob?= =?UTF-8?q?=C4=9B=20modelu=20na=20n=C4=9Bj=20rovnou=20p=C5=99esm=C4=9Bruje?= =?UTF-8?q?me=20p=C5=AFvodn=C3=AD=20contenttype.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- various/migrations/0001_initial.py | 10 ++++++++++ various/migrations/0003_fix_permissions.py | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/various/migrations/0001_initial.py b/various/migrations/0001_initial.py index 08bc1ea0..1cc24c3d 100644 --- a/various/migrations/0001_initial.py +++ b/various/migrations/0001_initial.py @@ -2,6 +2,15 @@ from django.db import migrations, models +def nastav_nove_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + old_ct = ContentType.objects.get_by_natural_key('seminar', 'nastaveni') + old_ct.update(appname='various') + +def nastav_stare_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + new_ct = ContentType.objects.get_by_natural_key('various', 'nastaveni') + new_ct.update(appname='seminar') class Migration(migrations.Migration): @@ -24,4 +33,5 @@ class Migration(migrations.Migration): 'managed': False, }, ), + migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes), ] diff --git a/various/migrations/0003_fix_permissions.py b/various/migrations/0003_fix_permissions.py index 2364f160..9c3396f6 100644 --- a/various/migrations/0003_fix_permissions.py +++ b/various/migrations/0003_fix_permissions.py @@ -37,5 +37,4 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RunPython(oprav_prava_k_nastaveni, obnov_prava_k_nastaveni), ] From 39d618834bf3f066544f97b4ff28e56dd42d889b Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Mon, 18 Dec 2023 21:32:58 +0100 Subject: [PATCH 10/59] =?UTF-8?q?fixup!=20Pokus=20o=20hack:=20p=C5=99i=20v?= =?UTF-8?q?=C3=BDrob=C4=9B=20modelu=20na=20n=C4=9Bj=20rovnou=20p=C5=99esm?= =?UTF-8?q?=C4=9Brujeme=20p=C5=AFvodn=C3=AD=20contenttype.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- various/migrations/0001_initial.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/various/migrations/0001_initial.py b/various/migrations/0001_initial.py index 1cc24c3d..38f2a029 100644 --- a/various/migrations/0001_initial.py +++ b/various/migrations/0001_initial.py @@ -4,13 +4,15 @@ from django.db import migrations, models def nastav_nove_contenttypes(apps, schema_editor): ContentType = apps.get_model('contenttypes', 'ContentType') - old_ct = ContentType.objects.get_by_natural_key('seminar', 'nastaveni') - old_ct.update(appname='various') + old_ct = ContentType.objects.filter(app_label='seminar', model='nastaveni') + # Pozn: tohle může být prázdné (pokud Django nedostalo signál o dokončených migracích, např. při vyrábění databáze z nuly) + # Ale .update to nevadí… + old_ct.update(app_label='various') def nastav_stare_contenttypes(apps, schema_editor): ContentType = apps.get_model('contenttypes', 'ContentType') - new_ct = ContentType.objects.get_by_natural_key('various', 'nastaveni') - new_ct.update(appname='seminar') + new_ct = ContentType.objects.filter(app_label='various', model='nastaveni') + new_ct.update(app_label='seminar') class Migration(migrations.Migration): From 7a34fced0ad3e5028f5088044000718b3b7e8b33 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:27:26 +0100 Subject: [PATCH 11/59] =?UTF-8?q?P=C5=99=C3=ADprava=20na=20zru=C5=A1en?= =?UTF-8?q?=C3=AD=20person=C3=A1ln=C3=ADch=20v=C4=9Bc=C3=AD=20ze=20Semin?= =?UTF-8?q?=C3=A1=C5=99e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modely: Osoba, Řešitel, Organizátor, Škola, Příjemce --- korektury/migrations/0021_auto_20240312_2124.py | 13 +++++++++++++ personalni/migrations/0002_auto_20240312_2118.py | 13 +++++++++++++ prednasky/migrations/0013_auto_20240312_2124.py | 13 +++++++++++++ seminar/migrations/0117_auto_20240312_2125.py | 16 ++++++++++++++++ sifrovacka/migrations/0004_auto_20240312_2124.py | 13 +++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 korektury/migrations/0021_auto_20240312_2124.py create mode 100644 personalni/migrations/0002_auto_20240312_2118.py create mode 100644 prednasky/migrations/0013_auto_20240312_2124.py create mode 100644 seminar/migrations/0117_auto_20240312_2125.py create mode 100644 sifrovacka/migrations/0004_auto_20240312_2124.py diff --git a/korektury/migrations/0021_auto_20240312_2124.py b/korektury/migrations/0021_auto_20240312_2124.py new file mode 100644 index 00000000..ee2eb53d --- /dev/null +++ b/korektury/migrations/0021_auto_20240312_2124.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0020_lepsi_popis_nazvu_PDF_v_adminu'), + ] + + operations = [ + ] diff --git a/personalni/migrations/0002_auto_20240312_2118.py b/personalni/migrations/0002_auto_20240312_2118.py new file mode 100644 index 00000000..62a0b0d2 --- /dev/null +++ b/personalni/migrations/0002_auto_20240312_2118.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0001_skupiny'), + ] + + operations = [ + ] diff --git a/prednasky/migrations/0013_auto_20240312_2124.py b/prednasky/migrations/0013_auto_20240312_2124.py new file mode 100644 index 00000000..ea9ddb2e --- /dev/null +++ b/prednasky/migrations/0013_auto_20240312_2124.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('prednasky', '0012_auto_20190610_2358'), + ] + + operations = [ + ] diff --git a/seminar/migrations/0117_auto_20240312_2125.py b/seminar/migrations/0117_auto_20240312_2125.py new file mode 100644 index 00000000..57b2431f --- /dev/null +++ b/seminar/migrations/0117_auto_20240312_2125.py @@ -0,0 +1,16 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0116_delete_nastaveni'), + ('personalni', '0001_skupiny'), + ('korektury', '0021_auto_20240312_2124'), + ('sifrovacka', '0004_auto_20240312_2124'), + ] + + operations = [ + ] diff --git a/sifrovacka/migrations/0004_auto_20240312_2124.py b/sifrovacka/migrations/0004_auto_20240312_2124.py new file mode 100644 index 00000000..8f58cf58 --- /dev/null +++ b/sifrovacka/migrations/0004_auto_20240312_2124.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('sifrovacka', '0003_odpoveducastnika_uspech'), + ] + + operations = [ + ] From ae8040fb04720fc504bf2a017ef909eb62093c15 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:30:58 +0100 Subject: [PATCH 12/59] =?UTF-8?q?P=C5=99id=C3=A1v=C3=A1m=20(si)=20pozn?= =?UTF-8?q?=C3=A1mky=20o=20tom,=20jak=20se=20to=20bastl=C3=AD=20:-)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/dummy_migration.py | 6 ++++++ split-apps-meta/pre.sh | 3 +++ 2 files changed, 9 insertions(+) create mode 100644 split-apps-meta/dummy_migration.py create mode 100644 split-apps-meta/pre.sh diff --git a/split-apps-meta/dummy_migration.py b/split-apps-meta/dummy_migration.py new file mode 100644 index 00000000..6f9a2c9c --- /dev/null +++ b/split-apps-meta/dummy_migration.py @@ -0,0 +1,6 @@ +from django.db import migrations +class Migration(migrations.Migration): + dependencies = [ + ('APP', 'MIGR'), + ] + operations = [] diff --git a/split-apps-meta/pre.sh b/split-apps-meta/pre.sh new file mode 100644 index 00000000..28dbe9da --- /dev/null +++ b/split-apps-meta/pre.sh @@ -0,0 +1,3 @@ +for app in whatever I want; do + ./manage.py makemigrations --empty $app +vim seminar/migrations/whatever.py # add the other as depends. From b550857a8d9c88f3380e226c73762fb4e3e87099 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:45:50 +0100 Subject: [PATCH 13/59] Wtf nastaveni.aktualni_cislo nebylo??!?! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nějaká bullshit migrace, whatever. --- .../0004_nastaveni_aktualni_cislo.py | 21 +++++++++++++++++++ various/models.py | 8 ++++++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 various/migrations/0004_nastaveni_aktualni_cislo.py diff --git a/various/migrations/0004_nastaveni_aktualni_cislo.py b/various/migrations/0004_nastaveni_aktualni_cislo.py new file mode 100644 index 00000000..feb6bc71 --- /dev/null +++ b/various/migrations/0004_nastaveni_aktualni_cislo.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:44 + +from django.db import migrations, models +import django.db.models.deletion +import various.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0118_alter_organizator_options_alter_osoba_options_and_more'), + ('various', '0003_fix_permissions'), + ] + + operations = [ + migrations.AddField( + model_name='nastaveni', + name='aktualni_cislo', + field=models.ForeignKey(default=various.models._default_aktualni_cislo, on_delete=django.db.models.deletion.PROTECT, to='seminar.cislo', verbose_name='Aktuální číslo'), + ), + ] diff --git a/various/models.py b/various/models.py index 6fc48e44..eb89ab25 100644 --- a/various/models.py +++ b/various/models.py @@ -7,6 +7,10 @@ from seminar.models import Cislo from django.urls import reverse +# Whatever, makemigrations chce default, má ho mít lol. +def _default_aktualni_cislo(): + return Cislo.objects.last() + @reversion.register(ignore_duplicates=True) class Nastaveni(SingletonModel): @@ -18,7 +22,9 @@ class Nastaveni(SingletonModel): # null=False, on_delete=models.PROTECT) aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo', - null=False, on_delete=models.PROTECT) + null=False, on_delete=models.PROTECT, + default=_default_aktualni_cislo, + ) cena_sous = models.IntegerField(null=False, verbose_name="Účastnický poplatek za soustředění", From a1c1b9f280aa57a27441da64d5125afa3de99009 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:46:50 +0100 Subject: [PATCH 14/59] =?UTF-8?q?Pozn=C3=A1mky=20k=20odmanagov=C3=A1n?= =?UTF-8?q?=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/unmanage.notes | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 split-apps-meta/unmanage.notes diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes new file mode 100644 index 00000000..a3965cdb --- /dev/null +++ b/split-apps-meta/unmanage.notes @@ -0,0 +1,5 @@ +vim seminar/models/whatever + Model.Meta.managed = False + Model.field.related_name = Model.related_name + '_old' # až vyrobíme nový objekt, tak nesmí kolidovat. + # related_name se vyhodnocuje za běhu, takže pokud nic nespustíme (celý + # blok migrací spustíme najednou), tak nám nevadí, že v tuhle chvíli nefunguje půlka views ap :-) From e3ce5efdd67ccf16a71fcea74c2c1e1eefcb3266 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:47:02 +0100 Subject: [PATCH 15/59] =?UTF-8?q?Odmanagovan=C3=BD=20semin=C3=A1=C5=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...or_options_alter_osoba_options_and_more.py | 33 +++++++++++++++++++ seminar/models/personalni.py | 7 +++- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 seminar/migrations/0118_alter_organizator_options_alter_osoba_options_and_more.py diff --git a/seminar/migrations/0118_alter_organizator_options_alter_osoba_options_and_more.py b/seminar/migrations/0118_alter_organizator_options_alter_osoba_options_and_more.py new file mode 100644 index 00000000..642820a6 --- /dev/null +++ b/seminar/migrations/0118_alter_organizator_options_alter_osoba_options_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.8 on 2024-03-12 20:44 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0117_auto_20240312_2125'), + ] + + operations = [ + migrations.AlterModelOptions( + name='organizator', + options={'managed': False, 'ordering': ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'], 'verbose_name': 'Organizátor', 'verbose_name_plural': 'Organizátoři'}, + ), + migrations.AlterModelOptions( + name='osoba', + options={'managed': False, 'ordering': ['prijmeni', 'jmeno'], 'verbose_name': 'Osoba', 'verbose_name_plural': 'Osoby'}, + ), + migrations.AlterModelOptions( + name='prijemce', + options={'managed': False, 'verbose_name': 'příjemce', 'verbose_name_plural': 'příjemce'}, + ), + migrations.AlterModelOptions( + name='resitel', + options={'managed': False, 'ordering': ['osoba'], 'verbose_name': 'Řešitel', 'verbose_name_plural': 'Řešitelé'}, + ), + migrations.AlterModelOptions( + name='skola', + options={'managed': False, 'ordering': ['mesto', 'nazev'], 'verbose_name': 'Škola', 'verbose_name_plural': 'Školy'}, + ), + ] diff --git a/seminar/models/personalni.py b/seminar/models/personalni.py index 61313e87..b245c2a4 100644 --- a/seminar/models/personalni.py +++ b/seminar/models/personalni.py @@ -25,6 +25,7 @@ class Osoba(SeminarModelBase): verbose_name = 'Osoba' verbose_name_plural = 'Osoby' ordering = ['prijmeni','jmeno'] + managed = False id = models.AutoField(primary_key = True) @@ -128,6 +129,7 @@ class Skola(SeminarModelBase): verbose_name = 'Škola' verbose_name_plural = 'Školy' ordering = ['mesto', 'nazev'] + managed = False # Interní ID id = models.AutoField(primary_key = True) @@ -180,6 +182,7 @@ class Prijemce(SeminarModelBase): db_table = 'seminar_prijemce' verbose_name = 'příjemce' verbose_name_plural = 'příjemce' + managed = False # Interní ID @@ -209,6 +212,7 @@ class Resitel(SeminarModelBase): verbose_name = 'Řešitel' verbose_name_plural = 'Řešitelé' ordering = ['osoba'] + managed = False # Interní ID id = models.AutoField(primary_key = True) @@ -395,7 +399,7 @@ class Resitel(SeminarModelBase): @reversion.register(ignore_duplicates=True) class Organizator(SeminarModelBase): - osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org', + osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org_old', help_text='osobní údaje organizátora', null=False, blank=False, on_delete=models.PROTECT) @@ -445,3 +449,4 @@ class Organizator(SeminarModelBase): # TODO: Zohledňovat přezdívky? # TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] + managed = False From 559297240d100b4f5b395f08b77189744b9ae7c7 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:53:17 +0100 Subject: [PATCH 16/59] =?UTF-8?q?Dal=C5=A1=C3=AD=20pozn=C3=A1mky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/create.notes | 4 ++++ split-apps-meta/unmanage.notes | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 split-apps-meta/create.notes diff --git a/split-apps-meta/create.notes b/split-apps-meta/create.notes new file mode 100644 index 00000000..9abae94d --- /dev/null +++ b/split-apps-meta/create.notes @@ -0,0 +1,4 @@ +Prostě zkopírovat vedle, s původními (=správnými) related names. +makemigrations +doplnit závislost na unmanage +migrate diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes index a3965cdb..b00cb294 100644 --- a/split-apps-meta/unmanage.notes +++ b/split-apps-meta/unmanage.notes @@ -3,3 +3,5 @@ vim seminar/models/whatever Model.field.related_name = Model.related_name + '_old' # až vyrobíme nový objekt, tak nesmí kolidovat. # related_name se vyhodnocuje za běhu, takže pokud nic nespustíme (celý # blok migrací spustíme najednou), tak nám nevadí, že v tuhle chvíli nefunguje půlka views ap :-) +makemigrations, bez úprav +migrate? From d4b92854c25cd726add0040d2b729da5dcd6d9a0 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 21:57:09 +0100 Subject: [PATCH 17/59] =?UTF-8?q?Pozn=C3=A1mky:=20nezapomenout=20na=20defa?= =?UTF-8?q?ultn=C3=AD=20related=5Fnames?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/unmanage.notes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes index b00cb294..4d863a21 100644 --- a/split-apps-meta/unmanage.notes +++ b/split-apps-meta/unmanage.notes @@ -3,5 +3,7 @@ vim seminar/models/whatever Model.field.related_name = Model.related_name + '_old' # až vyrobíme nový objekt, tak nesmí kolidovat. # related_name se vyhodnocuje za běhu, takže pokud nic nespustíme (celý # blok migrací spustíme najednou), tak nám nevadí, že v tuhle chvíli nefunguje půlka views ap :-) + Nastavit nějak i všechny další závislostní fieldy (mají defaultní related_name!) + - ManyToManyF, OneToOneF, ForeignKey, … makemigrations, bez úprav migrate? From 8cc5864257e3451d5a8e88422b9b42fcf8447205 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 22:09:52 +0100 Subject: [PATCH 18/59] =?UTF-8?q?Je=C5=A1t=C4=9B=20pozn=C3=A1mka=20k=20rel?= =?UTF-8?q?ated=5Fnames?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/unmanage.notes | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes index 4d863a21..d623425f 100644 --- a/split-apps-meta/unmanage.notes +++ b/split-apps-meta/unmanage.notes @@ -5,5 +5,16 @@ vim seminar/models/whatever # blok migrací spustíme najednou), tak nám nevadí, že v tuhle chvíli nefunguje půlka views ap :-) Nastavit nějak i všechny další závislostní fieldy (mají defaultní related_name!) - ManyToManyF, OneToOneF, ForeignKey, … + Nevím proč, ale když nebyly unikátní, tak se to potlouklo:: + seminar.Prijemce.osoba: (fields.E304) Reverse accessor 'Osoba.osoba_old' for 'seminar.Prijemce.osoba' clashes with reverse accessor for 'seminar.Resitel.osoba'. + HINT: Add or change a related_name argument to the definition for 'seminar.Prijemce.osoba' or 'seminar.Resitel.osoba'. + seminar.Prijemce.osoba: (fields.E305) Reverse query name for 'seminar.Prijemce.osoba' clashes with reverse query name for 'seminar.Resitel.osoba'. + HINT: Add or change a related_name argument to the definition for 'seminar.Prijemce.osoba' or 'seminar.Resitel.osoba'. + seminar.Resitel.osoba: (fields.E304) Reverse accessor 'Osoba.osoba_old' for 'seminar.Resitel.osoba' clashes with reverse accessor for 'seminar.Prijemce.osoba'. + HINT: Add or change a related_name argument to the definition for 'seminar.Resitel.osoba' or 'seminar.Prijemce.osoba'. + seminar.Resitel.osoba: (fields.E305) Reverse query name for 'seminar.Resitel.osoba' clashes with reverse query name for 'seminar.Prijemce.osoba'. + HINT: Add or change a related_name argument to the definition for 'seminar.Resitel.osoba' or 'seminar.Prijemce.osoba'. + Snadné řešení: dočasné related names mít unikátní. Stejně to nikoho nezajímá. + makemigrations, bez úprav migrate? From 17b4a4764c1f42be7ed52e5c7bd94850cc3e7007 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 22:10:25 +0100 Subject: [PATCH 19/59] =?UTF-8?q?Vyr=C3=A1b=C3=ADme=20person=C3=A1ln=C3=AD?= =?UTF-8?q?=20v=20person=C3=A1ln=C3=ADch=20+=20oprava=20sem/models.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nezapomenout na závislost v migraci! --- personalni/migrations/0003_initial.py | 124 +++++++ personalni/models.py | 453 ++++++++++++++++++++++++++ seminar/models/personalni.py | 13 +- 3 files changed, 584 insertions(+), 6 deletions(-) create mode 100644 personalni/migrations/0003_initial.py create mode 100644 personalni/models.py diff --git a/personalni/migrations/0003_initial.py b/personalni/migrations/0003_initial.py new file mode 100644 index 00000000..3c445cab --- /dev/null +++ b/personalni/migrations/0003_initial.py @@ -0,0 +1,124 @@ +# Generated by Django 4.2.8 on 2024-03-12 21:10 + +from django.db import migrations, models +import django.utils.timezone +import django_countries.fields +import imagekit.models.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('personalni', '0002_auto_20240312_2118'), + ('seminar', '0118_alter_organizator_options_alter_osoba_options_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Organizator', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('vytvoreno', models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False, verbose_name='Vytvořeno')), + ('organizuje_od', models.DateTimeField(blank=True, null=True, verbose_name='Organizuje od')), + ('organizuje_do', models.DateTimeField(blank=True, null=True, verbose_name='Organizuje do')), + ('studuje', models.CharField(blank=True, help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', 'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo 'Přednáší na MFF'", max_length=256, null=True, verbose_name='Studium aj.')), + ('strucny_popis_organizatora', models.TextField(blank=True, null=True, verbose_name='Stručný popis organizátora')), + ('skola', models.CharField(blank=True, help_text='Škola, např. MFF, VŠCHT, VUT, ... prostě aby se nemuselo psát do studuješkolu, ale jen obor, možnost zobrazit zvlášť', max_length=256, null=True, verbose_name='Škola, kterou studuje')), + ], + options={ + 'verbose_name': 'Organizátor', + 'verbose_name_plural': 'Organizátoři', + 'ordering': ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'], + 'managed': False, + }, + ), + migrations.CreateModel( + name='Osoba', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('jmeno', models.CharField(max_length=256, verbose_name='jméno')), + ('prijmeni', models.CharField(max_length=256, verbose_name='příjmení')), + ('prezdivka', models.CharField(blank=True, max_length=256, null=True, verbose_name='přezdívka')), + ('pohlavi_muz', models.BooleanField(default=False, verbose_name='pohlaví (muž)')), + ('email', models.EmailField(blank=True, default='', max_length=256, verbose_name='e-mail')), + ('telefon', models.CharField(blank=True, default='', max_length=256, verbose_name='telefon')), + ('datum_narozeni', models.DateField(blank=True, null=True, verbose_name='datum narození')), + ('datum_souhlasu_udaje', models.DateField(blank=True, help_text='Datum souhlasu se zpracováním osobních údajů', null=True, verbose_name='datum souhlasu (údaje)')), + ('datum_souhlasu_zasilani', models.DateField(blank=True, help_text='Datum souhlasu se zasíláním MFF materiálů', null=True, verbose_name='datum souhlasu (spam)')), + ('datum_registrace', models.DateField(default=django.utils.timezone.now, verbose_name='datum registrace do semináře')), + ('ulice', models.CharField(blank=True, default='', max_length=256, verbose_name='ulice')), + ('mesto', models.CharField(blank=True, default='', max_length=256, verbose_name='město')), + ('psc', models.CharField(blank=True, default='', max_length=32, verbose_name='PSČ')), + ('stat', django_countries.fields.CountryField(default='CZ', help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)', max_length=2, verbose_name='stát')), + ('jak_se_dozvedeli', models.TextField(blank=True, verbose_name='Jak se dozvěděli')), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k osobě (plain text)', verbose_name='neveřejná poznámka')), + ('foto', imagekit.models.fields.ProcessedImageField(blank=True, help_text='Vlož fotografii osoby o libovolné velikosti', null=True, upload_to='image_osoby/velke/%Y/', verbose_name='Fotografie osoby')), + ], + options={ + 'verbose_name': 'Osoba', + 'verbose_name_plural': 'Osoby', + 'db_table': 'seminar_osoby', + 'ordering': ['prijmeni', 'jmeno'], + 'managed': False, + }, + ), + migrations.CreateModel( + name='Prijemce', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k příemci čísel (plain text)', verbose_name='neveřejná poznámka')), + ('zasilat_cislo_emailem', models.BooleanField(default=False, help_text='True pokud chce příjemce dostávat číslo emailem', verbose_name='zasílat číslo emailem')), + ], + options={ + 'verbose_name': 'příjemce', + 'verbose_name_plural': 'příjemce', + 'db_table': 'seminar_prijemce', + 'managed': False, + }, + ), + migrations.CreateModel( + name='Resitel', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('prezdivka_resitele', models.CharField(blank=True, max_length=256, null=True, unique=True, verbose_name='přezdívka řešitele')), + ('rok_maturity', models.IntegerField(blank=True, null=True, verbose_name='rok maturity')), + ('zasilat', models.CharField(choices=[('domu', 'Domů'), ('do_skoly', 'Do školy'), ('nikam', 'Nezasílat papírově')], default='domu', max_length=32, verbose_name='kam zasílat')), + ('zasilat_cislo_emailem', models.BooleanField(default=False, help_text='True pokud chce řešitel dostávat číslo emailem', verbose_name='zasílat číslo emailem')), + ('zasilat_cislo_papirove', models.BooleanField(default=True, help_text='True pokud chce řešitel dostávat číslo papírově', verbose_name='zasílat číslo papírově')), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k řešiteli (plain text)', verbose_name='neveřejná poznámka')), + ], + options={ + 'verbose_name': 'Řešitel', + 'verbose_name_plural': 'Řešitelé', + 'db_table': 'seminar_resitele', + 'ordering': ['osoba'], + 'managed': False, + }, + ), + migrations.CreateModel( + name='Skola', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('aesop_id', models.CharField(blank=True, default='', help_text='Aesopi ID typu "izo:..." nebo "aesop:..."', max_length=32, verbose_name='Aesop ID')), + ('izo', models.CharField(blank=True, help_text='IZO školy (jen české školy)', max_length=32, verbose_name='IZO')), + ('nazev', models.CharField(help_text='Celý název školy', max_length=256, verbose_name='název')), + ('kratky_nazev', models.CharField(blank=True, help_text='Zkrácený název pro zobrazení ve výsledkovce', max_length=256, verbose_name='zkrácený název')), + ('ulice', models.CharField(max_length=256, verbose_name='ulice')), + ('mesto', models.CharField(max_length=256, verbose_name='město')), + ('psc', models.CharField(max_length=32, verbose_name='PSČ')), + ('stat', django_countries.fields.CountryField(default='CZ', help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)', max_length=2, verbose_name='stát')), + ('je_zs', models.BooleanField(default=True, verbose_name='základní stupeň')), + ('je_ss', models.BooleanField(default=True, verbose_name='střední stupeň')), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka ke škole (plain text)', verbose_name='neveřejná poznámka')), + ], + options={ + 'verbose_name': 'Škola', + 'verbose_name_plural': 'Školy', + 'db_table': 'seminar_skoly', + 'ordering': ['mesto', 'nazev'], + 'managed': False, + }, + ), + ] diff --git a/personalni/models.py b/personalni/models.py new file mode 100644 index 00000000..743e18b8 --- /dev/null +++ b/personalni/models.py @@ -0,0 +1,453 @@ +# -*- coding: utf-8 -*- +import logging + +from django.db import models +from django.utils import timezone +from django.conf import settings +from django.core.exceptions import ValidationError +from imagekit.models import ImageSpecField, ProcessedImageField +from imagekit.processors import ResizeToFit, Transpose + +from django_countries.fields import CountryField + +from reversion import revisions as reversion + +from seminar.models.base import SeminarModelBase + +logger = logging.getLogger(__name__) + + +@reversion.register(ignore_duplicates=True) +class Osoba(SeminarModelBase): + + class Meta: + db_table = 'seminar_osoby' + verbose_name = 'Osoba' + verbose_name_plural = 'Osoby' + ordering = ['prijmeni','jmeno'] + managed = False + + id = models.AutoField(primary_key = True) + + jmeno = models.CharField('jméno', max_length=256) + + prijmeni = models.CharField('příjmení', max_length=256) + + prezdivka = models.CharField('přezdívka', blank=True, null=True, max_length=256) + + # User, pokud má na webu účet + user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=True, null=True, + verbose_name='uživatel', on_delete=models.DO_NOTHING) + + # Pohlaví. Že ho neznáme se snad nestane (a ušetří to práci při programování) + pohlavi_muz = models.BooleanField('pohlaví (muž)', default=False) + + email = models.EmailField('e-mail', max_length=256, blank=True, default='') + + telefon = models.CharField('telefon', max_length=256, blank=True, default='') + + datum_narozeni = models.DateField('datum narození', blank=True, null=True) + + # NULL dokud nedali souhlas + datum_souhlasu_udaje = models.DateField('datum souhlasu (údaje)', blank=True, null=True, + help_text='Datum souhlasu se zpracováním osobních údajů') + + # NULL dokud nedali souhlas + datum_souhlasu_zasilani = models.DateField('datum souhlasu (spam)', blank=True, null=True, + help_text='Datum souhlasu se zasíláním MFF materiálů') + + # Alespoň odhad (rok či i měsíc) + datum_registrace = models.DateField('datum registrace do semináře', default=timezone.now) + + # Ulice může být i jen číslo + ulice = models.CharField('ulice', max_length=256, blank=True, default='') + + mesto = models.CharField('město', max_length=256, blank=True, default='') + + psc = models.CharField('PSČ', max_length=32, blank=True, default='') + + # ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) + # Ekvivalentní s CharField(max_length=2, default='CZ', ...) + stat = CountryField('stát', default='CZ', + help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') + + jak_se_dozvedeli = models.TextField('Jak se dozvěděli', blank=True) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k osobě (plain text)') + + foto = ProcessedImageField(verbose_name='Fotografie osoby', + upload_to='image_osoby/velke/%Y/', null = True, blank = True, + help_text = 'Vlož fotografii osoby o libovolné velikosti', + processors=[ + Transpose(Transpose.AUTO), + ResizeToFit(500, 500, upscale=False) + ], + options={'quality': 95}) + foto_male = ImageSpecField(source='foto', + processors=[ + ResizeToFit(200, 200, upscale=False) + ], + options={'quality': 95}) + + # má OneToOneField nejvýše s: + # Resitel + # Prijemce + # Organizator + + def plne_jmeno(self): + return '{} {}'.format(self.jmeno, self.prijmeni) + + def inicial_krestni(self): + jmena = self.jmeno.split() + return " ".join(['{}.'.format(jmeno[0]) for jmeno in jmena]) + + def __str__(self): + return self.plne_jmeno() + + # Overridujeme save Osoby, aby když si změní e-mail, aby se projevil i v + # Userovi (a tak se dal poslat mail s resetem hesla) + def save(self, *args, **kwargs): + if self.user is not None: + u = self.user + # U svatého tučňáka, prosím ať tohle funguje. + # (Takhle se kódit asi nemá...) + u.email = self.email + u.save() + super().save() + +# +# Mělo by být částečně vytaženo z Aesopa +# viz https://ovvp.mff.cuni.cz/wiki/aesop/export-skol. +# + +@reversion.register(ignore_duplicates=True) +class Skola(SeminarModelBase): + + class Meta: + db_table = 'seminar_skoly' + verbose_name = 'Škola' + verbose_name_plural = 'Školy' + ordering = ['mesto', 'nazev'] + managed = False + + # Interní ID + id = models.AutoField(primary_key = True) + + # Aesopi ID "izo:..." nebo "aesop:..." + # NULL znamená v exportu do aesopa "ufo" + aesop_id = models.CharField('Aesop ID', max_length=32, blank=True, default='', + help_text='Aesopi ID typu "izo:..." nebo "aesop:..."') + + # IZO školy (jen české školy) + izo = models.CharField('IZO', max_length=32, blank=True, + help_text='IZO školy (jen české školy)') + + # Celý název školy + nazev = models.CharField('název', max_length=256, + help_text='Celý název školy') + + # Zkraceny nazev pro zobrazení ve výsledkovce, volitelné. + # Není v Aesopovi, musíme vytvářet sami. + kratky_nazev = models.CharField('zkrácený název', max_length=256, blank=True, + help_text="Zkrácený název pro zobrazení ve výsledkovce") + + # Ulice může být jen číslo + ulice = models.CharField('ulice', max_length=256) + + mesto = models.CharField('město', max_length=256) + + psc = models.CharField('PSČ', max_length=32) + + # ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) + # Ekvivalentní s CharField(max_length=2, default='CZ', ...) + stat = CountryField('stát', default='CZ', + help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') + + # Jaké vzdělání škpla poskytuje? + je_zs = models.BooleanField('základní stupeň', default=True) + je_ss = models.BooleanField('střední stupeň', default=True) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka ke škole (plain text)') + + kontaktni_osoba = models.ForeignKey(Osoba, verbose_name='Kontaktní osoba', + blank=True, null=True, on_delete=models.SET_NULL) + + def __str__(self): + return '{}, {}, {}'.format(self.nazev, self.ulice, self.mesto) + +class Prijemce(SeminarModelBase): + class Meta: + db_table = 'seminar_prijemce' + verbose_name = 'příjemce' + verbose_name_plural = 'příjemce' + managed = False + + + # Interní ID + id = models.AutoField(primary_key = True) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k příemci čísel (plain text)') + + osoba = models.OneToOneField(Osoba, verbose_name='komu', blank=False, null=False, + help_text='Které osobě či na jakou adresu se mají zasílat čísla', + on_delete=models.CASCADE) + + zasilat_cislo_emailem = models.BooleanField('zasílat číslo emailem', help_text='True pokud chce příjemce dostávat číslo emailem', default=False) + + # FIXME: možná chceme něco jako vazbu na osobu XOR školu a počet kusů k zaslání + # FIXME: a možná taky posílání na mail a možná taky přes něj chceme posílat i řešitelům + + def __str__(self): + return self.osoba.plne_jmeno() + + +@reversion.register(ignore_duplicates=True) +class Resitel(SeminarModelBase): + + class Meta: + db_table = 'seminar_resitele' + verbose_name = 'Řešitel' + verbose_name_plural = 'Řešitelé' + ordering = ['osoba'] + managed = False + + # Interní ID + id = models.AutoField(primary_key = True) + + prezdivka_resitele = models.CharField('přezdívka řešitele', blank=True, null=True, max_length=256, unique=True) + + osoba = models.OneToOneField(Osoba, blank=False, null=False, verbose_name='osoba', + on_delete=models.PROTECT) + + + skola = models.ForeignKey(Skola, blank=True, null=True, verbose_name='škola', + on_delete=models.SET_NULL) + + # Očekávaný rok maturity a vyřazení z aktivních řešitelů + rok_maturity = models.IntegerField('rok maturity', blank=True, null=True) + + ZASILAT_DOMU = 'domu' + ZASILAT_DO_SKOLY = 'do_skoly' + ZASILAT_NIKAM = 'nikam' + ZASILAT_CHOICES = [ + (ZASILAT_DOMU, 'Domů'), + (ZASILAT_DO_SKOLY, 'Do školy'), + (ZASILAT_NIKAM, 'Nezasílat papírově'), + ] + + zasilat = models.CharField('kam zasílat', max_length=32, choices=ZASILAT_CHOICES, blank=False, default=ZASILAT_DOMU) + + zasilat_cislo_emailem = models.BooleanField('zasílat číslo emailem', help_text='True pokud chce řešitel dostávat číslo emailem', default=False) + + zasilat_cislo_papirove = models.BooleanField('zasílat číslo papírově', help_text='True pokud chce řešitel dostávat číslo papírově', default=True) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k řešiteli (plain text)') + + + def export_row(self): + "Slovnik pro pouziti v AESOP exportu" + return { + 'id': self.id, + 'name': self.osoba.jmeno, + 'surname': self.osoba.prijmeni, + 'gender': 'M' if self.osoba.pohlavi_muz else 'F', + 'born': self.osoba.datum_narozeni.isoformat() if self.osoba.datum_narozeni else '', + 'email': self.osoba.email, + 'end-year': self.rok_maturity or '', + + 'street': self.osoba.ulice, + 'town': self.osoba.mesto, + 'postcode': self.osoba.psc, + 'country': self.osoba.stat, + + 'spam-flag': 'Y' if self.osoba.datum_souhlasu_zasilani else '', + 'spam-date': self.osoba.datum_souhlasu_zasilani.isoformat() if self.osoba.datum_souhlasu_zasilani else '', + + 'school': self.skola.aesop_id if self.skola else '', + 'school-name': str(self.skola) if self.skola else 'Skola neni znama', + } + + def rocnik(self, rocnik): + """Vrati skolni rocnik resitele pro zadany Rocnik. + Vraci '' pro neznamy rok maturity resitele, Z* pro ekvivalent ZŠ.""" + if self.rok_maturity is None: + return '' + rozdil = 5 - (self.rok_maturity - rocnik.prvni_rok) + if rozdil >= 1: + return str(rozdil) + else: + return 'Z' + str(rozdil + 9) + + def vsechny_body(self): + "Spočítá body odjakživa." + vsechna_reseni = self.reseni_set.all() + from .odevzdavatko import Hodnoceni + vsechna_hodnoceni = Hodnoceni.objects.filter( + reseni__in=vsechna_reseni) + return sum(h.body for h in list(vsechna_hodnoceni) if h.body is not None) + + + def get_titul(self, body=None): + "Vrati titul jako řetězec." + + # Nejprve si zadefinujeme titul + from enum import Enum + from functools import total_ordering + @total_ordering + class Titul(Enum): + """ Třída reprezentující možné tituly. Hodnoty jsou dvojice (dolní hranice, stringifikace). """ + nic = (0, '') + bc = (20, 'Bc.') + mgr = (50, 'Mgr.') + dr = (100, 'Dr.') + doc = (200, 'Doc.') + prof = (500, 'Prof.') + akad = (1000, 'Akad.') + + def __lt__(self, other): + return True if self.value[0] < other.value[0] else False + def __eq__(self, other): # Měla by být implicitní, ale klidně explicitně. + return True if self.value[0] == other.value[0] else False + + def __str__(self): + return self.value[1] + + @classmethod + def z_bodu(cls, body): + aktualni = cls.nic + # TODO: ověřit, že to funguje + for titul in cls: # Kdyžtak použít __members__.items() + if titul.value[0] <= body: + aktualni = titul + else: + break + return aktualni + + # Hledáme body v databázi + # V listopadu 2020 jsme se na filosofické schůzce shodli o změně hranic titulů: + # - body z 25. ročníku a dříve byly shledány dvakrát hodnotnějšími + # - 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(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): + return sum(h.body for h in hh if h.body is not None) + + stare_body = body_z_hodnoceni(hodnoceni_do_25_rocniku) + if body is None: + nove_body = body_z_hodnoceni(novejsi_hodnoceni) + else: + # Zjistíme, kolik bodů jsou staré, tedy hodnotnější + nove_body = max(0, body - stare_body) # Všechny body nad počet původních hodnotnějších + stare_body = min(stare_body, body) # Skutečný počet hodnotnějších bodů + logicke_body = 2*stare_body + nove_body + + + # Titul se určí následovně: + # - Pokud se řeší body, které jsou starší, než do 26 ročníku (včetně), dáváme tituly postaru. + # - Jinak dáváme tituly po novu... + # - ... ale titul se nesmí odebrat, pokud se zmenšil. + def titul_do_26_rocniku(body): + """ Původní hranice bodů za tituly """ + if body < 10: + return Titul.nic + elif body < 20: + return Titul.bc + elif body < 50: + return Titul.mgr + elif body < 100: + return Titul.dr + elif body < 200: + return Titul.doc + elif body < 500: + return Titul.prof + else: + return Titul.akad + + from .odevzdavatko import Hodnoceni + 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) + ) + starsi_body = body_z_hodnoceni(hodnoceni_do_26_rocniku) + if body is not None: + # Ještě z toho vybereme ty správně staré body + novejsi_body = max(0, body - starsi_body) + starsi_body = min(starsi_body, body) + + # Titul pro 26. ročník + stary_titul = titul_do_26_rocniku(starsi_body) + # Titul podle aktuálních pravidel + novy_titul = Titul.z_bodu(logicke_body) + + if novejsi_body == 0: + # Žádné nové body -- titul podle starých pravidel + return str(stary_titul) + return str(max(novy_titul, stary_titul)) + + + def __str__(self): + return self.osoba.plne_jmeno() + + +@reversion.register(ignore_duplicates=True) +class Organizator(SeminarModelBase): + + class Meta: + verbose_name = 'Organizátor' + verbose_name_plural = 'Organizátoři' + # Řadí aktivní orgy na začátek, pod tím v pořadí od nejstarších neaktivní orgy. + # TODO: Chtěl bych spíš mít nejstarší orgy dole. + # TODO: Zohledňovat přezdívky? + # TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu + ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] + managed = False + + osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org', + help_text='osobní údaje organizátora', null=False, blank=False, + on_delete=models.PROTECT) + + vytvoreno = models.DateTimeField( + 'Vytvořeno', + default=timezone.now, + blank=True, + editable=False + ) + + # Ne, date to nebude. SQLite: invalid literal for int() with base 10: b'17 23:00:00' + organizuje_od = models.DateTimeField('Organizuje od', blank=True, null=True) + + organizuje_do = models.DateTimeField('Organizuje do', blank=True, null=True) + + studuje = models.CharField('Studium aj.', max_length = 256, + null = True, blank = True, + help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', " + "'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo " + "'Přednáší na MFF'") + + strucny_popis_organizatora = models.TextField('Stručný popis organizátora', + null = True, blank = True) + + skola = models.CharField('Škola, kterou studuje', max_length = 256, null=True, blank=True, + help_text="Škola, např. MFF, VŠCHT, VUT, ... prostě aby se nemuselo psát do studuje" + "školu, ale jen obor, možnost zobrazit zvlášť") + + def clean(self): + if self.organizuje_od and self.organizuje_do and (self.organizuje_od > self.organizuje_do): + raise ValidationError("Organizátor nemůže skončit s organizováním dříve než začal!") + super().clean() + + def __str__(self): + if self.osoba.prezdivka: + return "{} '{}' {}".format(self.osoba.jmeno, + self.osoba.prezdivka, + self.osoba.prijmeni) + else: + return "{} {}".format(self.osoba.jmeno, self.osoba.prijmeni) diff --git a/seminar/models/personalni.py b/seminar/models/personalni.py index b245c2a4..5286e1be 100644 --- a/seminar/models/personalni.py +++ b/seminar/models/personalni.py @@ -37,7 +37,8 @@ class Osoba(SeminarModelBase): # User, pokud má na webu účet user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=True, null=True, - verbose_name='uživatel', on_delete=models.DO_NOTHING) + verbose_name='uživatel', on_delete=models.DO_NOTHING, + related_name='user_old') # Pohlaví. Že ho neznáme se snad nestane (a ušetří to práci při programování) pohlavi_muz = models.BooleanField('pohlaví (muž)', default=False) @@ -172,7 +173,7 @@ class Skola(SeminarModelBase): help_text='Neveřejná poznámka ke škole (plain text)') kontaktni_osoba = models.ForeignKey(Osoba, verbose_name='Kontaktní osoba', - blank=True, null=True, on_delete=models.SET_NULL) + blank=True, null=True, on_delete=models.SET_NULL, related_name='kontaktni_osoba_old') def __str__(self): return '{}, {}, {}'.format(self.nazev, self.ulice, self.mesto) @@ -193,7 +194,7 @@ class Prijemce(SeminarModelBase): osoba = models.OneToOneField(Osoba, verbose_name='komu', blank=False, null=False, help_text='Které osobě či na jakou adresu se mají zasílat čísla', - on_delete=models.CASCADE) + on_delete=models.CASCADE, related_name='osobad_old1') zasilat_cislo_emailem = models.BooleanField('zasílat číslo emailem', help_text='True pokud chce příjemce dostávat číslo emailem', default=False) @@ -220,11 +221,11 @@ class Resitel(SeminarModelBase): prezdivka_resitele = models.CharField('přezdívka řešitele', blank=True, null=True, max_length=256, unique=True) osoba = models.OneToOneField(Osoba, blank=False, null=False, verbose_name='osoba', - on_delete=models.PROTECT) + on_delete=models.PROTECT, related_name='osoba_old2') skola = models.ForeignKey(Skola, blank=True, null=True, verbose_name='škola', - on_delete=models.SET_NULL) + on_delete=models.SET_NULL, related_name='skola_old3') # Očekávaný rok maturity a vyřazení z aktivních řešitelů rok_maturity = models.IntegerField('rok maturity', blank=True, null=True) @@ -399,7 +400,7 @@ class Resitel(SeminarModelBase): @reversion.register(ignore_duplicates=True) class Organizator(SeminarModelBase): - osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org_old', + osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org_old4', help_text='osobní údaje organizátora', null=False, blank=False, on_delete=models.PROTECT) From 4182bd542edcc1928de46608f4e4cba071795452 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 22:15:12 +0100 Subject: [PATCH 20/59] =?UTF-8?q?Oprava=20nejv=C3=ADc=20haluz=20migrace,?= =?UTF-8?q?=20wtf,=20nev=C3=ADm=20co=20d=C4=9Bl=C3=A1m?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Best commit. --- various/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/various/models.py b/various/models.py index eb89ab25..f551a652 100644 --- a/various/models.py +++ b/various/models.py @@ -9,7 +9,7 @@ from django.urls import reverse # Whatever, makemigrations chce default, má ho mít lol. def _default_aktualni_cislo(): - return Cislo.objects.last() + return Cislo.objects.last().id @reversion.register(ignore_duplicates=True) class Nastaveni(SingletonModel): From 457236c21a5e754d69f137362a16248c0567f002 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 12 Mar 2024 22:25:32 +0100 Subject: [PATCH 21/59] Vzor migrace pro create --- split-apps-meta/create-ct-hack.py | 52 +++++++++++++++++++++++++++++++ split-apps-meta/create.notes | 1 + 2 files changed, 53 insertions(+) create mode 100644 split-apps-meta/create-ct-hack.py diff --git a/split-apps-meta/create-ct-hack.py b/split-apps-meta/create-ct-hack.py new file mode 100644 index 00000000..fb603f6f --- /dev/null +++ b/split-apps-meta/create-ct-hack.py @@ -0,0 +1,52 @@ +# Správná migrace vypadá takto: +# Generated by Django 3.2.23 on 2023-12-11 19:19 + +def nastav_nove_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + old_ct = ContentType.objects.filter(app_label='seminar', model='nastaveni') + # Pozn: tohle může být prázdné (pokud Django nedostalo signál o dokončených migracích, např. při vyrábění databáze z nuly) + # Ale .update to nevadí… + old_ct.update(app_label='various') + +def nastav_stare_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + new_ct = ContentType.objects.filter(app_label='various', model='nastaveni') + new_ct.update(app_label='seminar') + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('seminar', '0115_alter_nastaveni_options'), + ] + + operations = [ + migrations.CreateModel( + name='Nastaveni', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cena_sous', models.IntegerField(default=1000, verbose_name='Účastnický poplatek za soustředění')), + ], + options={ + 'verbose_name': 'Nastavení semináře', + 'db_table': 'seminar_nastaveni', + 'managed': False, + }, + ), + migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes), + ] + + + +#Hack: zkrácení +def nastav_nove_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + for m in ('resitel', 'organizator', 'osoba', 'skola', 'prijemce'): + ContentType.objects.filter(app_label='seminar', model=m).update(app_label='personalni') + +def nastav_stare_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + for m in ('resitel', 'organizator', 'osoba', 'skola', 'prijemce'): + ContentType.objects.filter(app_label='personalni', model=m).update(app_label='seminar') + diff --git a/split-apps-meta/create.notes b/split-apps-meta/create.notes index 9abae94d..43872d68 100644 --- a/split-apps-meta/create.notes +++ b/split-apps-meta/create.notes @@ -1,4 +1,5 @@ Prostě zkopírovat vedle, s původními (=správnými) related names. makemigrations +! Doplnit hack kolem content-types doplnit závislost na unmanage migrate From a23daf8b9713a30751766580a060a3ee4b4b7ff9 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 21:35:52 +0100 Subject: [PATCH 22/59] =?UTF-8?q?Dal=C5=A1=C3=AD=20pokus=20o=20migraci,=20?= =?UTF-8?q?I=20guess=20(po=20t=C3=BDdnu,=20lol)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- personalni/migrations/0003_initial.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/personalni/migrations/0003_initial.py b/personalni/migrations/0003_initial.py index 3c445cab..fc586ff6 100644 --- a/personalni/migrations/0003_initial.py +++ b/personalni/migrations/0003_initial.py @@ -5,6 +5,17 @@ import django.utils.timezone import django_countries.fields import imagekit.models.fields +def nastav_nove_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + for m in ('resitel', 'organizator', 'osoba', 'skola', 'prijemce'): + oct = ContentType.objects.filter(app_label='seminar', model=m) + oct.update(app_label='personalni') + +def nastav_stare_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + for m in ('resitel', 'organizator', 'osoba', 'skola', 'prijemce'): + nct = ContentType.objects.filter(app_label='personalni', model=m) + nct.update(app_label='seminar') class Migration(migrations.Migration): @@ -16,6 +27,7 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes), migrations.CreateModel( name='Organizator', fields=[ From 46f1d3d42ddb23d8e0e30c9b061801520eb2c421 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:15:29 +0100 Subject: [PATCH 23/59] I did something! --- various/migrations/0001_initial.py | 1 + .../0004_nastaveni_aktualni_cislo.py | 21 ------------------- various/models.py | 7 +------ 3 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 various/migrations/0004_nastaveni_aktualni_cislo.py diff --git a/various/migrations/0001_initial.py b/various/migrations/0001_initial.py index 38f2a029..43b77171 100644 --- a/various/migrations/0001_initial.py +++ b/various/migrations/0001_initial.py @@ -28,6 +28,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('cena_sous', models.IntegerField(default=1000, verbose_name='Účastnický poplatek za soustředění')), + ('aktualni_cislo', models.ForeignKey(null=True, on_delete=models.deletion.PROTECT, to='seminar.cislo', verbose_name='Aktuální číslo')), ], options={ 'verbose_name': 'Nastavení semináře', diff --git a/various/migrations/0004_nastaveni_aktualni_cislo.py b/various/migrations/0004_nastaveni_aktualni_cislo.py deleted file mode 100644 index feb6bc71..00000000 --- a/various/migrations/0004_nastaveni_aktualni_cislo.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.2.8 on 2024-03-12 20:44 - -from django.db import migrations, models -import django.db.models.deletion -import various.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('seminar', '0118_alter_organizator_options_alter_osoba_options_and_more'), - ('various', '0003_fix_permissions'), - ] - - operations = [ - migrations.AddField( - model_name='nastaveni', - name='aktualni_cislo', - field=models.ForeignKey(default=various.models._default_aktualni_cislo, on_delete=django.db.models.deletion.PROTECT, to='seminar.cislo', verbose_name='Aktuální číslo'), - ), - ] diff --git a/various/models.py b/various/models.py index f551a652..17632c46 100644 --- a/various/models.py +++ b/various/models.py @@ -7,10 +7,6 @@ from seminar.models import Cislo from django.urls import reverse -# Whatever, makemigrations chce default, má ho mít lol. -def _default_aktualni_cislo(): - return Cislo.objects.last().id - @reversion.register(ignore_duplicates=True) class Nastaveni(SingletonModel): @@ -22,8 +18,7 @@ class Nastaveni(SingletonModel): # null=False, on_delete=models.PROTECT) aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo', - null=False, on_delete=models.PROTECT, - default=_default_aktualni_cislo, + null=True, blank=False, on_delete=models.PROTECT, ) cena_sous = models.IntegerField(null=False, From 1f0e6cccf60b7f49a545fbf3bb939a4f1a722a2a Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:47:11 +0100 Subject: [PATCH 24/59] =?UTF-8?q?Dal=C5=A1=C3=AD=20pozn=C3=A1mky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/relink.notes | 4 ++++ split-apps-meta/unmanage.notes | 1 + 2 files changed, 5 insertions(+) create mode 100644 split-apps-meta/relink.notes diff --git a/split-apps-meta/relink.notes b/split-apps-meta/relink.notes new file mode 100644 index 00000000..54d70260 --- /dev/null +++ b/split-apps-meta/relink.notes @@ -0,0 +1,4 @@ +Přepsat všechny odkazy v sousedních aplikacích na novou aplikaci +Naincludovat nové modely v seminar.models kvůli views +makemigrations +migrate diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes index d623425f..846b7314 100644 --- a/split-apps-meta/unmanage.notes +++ b/split-apps-meta/unmanage.notes @@ -15,6 +15,7 @@ vim seminar/models/whatever seminar.Resitel.osoba: (fields.E305) Reverse query name for 'seminar.Resitel.osoba' clashes with reverse query name for 'seminar.Prijemce.osoba'. HINT: Add or change a related_name argument to the definition for 'seminar.Resitel.osoba' or 'seminar.Prijemce.osoba'. Snadné řešení: dočasné related names mít unikátní. Stejně to nikoho nezajímá. + !! Zkontrolovat, že všechno má nastavenou db_table (jinak se to potom pokusí vybastlit jméno tabulky podle aplikace…) makemigrations, bez úprav migrate? From 9e21b2ca1a88f08897e7b715fcee6d331efd0595 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:47:45 +0100 Subject: [PATCH 25/59] relink --- ...tor_alter_korekturovanepdf_org_and_more.py | 30 +++++++ korektury/models.py | 2 +- .../migrations/0014_alter_prednaska_org.py | 20 +++++ prednasky/models.py | 3 +- .../0119_alter_konfera_ucastnici_and_more.py | 85 +++++++++++++++++++ seminar/models/__init__.py | 2 +- seminar/models/novinky.py | 4 +- seminar/models/odevzdavatko.py | 6 +- seminar/models/soustredeni.py | 14 +-- seminar/models/treenode.py | 4 +- seminar/models/tvorba.py | 12 +-- .../0005_alter_odpoveducastnika_resitel.py | 20 +++++ sifrovacka/models.py | 2 +- 13 files changed, 180 insertions(+), 24 deletions(-) create mode 100644 korektury/migrations/0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more.py create mode 100644 prednasky/migrations/0014_alter_prednaska_org.py create mode 100644 seminar/migrations/0119_alter_konfera_ucastnici_and_more.py create mode 100644 sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py diff --git a/korektury/migrations/0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more.py b/korektury/migrations/0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more.py new file mode 100644 index 00000000..4e063a89 --- /dev/null +++ b/korektury/migrations/0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.11 on 2024-03-19 21:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0003_initial'), + ('korektury', '0021_auto_20240312_2124'), + ] + + operations = [ + migrations.AlterField( + model_name='komentar', + name='autor', + field=models.ForeignKey(blank=True, help_text='Autor komentáře', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'), + ), + migrations.AlterField( + model_name='korekturovanepdf', + name='org', + field=models.ForeignKey(blank=True, default=None, help_text='Zodpovědný organizátor za obsah', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'), + ), + migrations.AlterField( + model_name='oprava', + name='autor', + field=models.ForeignKey(blank=True, help_text='Autor opravy', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'), + ), + ] diff --git a/korektury/models.py b/korektury/models.py index c9d47dfa..ca1bb877 100644 --- a/korektury/models.py +++ b/korektury/models.py @@ -20,7 +20,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.utils.functional import cached_property from django.utils.text import get_valid_filename -from seminar.models import Organizator +from personalni.models import Organizator import subprocess from reversion import revisions as reversion diff --git a/prednasky/migrations/0014_alter_prednaska_org.py b/prednasky/migrations/0014_alter_prednaska_org.py new file mode 100644 index 00000000..09742377 --- /dev/null +++ b/prednasky/migrations/0014_alter_prednaska_org.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.11 on 2024-03-19 21:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0003_initial'), + ('prednasky', '0013_auto_20240312_2124'), + ] + + operations = [ + migrations.AlterField( + model_name='prednaska', + name='org', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='personalni.organizator'), + ), + ] diff --git a/prednasky/models.py b/prednasky/models.py index dcf44cbc..7045f4d5 100644 --- a/prednasky/models.py +++ b/prednasky/models.py @@ -2,7 +2,8 @@ from django.db import models -from seminar.models import Organizator, Soustredeni +from seminar.models import Soustredeni +from personalni.models import Organizator STAV_NAVRH = 1 STAV_BUDE = 2 diff --git a/seminar/migrations/0119_alter_konfera_ucastnici_and_more.py b/seminar/migrations/0119_alter_konfera_ucastnici_and_more.py new file mode 100644 index 00000000..31457997 --- /dev/null +++ b/seminar/migrations/0119_alter_konfera_ucastnici_and_more.py @@ -0,0 +1,85 @@ +# Generated by Django 4.2.11 on 2024-03-19 21:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0003_initial'), + ('seminar', '0118_alter_organizator_options_alter_osoba_options_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='konfera', + name='ucastnici', + field=models.ManyToManyField(help_text='Seznam účastníků konfery', through='seminar.Konfery_Ucastnici', to='personalni.resitel', verbose_name='účastníci konfery'), + ), + migrations.AlterField( + model_name='konfery_ucastnici', + name='resitel', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='personalni.resitel', verbose_name='řešitel'), + ), + migrations.AlterField( + model_name='novinky', + name='autor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator', verbose_name='Autor novinky'), + ), + migrations.AlterField( + model_name='orgtextnode', + name='organizator', + field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='personalni.organizator', verbose_name='Organizátor'), + ), + migrations.AlterField( + model_name='pohadka', + name='autor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator', verbose_name='Autor pohádky'), + ), + migrations.AlterField( + model_name='problem', + name='autor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='autor_problemu_%(class)s', to='personalni.organizator', verbose_name='autor problému'), + ), + migrations.AlterField( + model_name='problem', + name='garant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='garant_problemu_%(class)s', to='personalni.organizator', verbose_name='garant zadaného problému'), + ), + migrations.AlterField( + model_name='problem', + name='opravovatele', + field=models.ManyToManyField(blank=True, related_name='opravovatele_%(class)s', to='personalni.organizator', verbose_name='opravovatelé'), + ), + migrations.AlterField( + model_name='reseni', + name='resitele', + field=models.ManyToManyField(help_text='Seznam autorů řešení', through='seminar.Reseni_Resitele', to='personalni.resitel', verbose_name='autoři řešení'), + ), + migrations.AlterField( + model_name='reseni_resitele', + name='resitele', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='personalni.resitel', verbose_name='řešitel'), + ), + migrations.AlterField( + model_name='soustredeni', + name='organizatori', + field=models.ManyToManyField(help_text='Seznam organizátorů soustředění', through='seminar.Soustredeni_Organizatori', to='personalni.organizator', verbose_name='Organizátoři soustředění'), + ), + migrations.AlterField( + model_name='soustredeni', + name='ucastnici', + field=models.ManyToManyField(help_text='Seznam účastníků soustředění', through='seminar.Soustredeni_Ucastnici', to='personalni.resitel', verbose_name='účastníci soustředění'), + ), + migrations.AlterField( + model_name='soustredeni_organizatori', + name='organizator', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='personalni.organizator', verbose_name='organizátor'), + ), + migrations.AlterField( + model_name='soustredeni_ucastnici', + name='resitel', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='personalni.resitel', verbose_name='řešitel'), + ), + ] diff --git a/seminar/models/__init__.py b/seminar/models/__init__.py index 6df1478f..e3026a2c 100644 --- a/seminar/models/__init__.py +++ b/seminar/models/__init__.py @@ -1,10 +1,10 @@ from .tvorba import * from .odevzdavatko import * from .base import * -from .personalni import * from .soustredeni import * from .pomocne import * from .treenode import * from .novinky import * from various.models import Nastaveni +from personalni.models import Organizator, Resitel, Skola, Prijemce, Osoba diff --git a/seminar/models/novinky.py b/seminar/models/novinky.py index cee674a8..b67bdfe6 100644 --- a/seminar/models/novinky.py +++ b/seminar/models/novinky.py @@ -4,7 +4,7 @@ from imagekit.processors import ResizeToFit from reversion import revisions as reversion -from . import personalni as pm +from personalni.models import Organizator @reversion.register(ignore_duplicates=True) class Novinky(models.Model): @@ -26,7 +26,7 @@ class Novinky(models.Model): ], options={'quality': 95}) - autor = models.ForeignKey(pm.Organizator, verbose_name='Autor novinky', null=True, + autor = models.ForeignKey(Organizator, verbose_name='Autor novinky', null=True, on_delete=models.SET_NULL) zverejneno = models.BooleanField('Zveřejněno', default=False) diff --git a/seminar/models/odevzdavatko.py b/seminar/models/odevzdavatko.py index 744fe38c..b0dec663 100644 --- a/seminar/models/odevzdavatko.py +++ b/seminar/models/odevzdavatko.py @@ -10,11 +10,11 @@ from django.utils import timezone from django.conf import settings from seminar.models import tvorba as am -from seminar.models import personalni as pm from seminar.models import treenode as tm from seminar.models import base as bm from seminar.utils import vzorecek_na_prepocet, inverze_vzorecku_na_prepocet +from personalni.models import Resitel @reversion.register(ignore_duplicates=True) @@ -34,7 +34,7 @@ class Reseni(bm.SeminarModelBase): problem = models.ManyToManyField(am.Problem, verbose_name='problém', help_text='Problém', through='Hodnoceni') - resitele = models.ManyToManyField(pm.Resitel, verbose_name='autoři řešení', + resitele = models.ManyToManyField(Resitel, verbose_name='autoři řešení', help_text='Seznam autorů řešení', through='Reseni_Resitele') @@ -229,7 +229,7 @@ class Reseni_Resitele(models.Model): # Interní ID id = models.AutoField(primary_key = True) - resitele = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + resitele = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE) diff --git a/seminar/models/soustredeni.py b/seminar/models/soustredeni.py index 03ff5909..275224a3 100644 --- a/seminar/models/soustredeni.py +++ b/seminar/models/soustredeni.py @@ -8,7 +8,7 @@ from reversion import revisions as reversion from django.conf import settings -from . import personalni as pm +from personalni.models import Resitel, Organizator from .base import SeminarModelBase from seminar.models import tvorba as am @@ -42,10 +42,10 @@ class Soustredeni(SeminarModelBase): misto = models.CharField('místo soustředění', max_length=256, blank=True, default='', help_text='Místo (název obce, volitelně též objektu') - ucastnici = models.ManyToManyField(pm.Resitel, verbose_name='účastníci soustředění', + ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci soustředění', help_text='Seznam účastníků soustředění', through='Soustredeni_Ucastnici') - organizatori = models.ManyToManyField(pm.Organizator, + organizatori = models.ManyToManyField(Organizator, verbose_name='Organizátoři soustředění', help_text='Seznam organizátorů soustředění', through='Soustredeni_Organizatori') @@ -92,7 +92,7 @@ class Soustredeni_Ucastnici(SeminarModelBase): # Interní ID id = models.AutoField(primary_key = True) - resitel = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', on_delete=models.PROTECT) @@ -118,7 +118,7 @@ class Soustredeni_Organizatori(SeminarModelBase): # Interní ID id = models.AutoField(primary_key = True) - organizator = models.ForeignKey(pm.Organizator, verbose_name='organizátor', + organizator = models.ForeignKey(Organizator, verbose_name='organizátor', on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', @@ -163,7 +163,7 @@ class Konfera(am.Problem): help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') # FIXME: Umíme omezit jen na účastníky daného soustřeďka? - ucastnici = models.ManyToManyField(pm.Resitel, verbose_name='účastníci konfery', + ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', @@ -204,7 +204,7 @@ class Konfery_Ucastnici(models.Model): # Interní ID id = models.AutoField(primary_key = True) - resitel = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE) diff --git a/seminar/models/treenode.py b/seminar/models/treenode.py index 50261d1a..735501c0 100644 --- a/seminar/models/treenode.py +++ b/seminar/models/treenode.py @@ -9,7 +9,7 @@ from unidecode import unidecode # Používám pro získání ID odkazu (ještě from polymorphic.models import PolymorphicModel -from . import personalni as pm +from personalni.models import Organizator from .pomocne import Text @@ -166,7 +166,7 @@ class OrgTextNode(TreeNode): verbose_name = 'Organizátorský článek (Node)' verbose_name_plural = 'Organizátorské články (Node)' - organizator = models.ForeignKey(pm.Organizator, + organizator = models.ForeignKey(Organizator, null=False, blank=False, on_delete=models.DO_NOTHING, diff --git a/seminar/models/tvorba.py b/seminar/models/tvorba.py index 41def9c4..1dd9db8e 100644 --- a/seminar/models/tvorba.py +++ b/seminar/models/tvorba.py @@ -34,7 +34,7 @@ from polymorphic.models import PolymorphicModel from django.core.mail import EmailMessage from seminar.utils import aktivniResitele -from . import personalni as pm +from personalni.models import Prijemce, Organizator from .base import SeminarModelBase @@ -306,7 +306,7 @@ class Cislo(SeminarModelBase): resitele_vsichni.filter(zasilat_cislo_papirove=True)) paticka_prijemce = "---\nPokud tyto e-maily nechcete nadále dostávat, prosíme, ozvěte se nám na mam@matfyz.cz." - posli(predmet, text_mailu + paticka_prijemce, pm.Prijemce.objects.filter(zasilat_cislo_emailem=True)) + posli(predmet, text_mailu + paticka_prijemce, Prijemce.objects.filter(zasilat_cislo_emailem=True)) def save(self, *args, **kwargs): super().save(*args, **kwargs) @@ -462,15 +462,15 @@ class Problem(SeminarModelBase,PolymorphicModel): poznamka = models.TextField('org poznámky (HTML)', blank=True, help_text='Neveřejný návrh úlohy, návrh řešení, text zadání, poznámky ...') - autor = models.ForeignKey(pm.Organizator, verbose_name='autor problému', + autor = models.ForeignKey(Organizator, verbose_name='autor problému', related_name='autor_problemu_%(class)s', null=True, blank=True, on_delete=models.SET_NULL) - garant = models.ForeignKey(pm.Organizator, verbose_name='garant zadaného problému', + garant = models.ForeignKey(Organizator, verbose_name='garant zadaného problému', related_name='garant_problemu_%(class)s', null=True, blank=True, on_delete=models.SET_NULL) - opravovatele = models.ManyToManyField(pm.Organizator, verbose_name='opravovatelé', + opravovatele = models.ManyToManyField(Organizator, verbose_name='opravovatelé', blank=True, related_name='opravovatele_%(class)s') kod = models.CharField('lokální kód', max_length=32, blank=True, default='', @@ -691,7 +691,7 @@ class Pohadka(SeminarModelBase): id = models.AutoField(primary_key=True) autor = models.ForeignKey( - pm.Organizator, + Organizator, verbose_name="Autor pohádky", # Při nahrávání z TeXu není vyplnění vyžadováno, v adminu je diff --git a/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py new file mode 100644 index 00000000..34b50d4b --- /dev/null +++ b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.11 on 2024-03-19 21:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0003_initial'), + ('sifrovacka', '0004_auto_20240312_2124'), + ] + + operations = [ + migrations.AlterField( + model_name='odpoveducastnika', + name='resitel', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel'), + ), + ] diff --git a/sifrovacka/models.py b/sifrovacka/models.py index 6517c2e0..5bad397f 100644 --- a/sifrovacka/models.py +++ b/sifrovacka/models.py @@ -1,7 +1,7 @@ from django.db import models from django.utils import timezone -from seminar.models.personalni import Resitel +from personalni.models import Resitel # Create your models here. From 53f40e193d06553e220735d34e86095263099f59 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:48:42 +0100 Subject: [PATCH 26/59] =?UTF-8?q?Dopln=C4=9Bn=C3=AD=20chyb=C4=9Bj=C3=ADc?= =?UTF-8?q?=C3=ADho=20jm=C3=A9na=20tabulky=20(do=20p=C5=99edchoz=C3=AD=20m?= =?UTF-8?q?igrace,=20proto=C5=BEe=20yolo)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- personalni/migrations/0003_initial.py | 1 + personalni/models.py | 1 + 2 files changed, 2 insertions(+) diff --git a/personalni/migrations/0003_initial.py b/personalni/migrations/0003_initial.py index fc586ff6..e026182c 100644 --- a/personalni/migrations/0003_initial.py +++ b/personalni/migrations/0003_initial.py @@ -42,6 +42,7 @@ class Migration(migrations.Migration): options={ 'verbose_name': 'Organizátor', 'verbose_name_plural': 'Organizátoři', + 'db_table': 'seminar_organizator', 'ordering': ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'], 'managed': False, }, diff --git a/personalni/models.py b/personalni/models.py index 743e18b8..cff2899e 100644 --- a/personalni/models.py +++ b/personalni/models.py @@ -407,6 +407,7 @@ class Organizator(SeminarModelBase): # TODO: Chtěl bych spíš mít nejstarší orgy dole. # TODO: Zohledňovat přezdívky? # TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu + db_table = 'seminar_organizator' ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] managed = False From e083f74a835991958ff131d72337bd743c184e37 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:49:32 +0100 Subject: [PATCH 27/59] =?UTF-8?q?Dal=C5=A1=C3=AD=20pozn=C3=A1mka?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/relink.notes | 1 + 1 file changed, 1 insertion(+) diff --git a/split-apps-meta/relink.notes b/split-apps-meta/relink.notes index 54d70260..5465c47d 100644 --- a/split-apps-meta/relink.notes +++ b/split-apps-meta/relink.notes @@ -1,4 +1,5 @@ Přepsat všechny odkazy v sousedních aplikacích na novou aplikaci Naincludovat nové modely v seminar.models kvůli views makemigrations + Zkontrolovat přítomnost závislosti na create! migrate From ace30c931e3d4168be0ca5a76bae8b160103e115 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:57:51 +0100 Subject: [PATCH 28/59] =?UTF-8?q?Neimportovat=20z=20mazan=C3=A9ho=20modulu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sifrovacka/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sifrovacka/views.py b/sifrovacka/views.py index 9c4af3ed..960dc366 100644 --- a/sifrovacka/views.py +++ b/sifrovacka/views.py @@ -4,7 +4,7 @@ from django.views.generic import FormView, ListView from seminar.views import formularOKView from .forms import SifrovackaForm from .models import OdpovedUcastnika, SpravnaOdpoved -from seminar.models.personalni import Resitel +from seminar.models import Resitel # Create your views here. From 858b5ce054ffc8f9a9e7fd9193eeaac18aeff3d3 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 22:58:15 +0100 Subject: [PATCH 29/59] =?UTF-8?q?Smaz=C3=A1n=C3=AD,=20makemigrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oba_user_remove_prijemce_osoba_and_more.py | 48 ++ seminar/models/personalni.py | 453 ------------------ 2 files changed, 48 insertions(+), 453 deletions(-) create mode 100644 seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py delete mode 100644 seminar/models/personalni.py diff --git a/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py new file mode 100644 index 00000000..6e4f4612 --- /dev/null +++ b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py @@ -0,0 +1,48 @@ +# Generated by Django 4.2.11 on 2024-03-19 21:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0119_alter_konfera_ucastnici_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='osoba', + name='user', + ), + migrations.RemoveField( + model_name='prijemce', + name='osoba', + ), + migrations.RemoveField( + model_name='resitel', + name='osoba', + ), + migrations.RemoveField( + model_name='resitel', + name='skola', + ), + migrations.RemoveField( + model_name='skola', + name='kontaktni_osoba', + ), + migrations.DeleteModel( + name='Organizator', + ), + migrations.DeleteModel( + name='Osoba', + ), + migrations.DeleteModel( + name='Prijemce', + ), + migrations.DeleteModel( + name='Resitel', + ), + migrations.DeleteModel( + name='Skola', + ), + ] diff --git a/seminar/models/personalni.py b/seminar/models/personalni.py deleted file mode 100644 index 5286e1be..00000000 --- a/seminar/models/personalni.py +++ /dev/null @@ -1,453 +0,0 @@ -# -*- coding: utf-8 -*- -import logging - -from django.db import models -from django.utils import timezone -from django.conf import settings -from django.core.exceptions import ValidationError -from imagekit.models import ImageSpecField, ProcessedImageField -from imagekit.processors import ResizeToFit, Transpose - -from django_countries.fields import CountryField - -from reversion import revisions as reversion - -from .base import SeminarModelBase - -logger = logging.getLogger(__name__) - - -@reversion.register(ignore_duplicates=True) -class Osoba(SeminarModelBase): - - class Meta: - db_table = 'seminar_osoby' - verbose_name = 'Osoba' - verbose_name_plural = 'Osoby' - ordering = ['prijmeni','jmeno'] - managed = False - - id = models.AutoField(primary_key = True) - - jmeno = models.CharField('jméno', max_length=256) - - prijmeni = models.CharField('příjmení', max_length=256) - - prezdivka = models.CharField('přezdívka', blank=True, null=True, max_length=256) - - # User, pokud má na webu účet - user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=True, null=True, - verbose_name='uživatel', on_delete=models.DO_NOTHING, - related_name='user_old') - - # Pohlaví. Že ho neznáme se snad nestane (a ušetří to práci při programování) - pohlavi_muz = models.BooleanField('pohlaví (muž)', default=False) - - email = models.EmailField('e-mail', max_length=256, blank=True, default='') - - telefon = models.CharField('telefon', max_length=256, blank=True, default='') - - datum_narozeni = models.DateField('datum narození', blank=True, null=True) - - # NULL dokud nedali souhlas - datum_souhlasu_udaje = models.DateField('datum souhlasu (údaje)', blank=True, null=True, - help_text='Datum souhlasu se zpracováním osobních údajů') - - # NULL dokud nedali souhlas - datum_souhlasu_zasilani = models.DateField('datum souhlasu (spam)', blank=True, null=True, - help_text='Datum souhlasu se zasíláním MFF materiálů') - - # Alespoň odhad (rok či i měsíc) - datum_registrace = models.DateField('datum registrace do semináře', default=timezone.now) - - # Ulice může být i jen číslo - ulice = models.CharField('ulice', max_length=256, blank=True, default='') - - mesto = models.CharField('město', max_length=256, blank=True, default='') - - psc = models.CharField('PSČ', max_length=32, blank=True, default='') - - # ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) - # Ekvivalentní s CharField(max_length=2, default='CZ', ...) - stat = CountryField('stát', default='CZ', - help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') - - jak_se_dozvedeli = models.TextField('Jak se dozvěděli', blank=True) - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k osobě (plain text)') - - foto = ProcessedImageField(verbose_name='Fotografie osoby', - upload_to='image_osoby/velke/%Y/', null = True, blank = True, - help_text = 'Vlož fotografii osoby o libovolné velikosti', - processors=[ - Transpose(Transpose.AUTO), - ResizeToFit(500, 500, upscale=False) - ], - options={'quality': 95}) - foto_male = ImageSpecField(source='foto', - processors=[ - ResizeToFit(200, 200, upscale=False) - ], - options={'quality': 95}) - - # má OneToOneField nejvýše s: - # Resitel - # Prijemce - # Organizator - - def plne_jmeno(self): - return '{} {}'.format(self.jmeno, self.prijmeni) - - def inicial_krestni(self): - jmena = self.jmeno.split() - return " ".join(['{}.'.format(jmeno[0]) for jmeno in jmena]) - - def __str__(self): - return self.plne_jmeno() - - # Overridujeme save Osoby, aby když si změní e-mail, aby se projevil i v - # Userovi (a tak se dal poslat mail s resetem hesla) - def save(self, *args, **kwargs): - if self.user is not None: - u = self.user - # U svatého tučňáka, prosím ať tohle funguje. - # (Takhle se kódit asi nemá...) - u.email = self.email - u.save() - super().save() - -# -# Mělo by být částečně vytaženo z Aesopa -# viz https://ovvp.mff.cuni.cz/wiki/aesop/export-skol. -# - -@reversion.register(ignore_duplicates=True) -class Skola(SeminarModelBase): - - class Meta: - db_table = 'seminar_skoly' - verbose_name = 'Škola' - verbose_name_plural = 'Školy' - ordering = ['mesto', 'nazev'] - managed = False - - # Interní ID - id = models.AutoField(primary_key = True) - - # Aesopi ID "izo:..." nebo "aesop:..." - # NULL znamená v exportu do aesopa "ufo" - aesop_id = models.CharField('Aesop ID', max_length=32, blank=True, default='', - help_text='Aesopi ID typu "izo:..." nebo "aesop:..."') - - # IZO školy (jen české školy) - izo = models.CharField('IZO', max_length=32, blank=True, - help_text='IZO školy (jen české školy)') - - # Celý název školy - nazev = models.CharField('název', max_length=256, - help_text='Celý název školy') - - # Zkraceny nazev pro zobrazení ve výsledkovce, volitelné. - # Není v Aesopovi, musíme vytvářet sami. - kratky_nazev = models.CharField('zkrácený název', max_length=256, blank=True, - help_text="Zkrácený název pro zobrazení ve výsledkovce") - - # Ulice může být jen číslo - ulice = models.CharField('ulice', max_length=256) - - mesto = models.CharField('město', max_length=256) - - psc = models.CharField('PSČ', max_length=32) - - # ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) - # Ekvivalentní s CharField(max_length=2, default='CZ', ...) - stat = CountryField('stát', default='CZ', - help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') - - # Jaké vzdělání škpla poskytuje? - je_zs = models.BooleanField('základní stupeň', default=True) - je_ss = models.BooleanField('střední stupeň', default=True) - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka ke škole (plain text)') - - kontaktni_osoba = models.ForeignKey(Osoba, verbose_name='Kontaktní osoba', - blank=True, null=True, on_delete=models.SET_NULL, related_name='kontaktni_osoba_old') - - def __str__(self): - return '{}, {}, {}'.format(self.nazev, self.ulice, self.mesto) - -class Prijemce(SeminarModelBase): - class Meta: - db_table = 'seminar_prijemce' - verbose_name = 'příjemce' - verbose_name_plural = 'příjemce' - managed = False - - - # Interní ID - id = models.AutoField(primary_key = True) - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k příemci čísel (plain text)') - - osoba = models.OneToOneField(Osoba, verbose_name='komu', blank=False, null=False, - help_text='Které osobě či na jakou adresu se mají zasílat čísla', - on_delete=models.CASCADE, related_name='osobad_old1') - - zasilat_cislo_emailem = models.BooleanField('zasílat číslo emailem', help_text='True pokud chce příjemce dostávat číslo emailem', default=False) - - # FIXME: možná chceme něco jako vazbu na osobu XOR školu a počet kusů k zaslání - # FIXME: a možná taky posílání na mail a možná taky přes něj chceme posílat i řešitelům - - def __str__(self): - return self.osoba.plne_jmeno() - - -@reversion.register(ignore_duplicates=True) -class Resitel(SeminarModelBase): - - class Meta: - db_table = 'seminar_resitele' - verbose_name = 'Řešitel' - verbose_name_plural = 'Řešitelé' - ordering = ['osoba'] - managed = False - - # Interní ID - id = models.AutoField(primary_key = True) - - prezdivka_resitele = models.CharField('přezdívka řešitele', blank=True, null=True, max_length=256, unique=True) - - osoba = models.OneToOneField(Osoba, blank=False, null=False, verbose_name='osoba', - on_delete=models.PROTECT, related_name='osoba_old2') - - - skola = models.ForeignKey(Skola, blank=True, null=True, verbose_name='škola', - on_delete=models.SET_NULL, related_name='skola_old3') - - # Očekávaný rok maturity a vyřazení z aktivních řešitelů - rok_maturity = models.IntegerField('rok maturity', blank=True, null=True) - - ZASILAT_DOMU = 'domu' - ZASILAT_DO_SKOLY = 'do_skoly' - ZASILAT_NIKAM = 'nikam' - ZASILAT_CHOICES = [ - (ZASILAT_DOMU, 'Domů'), - (ZASILAT_DO_SKOLY, 'Do školy'), - (ZASILAT_NIKAM, 'Nezasílat papírově'), - ] - - zasilat = models.CharField('kam zasílat', max_length=32, choices=ZASILAT_CHOICES, blank=False, default=ZASILAT_DOMU) - - zasilat_cislo_emailem = models.BooleanField('zasílat číslo emailem', help_text='True pokud chce řešitel dostávat číslo emailem', default=False) - - zasilat_cislo_papirove = models.BooleanField('zasílat číslo papírově', help_text='True pokud chce řešitel dostávat číslo papírově', default=True) - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k řešiteli (plain text)') - - - def export_row(self): - "Slovnik pro pouziti v AESOP exportu" - return { - 'id': self.id, - 'name': self.osoba.jmeno, - 'surname': self.osoba.prijmeni, - 'gender': 'M' if self.osoba.pohlavi_muz else 'F', - 'born': self.osoba.datum_narozeni.isoformat() if self.osoba.datum_narozeni else '', - 'email': self.osoba.email, - 'end-year': self.rok_maturity or '', - - 'street': self.osoba.ulice, - 'town': self.osoba.mesto, - 'postcode': self.osoba.psc, - 'country': self.osoba.stat, - - 'spam-flag': 'Y' if self.osoba.datum_souhlasu_zasilani else '', - 'spam-date': self.osoba.datum_souhlasu_zasilani.isoformat() if self.osoba.datum_souhlasu_zasilani else '', - - 'school': self.skola.aesop_id if self.skola else '', - 'school-name': str(self.skola) if self.skola else 'Skola neni znama', - } - - def rocnik(self, rocnik): - """Vrati skolni rocnik resitele pro zadany Rocnik. - Vraci '' pro neznamy rok maturity resitele, Z* pro ekvivalent ZŠ.""" - if self.rok_maturity is None: - return '' - rozdil = 5 - (self.rok_maturity - rocnik.prvni_rok) - if rozdil >= 1: - return str(rozdil) - else: - return 'Z' + str(rozdil + 9) - - def vsechny_body(self): - "Spočítá body odjakživa." - vsechna_reseni = self.reseni_set.all() - from .odevzdavatko import Hodnoceni - vsechna_hodnoceni = Hodnoceni.objects.filter( - reseni__in=vsechna_reseni) - return sum(h.body for h in list(vsechna_hodnoceni) if h.body is not None) - - - def get_titul(self, body=None): - "Vrati titul jako řetězec." - - # Nejprve si zadefinujeme titul - from enum import Enum - from functools import total_ordering - @total_ordering - class Titul(Enum): - """ Třída reprezentující možné tituly. Hodnoty jsou dvojice (dolní hranice, stringifikace). """ - nic = (0, '') - bc = (20, 'Bc.') - mgr = (50, 'Mgr.') - dr = (100, 'Dr.') - doc = (200, 'Doc.') - prof = (500, 'Prof.') - akad = (1000, 'Akad.') - - def __lt__(self, other): - return True if self.value[0] < other.value[0] else False - def __eq__(self, other): # Měla by být implicitní, ale klidně explicitně. - return True if self.value[0] == other.value[0] else False - - def __str__(self): - return self.value[1] - - @classmethod - def z_bodu(cls, body): - aktualni = cls.nic - # TODO: ověřit, že to funguje - for titul in cls: # Kdyžtak použít __members__.items() - if titul.value[0] <= body: - aktualni = titul - else: - break - return aktualni - - # Hledáme body v databázi - # V listopadu 2020 jsme se na filosofické schůzce shodli o změně hranic titulů: - # - body z 25. ročníku a dříve byly shledány dvakrát hodnotnějšími - # - 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(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): - return sum(h.body for h in hh if h.body is not None) - - stare_body = body_z_hodnoceni(hodnoceni_do_25_rocniku) - if body is None: - nove_body = body_z_hodnoceni(novejsi_hodnoceni) - else: - # Zjistíme, kolik bodů jsou staré, tedy hodnotnější - nove_body = max(0, body - stare_body) # Všechny body nad počet původních hodnotnějších - stare_body = min(stare_body, body) # Skutečný počet hodnotnějších bodů - logicke_body = 2*stare_body + nove_body - - - # Titul se určí následovně: - # - Pokud se řeší body, které jsou starší, než do 26 ročníku (včetně), dáváme tituly postaru. - # - Jinak dáváme tituly po novu... - # - ... ale titul se nesmí odebrat, pokud se zmenšil. - def titul_do_26_rocniku(body): - """ Původní hranice bodů za tituly """ - if body < 10: - return Titul.nic - elif body < 20: - return Titul.bc - elif body < 50: - return Titul.mgr - elif body < 100: - return Titul.dr - elif body < 200: - return Titul.doc - elif body < 500: - return Titul.prof - else: - return Titul.akad - - from .odevzdavatko import Hodnoceni - 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) - ) - starsi_body = body_z_hodnoceni(hodnoceni_do_26_rocniku) - if body is not None: - # Ještě z toho vybereme ty správně staré body - novejsi_body = max(0, body - starsi_body) - starsi_body = min(starsi_body, body) - - # Titul pro 26. ročník - stary_titul = titul_do_26_rocniku(starsi_body) - # Titul podle aktuálních pravidel - novy_titul = Titul.z_bodu(logicke_body) - - if novejsi_body == 0: - # Žádné nové body -- titul podle starých pravidel - return str(stary_titul) - return str(max(novy_titul, stary_titul)) - - - def __str__(self): - return self.osoba.plne_jmeno() - - -@reversion.register(ignore_duplicates=True) -class Organizator(SeminarModelBase): - osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org_old4', - help_text='osobní údaje organizátora', null=False, blank=False, - on_delete=models.PROTECT) - - vytvoreno = models.DateTimeField( - 'Vytvořeno', - default=timezone.now, - blank=True, - editable=False - ) - - # Ne, date to nebude. SQLite: invalid literal for int() with base 10: b'17 23:00:00' - organizuje_od = models.DateTimeField('Organizuje od', blank=True, null=True) - - organizuje_do = models.DateTimeField('Organizuje do', blank=True, null=True) - - studuje = models.CharField('Studium aj.', max_length = 256, - null = True, blank = True, - help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', " - "'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo " - "'Přednáší na MFF'") - - strucny_popis_organizatora = models.TextField('Stručný popis organizátora', - null = True, blank = True) - - skola = models.CharField('Škola, kterou studuje', max_length = 256, null=True, blank=True, - help_text="Škola, např. MFF, VŠCHT, VUT, ... prostě aby se nemuselo psát do studuje" - "školu, ale jen obor, možnost zobrazit zvlášť") - - def clean(self): - if self.organizuje_od and self.organizuje_do and (self.organizuje_od > self.organizuje_do): - raise ValidationError("Organizátor nemůže skončit s organizováním dříve než začal!") - super().clean() - - def __str__(self): - if self.osoba.prezdivka: - return "{} '{}' {}".format(self.osoba.jmeno, - self.osoba.prezdivka, - self.osoba.prijmeni) - else: - return "{} {}".format(self.osoba.jmeno, self.osoba.prijmeni) - - class Meta: - verbose_name = 'Organizátor' - verbose_name_plural = 'Organizátoři' - # Řadí aktivní orgy na začátek, pod tím v pořadí od nejstarších neaktivní orgy. - # TODO: Chtěl bych spíš mít nejstarší orgy dole. - # TODO: Zohledňovat přezdívky? - # TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu - ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] - managed = False From 9c1c393395be0491e3ccd52a692566056d5bec59 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 19 Mar 2024 23:11:15 +0100 Subject: [PATCH 30/59] delete notes --- split-apps-meta/delete.notes | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 split-apps-meta/delete.notes diff --git a/split-apps-meta/delete.notes b/split-apps-meta/delete.notes new file mode 100644 index 00000000..64c15c0a --- /dev/null +++ b/split-apps-meta/delete.notes @@ -0,0 +1,8 @@ +Prostě to smazat. +makemigrations + Kromě triviální smazání modelů se smažou i jejich vazby, to je snad OK. + (Hypotéza: kvůli konzistenčním kontrolám v DB?) +migrate +a doufat :-P + +(Pozor: pokud něco (JSON serializace, data/… atp.) má starý identifikátor modelu, tak se to teď rozbije.) From b17b97e4e4e5299b55a597e487b1133b79b6d602 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:09:12 +0100 Subject: [PATCH 31/59] OrgSkolyAutocompleteTestCase: jde vypnout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Když máme jiný model, tak se nepotkají typy dumpů. Cherry-pickable. --- api/tests/test_skola_autocomplete.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/tests/test_skola_autocomplete.py b/api/tests/test_skola_autocomplete.py index 9fc4aee6..36df97e8 100644 --- a/api/tests/test_skola_autocomplete.py +++ b/api/tests/test_skola_autocomplete.py @@ -1,9 +1,10 @@ -from django.test import TestCase +from django.test import TestCase, tag from django.urls import reverse import seminar.models as m import seminar.views as v from seminar.utils import sync_skoly +@tag('stejny-model-na-produkci') class OrgSkolyAutocompleteTestCase(TestCase): @classmethod def setUpClass(cls): From 54db53805a87e3d117df184f66f51fc6c7780be4 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:16:59 +0100 Subject: [PATCH 32/59] Nezapomenout na vazby --- split-apps-meta/delete.notes | 1 + 1 file changed, 1 insertion(+) diff --git a/split-apps-meta/delete.notes b/split-apps-meta/delete.notes index 64c15c0a..dad0e6d4 100644 --- a/split-apps-meta/delete.notes +++ b/split-apps-meta/delete.notes @@ -2,6 +2,7 @@ Prostě to smazat. makemigrations Kromě triviální smazání modelů se smažou i jejich vazby, to je snad OK. (Hypotéza: kvůli konzistenčním kontrolám v DB?) +Doplnit vazby na relinky a vznik nového modelu migrate a doufat :-P From 1a3dd5d6b233aa646e3797002655fe2407e939ed Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:17:53 +0100 Subject: [PATCH 33/59] =?UTF-8?q?Jak=20za=C5=99=C3=ADdit,=20=C5=BEe=20mode?= =?UTF-8?q?l=20bude=20managed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/manage.notes | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 split-apps-meta/manage.notes diff --git a/split-apps-meta/manage.notes b/split-apps-meta/manage.notes new file mode 100644 index 00000000..3cf5a8d2 --- /dev/null +++ b/split-apps-meta/manage.notes @@ -0,0 +1,3 @@ +1. smazat `managed = False` +2. makemigrations +3. migrate From b4b41b949966c1cf8ed194de8c90fb06e6c5c278 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:18:12 +0100 Subject: [PATCH 34/59] =?UTF-8?q?P=C5=99id=C3=A1n=C3=AD=20z=C3=A1vislost?= =?UTF-8?q?=C3=AD=20do=20delete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0120_remove_osoba_user_remove_prijemce_osoba_and_more.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py index 6e4f4612..1bbfcff0 100644 --- a/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py +++ b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py @@ -7,6 +7,10 @@ class Migration(migrations.Migration): dependencies = [ ('seminar', '0119_alter_konfera_ucastnici_and_more'), + ('personalni', '0003_initial'), + ('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'), + ('prednasky', '0014_alter_prednaska_org'), + ('sifrovacka', '0005_alter_odpoveducastnika_resitel'), ] operations = [ From a17914f49ce6b09995369f933192dd0c6f3ab8ca Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:18:25 +0100 Subject: [PATCH 35/59] Personalni: managed = True + makemigrations --- ...or_options_alter_osoba_options_and_more.py | 33 +++++++++++++++++++ personalni/models.py | 5 --- 2 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py diff --git a/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py b/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py new file mode 100644 index 00000000..8abbf0a0 --- /dev/null +++ b/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.11 on 2024-03-26 21:11 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0003_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='organizator', + options={'ordering': ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'], 'verbose_name': 'Organizátor', 'verbose_name_plural': 'Organizátoři'}, + ), + migrations.AlterModelOptions( + name='osoba', + options={'ordering': ['prijmeni', 'jmeno'], 'verbose_name': 'Osoba', 'verbose_name_plural': 'Osoby'}, + ), + migrations.AlterModelOptions( + name='prijemce', + options={'verbose_name': 'příjemce', 'verbose_name_plural': 'příjemce'}, + ), + migrations.AlterModelOptions( + name='resitel', + options={'ordering': ['osoba'], 'verbose_name': 'Řešitel', 'verbose_name_plural': 'Řešitelé'}, + ), + migrations.AlterModelOptions( + name='skola', + options={'ordering': ['mesto', 'nazev'], 'verbose_name': 'Škola', 'verbose_name_plural': 'Školy'}, + ), + ] diff --git a/personalni/models.py b/personalni/models.py index cff2899e..7ede2d08 100644 --- a/personalni/models.py +++ b/personalni/models.py @@ -25,7 +25,6 @@ class Osoba(SeminarModelBase): verbose_name = 'Osoba' verbose_name_plural = 'Osoby' ordering = ['prijmeni','jmeno'] - managed = False id = models.AutoField(primary_key = True) @@ -129,7 +128,6 @@ class Skola(SeminarModelBase): verbose_name = 'Škola' verbose_name_plural = 'Školy' ordering = ['mesto', 'nazev'] - managed = False # Interní ID id = models.AutoField(primary_key = True) @@ -182,7 +180,6 @@ class Prijemce(SeminarModelBase): db_table = 'seminar_prijemce' verbose_name = 'příjemce' verbose_name_plural = 'příjemce' - managed = False # Interní ID @@ -212,7 +209,6 @@ class Resitel(SeminarModelBase): verbose_name = 'Řešitel' verbose_name_plural = 'Řešitelé' ordering = ['osoba'] - managed = False # Interní ID id = models.AutoField(primary_key = True) @@ -409,7 +405,6 @@ class Organizator(SeminarModelBase): # TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu db_table = 'seminar_organizator' ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] - managed = False osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org', help_text='osobní údaje organizátora', null=False, blank=False, From 49f9b052852a84a107e5fdb402ac77310dd24b87 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:19:02 +0100 Subject: [PATCH 36/59] =?UTF-8?q?nezapomenout=20vazby=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/manage.notes | 1 + 1 file changed, 1 insertion(+) diff --git a/split-apps-meta/manage.notes b/split-apps-meta/manage.notes index 3cf5a8d2..c6d4b189 100644 --- a/split-apps-meta/manage.notes +++ b/split-apps-meta/manage.notes @@ -1,3 +1,4 @@ 1. smazat `managed = False` 2. makemigrations + Vazba na delete! 3. migrate From d21ac37187001b65aeb0bb74adb1540af6c985ad Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:19:38 +0100 Subject: [PATCH 37/59] vazba --- ...004_alter_organizator_options_alter_osoba_options_and_more.py | 1 + 1 file changed, 1 insertion(+) diff --git a/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py b/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py index 8abbf0a0..6065e58f 100644 --- a/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py +++ b/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py @@ -7,6 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('personalni', '0003_initial'), + ('seminar', '0120_remove_osoba_user_remove_prijemce_osoba_and_more'), ] operations = [ From 9b12681e4526b96ea2ca3853f26d1c1ef3b5947d Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:23:40 +0100 Subject: [PATCH 38/59] =?UTF-8?q?pomigra=C4=8Dn=C3=AD=20safeguardy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/post | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 split-apps-meta/post diff --git a/split-apps-meta/post b/split-apps-meta/post new file mode 100644 index 00000000..0fa01c0d --- /dev/null +++ b/split-apps-meta/post @@ -0,0 +1,2 @@ +dummy migrace v novém modelu +dummy migrace v semináři a ostatních, závisející na té nové migraci. From e0d45ddf5d7ce558e6bcef59ba5996d3baf00ab1 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:26:33 +0100 Subject: [PATCH 39/59] =?UTF-8?q?Pomigra=C4=8Dn=C3=AD=20migrace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lol wording --- .../migrations/0023_personalni_post_migrate.py | 14 ++++++++++++++ .../migrations/0005_personalni_post_migrate.py | 13 +++++++++++++ .../migrations/0015_personalni_post_migrate.py | 14 ++++++++++++++ seminar/migrations/0121_personalni_post_migrate.py | 14 ++++++++++++++ .../migrations/0006_personalni_post_migrate.py | 14 ++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 korektury/migrations/0023_personalni_post_migrate.py create mode 100644 personalni/migrations/0005_personalni_post_migrate.py create mode 100644 prednasky/migrations/0015_personalni_post_migrate.py create mode 100644 seminar/migrations/0121_personalni_post_migrate.py create mode 100644 sifrovacka/migrations/0006_personalni_post_migrate.py diff --git a/korektury/migrations/0023_personalni_post_migrate.py b/korektury/migrations/0023_personalni_post_migrate.py new file mode 100644 index 00000000..a92ec89d --- /dev/null +++ b/korektury/migrations/0023_personalni_post_migrate.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-03-26 21:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'), + ('peronalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] diff --git a/personalni/migrations/0005_personalni_post_migrate.py b/personalni/migrations/0005_personalni_post_migrate.py new file mode 100644 index 00000000..72d1571a --- /dev/null +++ b/personalni/migrations/0005_personalni_post_migrate.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.11 on 2024-03-26 21:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0004_alter_organizator_options_alter_osoba_options_and_more'), + ] + + operations = [ + ] diff --git a/prednasky/migrations/0015_personalni_post_migrate.py b/prednasky/migrations/0015_personalni_post_migrate.py new file mode 100644 index 00000000..7bb596d6 --- /dev/null +++ b/prednasky/migrations/0015_personalni_post_migrate.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-03-26 21:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('prednasky', '0014_alter_prednaska_org'), + ('peronalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] diff --git a/seminar/migrations/0121_personalni_post_migrate.py b/seminar/migrations/0121_personalni_post_migrate.py new file mode 100644 index 00000000..f84328a5 --- /dev/null +++ b/seminar/migrations/0121_personalni_post_migrate.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-03-26 21:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0120_remove_osoba_user_remove_prijemce_osoba_and_more'), + ('peronalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] diff --git a/sifrovacka/migrations/0006_personalni_post_migrate.py b/sifrovacka/migrations/0006_personalni_post_migrate.py new file mode 100644 index 00000000..25775ae4 --- /dev/null +++ b/sifrovacka/migrations/0006_personalni_post_migrate.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-03-26 21:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('sifrovacka', '0005_alter_odpoveducastnika_resitel'), + ('peronalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] From 51f730fe71d9017a45d123ecf6352e7c77c644df Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 26 Mar 2024 22:27:48 +0100 Subject: [PATCH 40/59] =?UTF-8?q?typo=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- korektury/migrations/0023_personalni_post_migrate.py | 2 +- prednasky/migrations/0015_personalni_post_migrate.py | 2 +- seminar/migrations/0121_personalni_post_migrate.py | 2 +- sifrovacka/migrations/0006_personalni_post_migrate.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/korektury/migrations/0023_personalni_post_migrate.py b/korektury/migrations/0023_personalni_post_migrate.py index a92ec89d..048ece7a 100644 --- a/korektury/migrations/0023_personalni_post_migrate.py +++ b/korektury/migrations/0023_personalni_post_migrate.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'), - ('peronalni', '0005_personalni_post_migrate'), + ('personalni', '0005_personalni_post_migrate'), ] operations = [ diff --git a/prednasky/migrations/0015_personalni_post_migrate.py b/prednasky/migrations/0015_personalni_post_migrate.py index 7bb596d6..04553e8f 100644 --- a/prednasky/migrations/0015_personalni_post_migrate.py +++ b/prednasky/migrations/0015_personalni_post_migrate.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('prednasky', '0014_alter_prednaska_org'), - ('peronalni', '0005_personalni_post_migrate'), + ('personalni', '0005_personalni_post_migrate'), ] operations = [ diff --git a/seminar/migrations/0121_personalni_post_migrate.py b/seminar/migrations/0121_personalni_post_migrate.py index f84328a5..51840894 100644 --- a/seminar/migrations/0121_personalni_post_migrate.py +++ b/seminar/migrations/0121_personalni_post_migrate.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('seminar', '0120_remove_osoba_user_remove_prijemce_osoba_and_more'), - ('peronalni', '0005_personalni_post_migrate'), + ('personalni', '0005_personalni_post_migrate'), ] operations = [ diff --git a/sifrovacka/migrations/0006_personalni_post_migrate.py b/sifrovacka/migrations/0006_personalni_post_migrate.py index 25775ae4..cf2c8ad5 100644 --- a/sifrovacka/migrations/0006_personalni_post_migrate.py +++ b/sifrovacka/migrations/0006_personalni_post_migrate.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ ('sifrovacka', '0005_alter_odpoveducastnika_resitel'), - ('peronalni', '0005_personalni_post_migrate'), + ('personalni', '0005_personalni_post_migrate'), ] operations = [ From 026efe2467646fc8aa95eba5c7f67da103ee310a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sun, 14 Apr 2024 15:09:03 +0200 Subject: [PATCH 41/59] =?UTF-8?q?N=C3=A1pov=C4=9Bdy=20v=20=C5=A1ifrova?= =?UTF-8?q?=C4=8Dce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sifrovacka/admin.py | 4 +- sifrovacka/forms.py | 14 +++- .../0004_napoveda_napovezenoucastnikovi.py | 65 +++++++++++++++++++ sifrovacka/models.py | 17 +++++ sifrovacka/templates/sifrovacka/napoveda.html | 48 ++++++++++++++ .../templates/sifrovacka/napovedy_list.html | 23 +++++++ .../templates/sifrovacka/sifrovacka.html | 2 + sifrovacka/urls.py | 12 +++- sifrovacka/views.py | 27 +++++++- 9 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py create mode 100644 sifrovacka/templates/sifrovacka/napoveda.html create mode 100644 sifrovacka/templates/sifrovacka/napovedy_list.html diff --git a/sifrovacka/admin.py b/sifrovacka/admin.py index 71d191d4..5099c241 100644 --- a/sifrovacka/admin.py +++ b/sifrovacka/admin.py @@ -1,8 +1,10 @@ from django.contrib import admin -from .models import OdpovedUcastnika, SpravnaOdpoved +from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda # Register your models here. admin.site.register(OdpovedUcastnika) admin.site.register(SpravnaOdpoved) +admin.site.register(Napoveda) +admin.site.register(NapovezenoUcastnikovi) diff --git a/sifrovacka/forms.py b/sifrovacka/forms.py index e3eba7c7..8a1e16d1 100644 --- a/sifrovacka/forms.py +++ b/sifrovacka/forms.py @@ -1,6 +1,6 @@ from django.core.exceptions import ValidationError from django.forms import ModelForm, Textarea -from .models import OdpovedUcastnika, SpravnaOdpoved +from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda class SifrovackaForm(ModelForm): @@ -16,3 +16,15 @@ class SifrovackaForm(ModelForm): if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0: raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.") return sifra + + +class NapovedaForm(ModelForm): + class Meta: + model = NapovezenoUcastnikovi + fields = ["sifra",] + + def clean_sifra(self): + sifra = self.cleaned_data.get('sifra') + if Napoveda.objects.filter(sifra=sifra).count() == 0: + raise ValidationError("K tomuto číslu šifry nemáme nápovědu. Zkonstolujte si ho prosím.") + return sifra diff --git a/sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py b/sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py new file mode 100644 index 00000000..cba7ae8f --- /dev/null +++ b/sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py @@ -0,0 +1,65 @@ +# Generated by Django 4.2.8 on 2024-04-14 12:57 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + dependencies = [ + ( + "seminar", + "0114_related_name_se_zmenilo_a_django_chce_migraci_tak_dostane_migraci", + ), + ("sifrovacka", "0003_odpoveducastnika_uspech"), + ] + + operations = [ + migrations.CreateModel( + name="Napoveda", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("text", models.TextField()), + ("sifra", models.IntegerField()), + ], + ), + migrations.CreateModel( + name="NapovezenoUcastnikovi", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("sifra", models.IntegerField(verbose_name="Číslo šifry")), + ( + "timestamp", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="Timestamp" + ), + ), + ( + "resitel", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="seminar.resitel", + ), + ), + ], + options={ + "ordering": ["-timestamp"], + }, + ), + ] diff --git a/sifrovacka/models.py b/sifrovacka/models.py index 6517c2e0..beabd0a7 100644 --- a/sifrovacka/models.py +++ b/sifrovacka/models.py @@ -25,3 +25,20 @@ class SpravnaOdpoved(models.Model): def __str__(self): return f"{self.sifra}: {self.odpoved}" + + +class NapovezenoUcastnikovi(models.Model): + class Meta: + ordering = ["-timestamp"] + + resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE) + sifra = models.IntegerField("Číslo šifry", blank=False, null=False,) + timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now) + + +class Napoveda(models.Model): + text = models.TextField(blank=False, null=False,) + sifra = models.IntegerField(blank=False, null=False,) + + def __str__(self): + return f"{self.sifra}: {self.text}" diff --git a/sifrovacka/templates/sifrovacka/napoveda.html b/sifrovacka/templates/sifrovacka/napoveda.html new file mode 100644 index 00000000..88944216 --- /dev/null +++ b/sifrovacka/templates/sifrovacka/napoveda.html @@ -0,0 +1,48 @@ +{% extends "base.html" %} + +{% block content %} + +
+ +

{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}

+ +
+ +

Získat nápovědu k šifře:

+ +
+ + {{form.non_field_errors}} + {% for field in form %} + + + + + + + + + {% if field.errors %} + + + + {% endif %} + {% endfor %} +
+ + + + {{ field }} + {{ field.help_text|safe }} +
{{ field.errors }}
+ + {% csrf_token %} + + +
+ + Nechceme nápovědu, známe řešení! + +{% endblock content %} diff --git a/sifrovacka/templates/sifrovacka/napovedy_list.html b/sifrovacka/templates/sifrovacka/napovedy_list.html new file mode 100644 index 00000000..dc729947 --- /dev/null +++ b/sifrovacka/templates/sifrovacka/napovedy_list.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% block content %} + +

{% block nadpis1a %}Šifrovačka vzaté nápovědy{% endblock nadpis1a %}

+ + + + + + + + + {% for u in object_list %} + + + + + + {% endfor %} +
TimestampŘešitelŠifra
{{ u.timestamp }}{{ u.resitel }}{{ u.sifra }}
+ +{% endblock content %} diff --git a/sifrovacka/templates/sifrovacka/sifrovacka.html b/sifrovacka/templates/sifrovacka/sifrovacka.html index 4e0cc15a..74943406 100644 --- a/sifrovacka/templates/sifrovacka/sifrovacka.html +++ b/sifrovacka/templates/sifrovacka/sifrovacka.html @@ -43,4 +43,6 @@ + Získat nápovědu + {% endblock content %} diff --git a/sifrovacka/urls.py b/sifrovacka/urls.py index a7af5e54..916d73ec 100644 --- a/sifrovacka/urls.py +++ b/sifrovacka/urls.py @@ -1,7 +1,7 @@ from django.urls import path from seminar.utils import org_required, resitel_or_org_required -from .views import SifrovackaView, SifrovackaListView +from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView urlpatterns = [ path( @@ -14,4 +14,14 @@ urlpatterns = [ org_required(SifrovackaListView.as_view()), name='sifrovacka_odpovedi' ), + path( + 'napoveda/', + resitel_or_org_required(NapovedaView.as_view()), + name='sifrovacka_napoveda' + ), + path( + 'napovedy/', + org_required(NapovedaListView.as_view()), + name='sifrovacka_napovedy' + ), ] diff --git a/sifrovacka/views.py b/sifrovacka/views.py index 9c4af3ed..5537344b 100644 --- a/sifrovacka/views.py +++ b/sifrovacka/views.py @@ -2,8 +2,8 @@ from django.urls import reverse from django.views.generic import FormView, ListView from seminar.views import formularOKView -from .forms import SifrovackaForm -from .models import OdpovedUcastnika, SpravnaOdpoved +from .forms import SifrovackaForm, NapovedaForm +from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi from seminar.models.personalni import Resitel @@ -24,10 +24,31 @@ class SifrovackaView(FormView): instance.uspech = True instance.save() - + return formularOKView(self.request, f'

{sifra.skryty_text}

Odevzdat další.




') class SifrovackaListView(ListView): template_name = 'sifrovacka/odpovedi_list.html' model = OdpovedUcastnika + + +class NapovedaView(FormView): + template_name = 'sifrovacka/napoveda.html' + form_class = NapovedaForm + + def form_valid(self, form): + instance = form.save(commit=False) + resitel = Resitel.objects.get(osoba__user=self.request.user) + instance.resitel = resitel + + if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra=instance.sifra).first() is None: + instance.save() + + napoveda = Napoveda.objects.filter(sifra=instance.sifra).first() + return formularOKView(self.request, f'

Nápověda k šifře číslo {instance.sifra} je:

{napoveda.text}

Odevzdat řešení.




') + + +class NapovedaListView(ListView): + template_name = 'sifrovacka/napovedy_list.html' + model = NapovezenoUcastnikovi From 9a93f954906d1eeaccc2a447d0c6c73a1f7a2445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Sun, 21 Apr 2024 21:06:56 +0200 Subject: [PATCH 42/59] =?UTF-8?q?fix:=20N=C3=A1pov=C4=9Bdy=20v=20=C5=A1ifr?= =?UTF-8?q?ova=C4=8Dce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sifrovacka/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sifrovacka/forms.py b/sifrovacka/forms.py index 8a1e16d1..3ae75cc1 100644 --- a/sifrovacka/forms.py +++ b/sifrovacka/forms.py @@ -26,5 +26,5 @@ class NapovedaForm(ModelForm): def clean_sifra(self): sifra = self.cleaned_data.get('sifra') if Napoveda.objects.filter(sifra=sifra).count() == 0: - raise ValidationError("K tomuto číslu šifry nemáme nápovědu. Zkonstolujte si ho prosím.") + raise ValidationError("K tomuto číslu šifry nemáme nápovědu. Zkontrolujte si ho prosím.") return sifra From d09a08f53fc5c9c028ac4295f0908fe7e4a9441e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Mon, 22 Apr 2024 23:27:29 +0200 Subject: [PATCH 43/59] =?UTF-8?q?fix:=20P=C5=99eskakov=C3=A1n=C3=AD=20v=20?= =?UTF-8?q?=C5=A1ifrova=C4=8Dce=20(je=20tam=20faaaaakt=20hodn=C4=9B=20sn?= =?UTF-8?q?=C4=9Bhu)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sifrovacka/templates/sifrovacka/napoveda.html | 4 +- .../templates/sifrovacka/preskoceni.html | 54 +++++++++++++++++++ .../templates/sifrovacka/sifrovacka.html | 4 +- sifrovacka/urls.py | 7 ++- sifrovacka/views.py | 16 ++++++ 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 sifrovacka/templates/sifrovacka/preskoceni.html diff --git a/sifrovacka/templates/sifrovacka/napoveda.html b/sifrovacka/templates/sifrovacka/napoveda.html index 88944216..cce48ed8 100644 --- a/sifrovacka/templates/sifrovacka/napoveda.html +++ b/sifrovacka/templates/sifrovacka/napoveda.html @@ -43,6 +43,8 @@ - Nechceme nápovědu, známe řešení! +

Nechceme nápovědu, známe řešení!

+ +

Přeskoč šifru

{% endblock content %} diff --git a/sifrovacka/templates/sifrovacka/preskoceni.html b/sifrovacka/templates/sifrovacka/preskoceni.html new file mode 100644 index 00000000..64e777ea --- /dev/null +++ b/sifrovacka/templates/sifrovacka/preskoceni.html @@ -0,0 +1,54 @@ +{% extends "base.html" %} + +{% block content %} + +
+ +

{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}

+ +
+ +

Přeskočit šifru:

+ +
+ + {{form.non_field_errors}} + {% for field in form %} + {% if field.id_for_label != "id_odpoved" %} + + + + + + + + + {% if field.errors %} + + + + {% endif %} + {% else %} + {{ field.as_hidden }} + {% endif %} + {% endfor %} +
+ + + + {{ field }} + {{ field.help_text|safe }} +
{{ field.errors }}
+ + {% csrf_token %} + + +
+ +

Nechceme přeskočit, známe řešení!

+ +

Nechceme přeskakovat, ale nápověda by se šikla.

+ +{% endblock content %} diff --git a/sifrovacka/templates/sifrovacka/sifrovacka.html b/sifrovacka/templates/sifrovacka/sifrovacka.html index 74943406..1ce95454 100644 --- a/sifrovacka/templates/sifrovacka/sifrovacka.html +++ b/sifrovacka/templates/sifrovacka/sifrovacka.html @@ -43,6 +43,8 @@ - Získat nápovědu +

Získat nápovědu

+ +

Přeskoč šifru

{% endblock content %} diff --git a/sifrovacka/urls.py b/sifrovacka/urls.py index 916d73ec..85f9c4cc 100644 --- a/sifrovacka/urls.py +++ b/sifrovacka/urls.py @@ -1,7 +1,7 @@ from django.urls import path from seminar.utils import org_required, resitel_or_org_required -from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView +from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView, PreskoceniView urlpatterns = [ path( @@ -24,4 +24,9 @@ urlpatterns = [ org_required(NapovedaListView.as_view()), name='sifrovacka_napovedy' ), + path( + 'preskoceni/', + resitel_or_org_required(PreskoceniView.as_view()), + name='sifrovacka_preskoceni' + ), ] diff --git a/sifrovacka/views.py b/sifrovacka/views.py index 5537344b..59f3deec 100644 --- a/sifrovacka/views.py +++ b/sifrovacka/views.py @@ -52,3 +52,19 @@ class NapovedaView(FormView): class NapovedaListView(ListView): template_name = 'sifrovacka/napovedy_list.html' model = NapovezenoUcastnikovi + + +class PreskoceniView(FormView): + template_name = 'sifrovacka/preskoceni.html' + form_class = SifrovackaForm + initial = {"odpoved": "=======PŘESKOČENO======="} + + def form_valid(self, form): + instance = form.save(commit=False) + instance.odpoved = "=======PŘESKOČENO=======" + resitel = Resitel.objects.get(osoba__user=self.request.user) + instance.resitel = resitel + instance.save() + sifra = SpravnaOdpoved.objects.filter(sifra=instance.sifra).first() # FIXME co když je více "správných" odpovědí? + + return formularOKView(self.request, f'

{sifra.skryty_text}

Zpět na odevzdávátko.




') From 4eb6746c75f73fbe90cfc901e321d43e0f0ba674 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 30 Apr 2024 21:05:10 +0200 Subject: [PATCH 44/59] =?UTF-8?q?Chyb=C4=9Bj=C3=ADc=C3=AD=20ForeignKeys/1-?= =?UTF-8?q?2-1Keys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- personalni/migrations/0003_initial.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/personalni/migrations/0003_initial.py b/personalni/migrations/0003_initial.py index e026182c..4103295e 100644 --- a/personalni/migrations/0003_initial.py +++ b/personalni/migrations/0003_initial.py @@ -5,6 +5,9 @@ import django.utils.timezone import django_countries.fields import imagekit.models.fields +from django.conf import settings +import django.db.models.deletion + def nastav_nove_contenttypes(apps, schema_editor): ContentType = apps.get_model('contenttypes', 'ContentType') for m in ('resitel', 'organizator', 'osoba', 'skola', 'prijemce'): @@ -38,6 +41,7 @@ class Migration(migrations.Migration): ('studuje', models.CharField(blank=True, help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', 'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo 'Přednáší na MFF'", max_length=256, null=True, verbose_name='Studium aj.')), ('strucny_popis_organizatora', models.TextField(blank=True, null=True, verbose_name='Stručný popis organizátora')), ('skola', models.CharField(blank=True, help_text='Škola, např. MFF, VŠCHT, VUT, ... prostě aby se nemuselo psát do studuješkolu, ale jen obor, možnost zobrazit zvlášť', max_length=256, null=True, verbose_name='Škola, kterou studuje')), + ('osoba', models.OneToOneField(help_text='osobní údaje organizátora', on_delete=django.db.models.deletion.PROTECT, related_name='org', to='personalni.osoba', verbose_name='osoba')), ], options={ 'verbose_name': 'Organizátor', @@ -68,6 +72,7 @@ class Migration(migrations.Migration): ('jak_se_dozvedeli', models.TextField(blank=True, verbose_name='Jak se dozvěděli')), ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k osobě (plain text)', verbose_name='neveřejná poznámka')), ('foto', imagekit.models.fields.ProcessedImageField(blank=True, help_text='Vlož fotografii osoby o libovolné velikosti', null=True, upload_to='image_osoby/velke/%Y/', verbose_name='Fotografie osoby')), + ('user', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL, verbose_name='uživatel')), ], options={ 'verbose_name': 'Osoba', @@ -83,6 +88,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(primary_key=True, serialize=False)), ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k příemci čísel (plain text)', verbose_name='neveřejná poznámka')), ('zasilat_cislo_emailem', models.BooleanField(default=False, help_text='True pokud chce příjemce dostávat číslo emailem', verbose_name='zasílat číslo emailem')), + ('osoba', models.OneToOneField(help_text='Které osobě či na jakou adresu se mají zasílat čísla', on_delete=django.db.models.deletion.CASCADE, to='personalni.osoba', verbose_name='komu')), ], options={ 'verbose_name': 'příjemce', @@ -101,6 +107,8 @@ class Migration(migrations.Migration): ('zasilat_cislo_emailem', models.BooleanField(default=False, help_text='True pokud chce řešitel dostávat číslo emailem', verbose_name='zasílat číslo emailem')), ('zasilat_cislo_papirove', models.BooleanField(default=True, help_text='True pokud chce řešitel dostávat číslo papírově', verbose_name='zasílat číslo papírově')), ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k řešiteli (plain text)', verbose_name='neveřejná poznámka')), + ('osoba', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='personalni.osoba', verbose_name='osoba')), + ('skola', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.skola', verbose_name='škola')), ], options={ 'verbose_name': 'Řešitel', @@ -125,6 +133,7 @@ class Migration(migrations.Migration): ('je_zs', models.BooleanField(default=True, verbose_name='základní stupeň')), ('je_ss', models.BooleanField(default=True, verbose_name='střední stupeň')), ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka ke škole (plain text)', verbose_name='neveřejná poznámka')), + ('kontaktni_osoba', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.osoba', verbose_name='Kontaktní osoba')), ], options={ 'verbose_name': 'Škola', From 8ab25545a493258cf0c198353b2c07306bd681d1 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 30 Apr 2024 21:07:11 +0200 Subject: [PATCH 45/59] =?UTF-8?q?Pozn=C3=A1mky=20k=20FK/1to1F=20v=20creaet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- split-apps-meta/create.notes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/split-apps-meta/create.notes b/split-apps-meta/create.notes index 43872d68..8d3174e3 100644 --- a/split-apps-meta/create.notes +++ b/split-apps-meta/create.notes @@ -1,5 +1,6 @@ Prostě zkopírovat vedle, s původními (=správnými) related names. makemigrations -! Doplnit hack kolem content-types +! Doplnit hack kolem content-types (jako první operace při migraci) +! Doplnit ForeignKeys (TODO: jak? Já jsem je ukradl až zpětně…) doplnit závislost na unmanage migrate From 03589e484c3b84b0b289f80fbba38c187697ee26 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 30 Apr 2024 21:34:54 +0200 Subject: [PATCH 46/59] =?UTF-8?q?Fix=20import=C5=AF=20v=20personalni.model?= =?UTF-8?q?s.Resitel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lokální, přehlédl jsem je… --- personalni/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/personalni/models.py b/personalni/models.py index 7ede2d08..b78ab4c1 100644 --- a/personalni/models.py +++ b/personalni/models.py @@ -281,7 +281,7 @@ class Resitel(SeminarModelBase): def vsechny_body(self): "Spočítá body odjakživa." vsechna_reseni = self.reseni_set.all() - from .odevzdavatko import Hodnoceni + from seminar.odevzdavatko import Hodnoceni vsechna_hodnoceni = Hodnoceni.objects.filter( reseni__in=vsechna_reseni) return sum(h.body for h in list(vsechna_hodnoceni) if h.body is not None) @@ -328,7 +328,7 @@ class Resitel(SeminarModelBase): # - body z 25. ročníku a dříve byly shledány dvakrát hodnotnějšími # - 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 + from seminar.odevzdavatko import Hodnoceni 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) @@ -366,7 +366,7 @@ class Resitel(SeminarModelBase): else: return Titul.akad - from .odevzdavatko import Hodnoceni + from seminar.odevzdavatko import Hodnoceni 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()) From 77d392f14f3e4722ae0b0473d3650ac13c9be1b4 Mon Sep 17 00:00:00 2001 From: Pavel 'LEdoian' Turinsky Date: Tue, 30 Apr 2024 21:36:59 +0200 Subject: [PATCH 47/59] =?UTF-8?q?fixup!=20Fix=20import=C5=AF=20v=20persona?= =?UTF-8?q?lni.models.Resitel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- personalni/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/personalni/models.py b/personalni/models.py index b78ab4c1..dfcc7372 100644 --- a/personalni/models.py +++ b/personalni/models.py @@ -281,7 +281,7 @@ class Resitel(SeminarModelBase): def vsechny_body(self): "Spočítá body odjakživa." vsechna_reseni = self.reseni_set.all() - from seminar.odevzdavatko import Hodnoceni + from seminar.models.odevzdavatko import Hodnoceni vsechna_hodnoceni = Hodnoceni.objects.filter( reseni__in=vsechna_reseni) return sum(h.body for h in list(vsechna_hodnoceni) if h.body is not None) @@ -328,7 +328,7 @@ class Resitel(SeminarModelBase): # - body z 25. ročníku a dříve byly shledány dvakrát hodnotnějšími # - 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 seminar.odevzdavatko import Hodnoceni + from seminar.models.odevzdavatko import Hodnoceni 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) @@ -366,7 +366,7 @@ class Resitel(SeminarModelBase): else: return Titul.akad - from seminar.odevzdavatko import Hodnoceni + from seminar.models.odevzdavatko import Hodnoceni 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()) From 6ab00392cca19542f4f332bb7a70553ad887b276 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 30 Apr 2024 22:20:36 +0200 Subject: [PATCH 48/59] =?UTF-8?q?Pou=C5=BE=C3=ADt=20p=C5=99=C3=ADmo=20nov?= =?UTF-8?q?=C3=BD=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … když už můžeme --- sifrovacka/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sifrovacka/views.py b/sifrovacka/views.py index 0428e043..2ad352da 100644 --- a/sifrovacka/views.py +++ b/sifrovacka/views.py @@ -4,7 +4,7 @@ from django.views.generic import FormView, ListView from seminar.views import formularOKView from .forms import SifrovackaForm, NapovedaForm from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi -from seminar.models import Resitel +from personalni.models import Resitel # Create your views here. From 676b94ca1bf354bcbfb75a17f8bb2c7ea204641a Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 30 Apr 2024 22:27:06 +0200 Subject: [PATCH 49/59] =?UTF-8?q?Oprava=20po=C5=99ad=C3=AD=20migrac=C3=AD?= =?UTF-8?q?=20v=20=C5=A0ifrova=C4=8Dce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sifrovacka/migrations/0004_auto_20240312_2124.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sifrovacka/migrations/0004_auto_20240312_2124.py b/sifrovacka/migrations/0004_auto_20240312_2124.py index 8f58cf58..252268a6 100644 --- a/sifrovacka/migrations/0004_auto_20240312_2124.py +++ b/sifrovacka/migrations/0004_auto_20240312_2124.py @@ -6,7 +6,7 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('sifrovacka', '0003_odpoveducastnika_uspech'), + ('sifrovacka', '0004_napoveda_napovezenoucastnikovi'), ] operations = [ From 99c00954651d1dc5f49150e77d6cf6a0ce5f8d6b Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 30 Apr 2024 23:00:28 +0200 Subject: [PATCH 50/59] =?UTF-8?q?Fix=20migrac=C3=AD:=20p=C5=99ibyl=20FK=20?= =?UTF-8?q?na=20masteru=20b=C4=9Bhem=20p=C5=99ekop=C3=A1v=C3=A1n=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py index 34b50d4b..d21d65d6 100644 --- a/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py +++ b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py @@ -17,4 +17,9 @@ class Migration(migrations.Migration): name='resitel', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel'), ), + migrations.AlterField( + model_name='napovezenoucastnikovi', + name='resitel', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel'), + ), ] From cdc147259589d445fc881a78febec15e95912088 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 1 May 2024 00:46:31 +0200 Subject: [PATCH 51/59] =?UTF-8?q?Pre,=20unmanage,=20create.=20Snad=20ve=20?= =?UTF-8?q?fin=C3=A1ln=C3=AD=20podob=C4=9B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0011_pre_split_soustredeni.py | 13 ++ .../migrations/0006_pre_split_soustredeni.py | 13 ++ .../migrations/0016_pre_split_soustredeni.py | 13 ++ .../migrations/0122_pre_split_soustredeni.py | 16 ++ .../migrations/0123_soustredeni_unmanage.py | 33 +++ seminar/models/soustredeni.py | 25 +- .../migrations/0001_split_from_seminar.py | 119 ++++++++++ soustredeni/models.py | 221 ++++++++++++++++++ split-apps-meta/create.notes | 3 +- split-apps-meta/unmanage.notes | 3 + 10 files changed, 453 insertions(+), 6 deletions(-) create mode 100644 galerie/migrations/0011_pre_split_soustredeni.py create mode 100644 personalni/migrations/0006_pre_split_soustredeni.py create mode 100644 prednasky/migrations/0016_pre_split_soustredeni.py create mode 100644 seminar/migrations/0122_pre_split_soustredeni.py create mode 100644 seminar/migrations/0123_soustredeni_unmanage.py create mode 100644 soustredeni/migrations/0001_split_from_seminar.py create mode 100644 soustredeni/models.py diff --git a/galerie/migrations/0011_pre_split_soustredeni.py b/galerie/migrations/0011_pre_split_soustredeni.py new file mode 100644 index 00000000..a038ca44 --- /dev/null +++ b/galerie/migrations/0011_pre_split_soustredeni.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.11 on 2024-04-30 21:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0010_auto_20200819_0947'), + ] + + operations = [ + ] diff --git a/personalni/migrations/0006_pre_split_soustredeni.py b/personalni/migrations/0006_pre_split_soustredeni.py new file mode 100644 index 00000000..ce2b4de1 --- /dev/null +++ b/personalni/migrations/0006_pre_split_soustredeni.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.11 on 2024-04-30 21:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] diff --git a/prednasky/migrations/0016_pre_split_soustredeni.py b/prednasky/migrations/0016_pre_split_soustredeni.py new file mode 100644 index 00000000..77ade0d0 --- /dev/null +++ b/prednasky/migrations/0016_pre_split_soustredeni.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.11 on 2024-04-30 21:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('prednasky', '0015_personalni_post_migrate'), + ] + + operations = [ + ] diff --git a/seminar/migrations/0122_pre_split_soustredeni.py b/seminar/migrations/0122_pre_split_soustredeni.py new file mode 100644 index 00000000..58e9d479 --- /dev/null +++ b/seminar/migrations/0122_pre_split_soustredeni.py @@ -0,0 +1,16 @@ +# Generated by Django 4.2.11 on 2024-04-30 21:54 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0121_personalni_post_migrate'), + ('personalni', '0006_pre_split_soustredeni'), + ('galerie', '0011_pre_split_soustredeni'), + ('prednasky', '0016_pre_split_soustredeni'), + ] + + operations = [ + ] diff --git a/seminar/migrations/0123_soustredeni_unmanage.py b/seminar/migrations/0123_soustredeni_unmanage.py new file mode 100644 index 00000000..a7b87ff3 --- /dev/null +++ b/seminar/migrations/0123_soustredeni_unmanage.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.11 on 2024-04-30 22:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0122_pre_split_soustredeni'), + ] + + operations = [ + migrations.AlterModelOptions( + name='konfera', + options={'managed': False, 'verbose_name': 'Konfera', 'verbose_name_plural': 'Konfery'}, + ), + migrations.AlterModelOptions( + name='konfery_ucastnici', + options={'managed': False, 'ordering': ['konfera', 'resitel'], 'verbose_name': 'Účast na konfeře', 'verbose_name_plural': 'Účasti na konfeře'}, + ), + migrations.AlterModelOptions( + name='soustredeni', + options={'managed': False, 'ordering': ['-rocnik__rocnik', '-datum_zacatku'], 'verbose_name': 'Soustředění', 'verbose_name_plural': 'Soustředění'}, + ), + migrations.AlterModelOptions( + name='soustredeni_organizatori', + options={'managed': False, 'ordering': ['soustredeni', 'organizator'], 'verbose_name': 'Účast organizátorů na soustředění', 'verbose_name_plural': 'Účasti organizátorů na soustředění'}, + ), + migrations.AlterModelOptions( + name='soustredeni_ucastnici', + options={'managed': False, 'ordering': ['soustredeni', 'resitel'], 'verbose_name': 'Účast na soustředění', 'verbose_name_plural': 'Účasti na soustředění'}, + ), + ] diff --git a/seminar/models/soustredeni.py b/seminar/models/soustredeni.py index 275224a3..3f761444 100644 --- a/seminar/models/soustredeni.py +++ b/seminar/models/soustredeni.py @@ -20,6 +20,7 @@ logger = logging.getLogger(__name__) class Soustredeni(SeminarModelBase): class Meta: + managed = False db_table = 'seminar_soustredeni' verbose_name = 'Soustředění' verbose_name_plural = 'Soustředění' @@ -28,7 +29,7 @@ class Soustredeni(SeminarModelBase): # Interní ID id = models.AutoField(primary_key = True) - rocnik = models.ForeignKey(am.Rocnik, verbose_name='ročník', related_name='soustredeni', + rocnik = models.ForeignKey(am.Rocnik, verbose_name='ročník', related_name='soustredeni_old', on_delete=models.PROTECT) datum_zacatku = models.DateField('datum začátku', blank=True, null=True, @@ -43,9 +44,11 @@ class Soustredeni(SeminarModelBase): help_text='Místo (název obce, volitelně též objektu') ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci soustředění', + related_name='soustredeni_old', help_text='Seznam účastníků soustředění', through='Soustredeni_Ucastnici') organizatori = models.ManyToManyField(Organizator, + related_name='soustredeni_old', verbose_name='Organizátoři soustředění', help_text='Seznam organizátorů soustředění', through='Soustredeni_Organizatori') @@ -84,6 +87,7 @@ class Soustredeni_Ucastnici(SeminarModelBase): # zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu class Meta: + managed = False db_table = 'seminar_soustredeni_ucastnici' verbose_name = 'Účast na soustředění' verbose_name_plural = 'Účasti na soustředění' @@ -92,9 +96,12 @@ class Soustredeni_Ucastnici(SeminarModelBase): # Interní ID id = models.AutoField(primary_key = True) - resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + resitel = models.ForeignKey(Resitel, verbose_name='řešitel', + related_name='sous_ucastnici', + on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', + related_name='sous_ucastnici', on_delete=models.PROTECT) poznamka = models.TextField('neveřejná poznámka', blank=True, @@ -110,6 +117,7 @@ class Soustredeni_Organizatori(SeminarModelBase): # zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu class Meta: + managed = False db_table = 'seminar_soustredeni_organizatori' verbose_name = 'Účast organizátorů na soustředění' verbose_name_plural = 'Účasti organizátorů na soustředění' @@ -119,9 +127,11 @@ class Soustredeni_Organizatori(SeminarModelBase): id = models.AutoField(primary_key = True) organizator = models.ForeignKey(Organizator, verbose_name='organizátor', + related_name='sous_orgove', on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', + related_name='sous_orgove', on_delete=models.PROTECT) poznamka = models.TextField('neveřejná poznámka', blank=True, @@ -152,10 +162,13 @@ def generate_filename_konfera(self, filename): @reversion.register(ignore_duplicates=True) class Konfera(am.Problem): class Meta: + managed = False db_table = 'seminar_konfera' verbose_name = 'Konfera' verbose_name_plural = 'Konfery' + problem_ptr_old = models.OneToOneField(am.Problem, parent_link=True, related_name='konfera_old', on_delete=models.PROTECT, primary_key=True) + anotace = models.TextField('anotace', blank=True, help_text='Popis, o čem bude konfera.') @@ -164,10 +177,11 @@ class Konfera(am.Problem): # FIXME: Umíme omezit jen na účastníky daného soustřeďka? ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', + related_name='konfera_old', help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', - related_name='konfery', on_delete = models.SET_NULL, null=True) + related_name='konfery_old', on_delete = models.SET_NULL, null=True) TYP_VELETRH = 'veletrh' TYP_PREZENTACE = 'prezentace' @@ -196,6 +210,7 @@ class Konfera(am.Problem): class Konfery_Ucastnici(models.Model): class Meta: + managed = False db_table = 'seminar_konfery_ucastnici' verbose_name = 'Účast na konfeře' verbose_name_plural = 'Účasti na konfeře' @@ -204,9 +219,9 @@ class Konfery_Ucastnici(models.Model): # Interní ID id = models.AutoField(primary_key = True) - resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT, related_name='konf_uc') - konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE) + konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE, related_name='konf_uc') poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k účasti (plain text)') diff --git a/soustredeni/migrations/0001_split_from_seminar.py b/soustredeni/migrations/0001_split_from_seminar.py new file mode 100644 index 00000000..745f62e7 --- /dev/null +++ b/soustredeni/migrations/0001_split_from_seminar.py @@ -0,0 +1,119 @@ +# Generated by Django 4.2.11 on 2024-04-30 22:53 + +from django.db import migrations, models +import django.db.models.deletion +import soustredeni.models + +def nastav_nove_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + for m in ('konfera', 'soustredeni', 'soustredeni_ucastnici', 'soustredeni_organizatori', 'konfery_ucastnici'): + oct = ContentType.objects.filter(app_label='seminar', model=m) + oct.update(app_label='soustredeni') + +def nastav_stare_contenttypes(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + for m in ('konfera', 'soustredeni', 'soustredeni_ucastnici', 'soustredeni_organizatori', 'konfery_ucastnici'): + nct = ContentType.objects.filter(app_label='soustredeni', model=m) + nct.update(app_label='seminar') + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('seminar', '0123_soustredeni_unmanage'), + ] + + operations = [ + migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes), + + migrations.CreateModel( + name='Konfera', + fields=[ + ('problem_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.problem')), + ('anotace', models.TextField(blank=True, help_text='Popis, o čem bude konfera.', verbose_name='anotace')), + ('abstrakt', models.TextField(blank=True, help_text='Abstrakt konfery tak, jak byl uveden ve sborníku', verbose_name='abstrakt')), + ('typ_prezentace', models.CharField(choices=[('veletrh', 'Veletrh (postery)'), ('prezentace', 'Prezentace (přednáška)')], default='veletrh', max_length=16, verbose_name='typ prezentace')), + ('prezentace', models.FileField(blank=True, help_text='Prezentace nebo fotka posteru', upload_to=soustredeni.models.generate_filename_konfera, verbose_name='prezentace')), + ('materialy', models.FileField(blank=True, help_text='Další materiály ke konfeře zabalené do jednoho souboru', upload_to=soustredeni.models.generate_filename_konfera, verbose_name='materialy')), + ('soustredeni', models.ForeignKey(to='soustredeni.soustredeni', verbose_name='soustředění', on_delete=models.PROTECT)), + ], + options={ + 'verbose_name': 'Konfera', + 'verbose_name_plural': 'Konfery', + 'db_table': 'seminar_konfera', + 'managed': False, + }, + bases=('seminar.problem',), + ), + migrations.CreateModel( + name='Konfery_Ucastnici', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k účasti (plain text)', verbose_name='neveřejná poznámka')), + ('resitel', models.ForeignKey(to='personalni.resitel', verbose_name='řešitel', on_delete=models.PROTECT)), + ('konfera', models.ForeignKey(to='soustredeni.konfera', verbose_name='konfera', on_delete=models.CASCADE)), + ], + options={ + 'verbose_name': 'Účast na konfeře', + 'verbose_name_plural': 'Účasti na konfeře', + 'db_table': 'seminar_konfery_ucastnici', + 'ordering': ['konfera', 'resitel'], + 'managed': False, + }, + ), + migrations.CreateModel( + name='Soustredeni', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('datum_zacatku', models.DateField(blank=True, help_text='První den soustředění', null=True, verbose_name='datum začátku')), + ('datum_konce', models.DateField(blank=True, help_text='Poslední den soustředění', null=True, verbose_name='datum konce')), + ('verejne_db', models.BooleanField(db_column='verejne', default=False, verbose_name='soustředění zveřejněno')), + ('misto', models.CharField(blank=True, default='', help_text='Místo (název obce, volitelně též objektu', max_length=256, verbose_name='místo soustředění')), + ('text', models.TextField(blank=True, default='', verbose_name='text k soustředění (HTML)')), + ('typ', models.CharField(choices=[('jarni', 'Jarní soustředění'), ('podzimni', 'Podzimní soustředění'), ('vikend', 'Víkendový sraz'), ('vylet', 'Výlet')], default='podzimni', max_length=16, verbose_name='typ akce')), + ('exportovat', models.BooleanField(db_column='exportovat', default=False, help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)', verbose_name='export do AESOPa')), + ('rocnik', models.ForeignKey(to='seminar.rocnik', verbose_name='ročník', related_name='soustredeni', on_delete=models.PROTECT)), + ], + options={ + 'verbose_name': 'Soustředění', + 'verbose_name_plural': 'Soustředění', + 'db_table': 'seminar_soustredeni', + 'ordering': ['-rocnik__rocnik', '-datum_zacatku'], + 'managed': False, + }, + ), + migrations.CreateModel( + name='Soustredeni_Organizatori', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k účasti organizátora (plain text)', verbose_name='neveřejná poznámka')), + ('organizator', models.ForeignKey(to='personalni.organizator', verbose_name='organizátor', on_delete=models.PROTECT)), + ('soustredeni', models.ForeignKey(to='soustredeni.soustredeni', verbose_name='soustředění', on_delete=models.PROTECT)), + ], + options={ + 'verbose_name': 'Účast organizátorů na soustředění', + 'verbose_name_plural': 'Účasti organizátorů na soustředění', + 'db_table': 'seminar_soustredeni_organizatori', + 'ordering': ['soustredeni', 'organizator'], + 'managed': False, + }, + ), + migrations.CreateModel( + name='Soustredeni_Ucastnici', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k účasti (plain text)', verbose_name='neveřejná poznámka')), + ('resitel', models.ForeignKey(to='personalni.resitel', verbose_name='řešitel', on_delete=models.PROTECT)), + ('soustredeni', models.ForeignKey(to='soustredeni.soustredeni', verbose_name='soustředění', on_delete=models.PROTECT)), + ], + options={ + 'verbose_name': 'Účast na soustředění', + 'verbose_name_plural': 'Účasti na soustředění', + 'db_table': 'seminar_soustredeni_ucastnici', + 'ordering': ['soustredeni', 'resitel'], + 'managed': False, + }, + ), + ] diff --git a/soustredeni/models.py b/soustredeni/models.py new file mode 100644 index 00000000..4429e2bf --- /dev/null +++ b/soustredeni/models.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +import logging +import os + +from django.db import models +from django.urls import reverse +from reversion import revisions as reversion + +from django.conf import settings + +from personalni.models import Resitel, Organizator + +from seminar.models.base import SeminarModelBase +from seminar.models import tvorba as am + +logger = logging.getLogger(__name__) + + +@reversion.register(ignore_duplicates=True) +class Soustredeni(SeminarModelBase): + + class Meta: + managed = False + db_table = 'seminar_soustredeni' + verbose_name = 'Soustředění' + verbose_name_plural = 'Soustředění' + ordering = ['-rocnik__rocnik', '-datum_zacatku'] + + # Interní ID + id = models.AutoField(primary_key = True) + + rocnik = models.ForeignKey(am.Rocnik, verbose_name='ročník', related_name='soustredeni', + on_delete=models.PROTECT) + + datum_zacatku = models.DateField('datum začátku', blank=True, null=True, + help_text='První den soustředění') + + datum_konce = models.DateField('datum konce', blank=True, null=True, + help_text='Poslední den soustředění') + + verejne_db = models.BooleanField('soustředění zveřejněno', db_column='verejne', default=False) + + misto = models.CharField('místo soustředění', max_length=256, blank=True, default='', + help_text='Místo (název obce, volitelně též objektu') + + ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci soustředění', + help_text='Seznam účastníků soustředění', through='Soustredeni_Ucastnici') + + organizatori = models.ManyToManyField(Organizator, + verbose_name='Organizátoři soustředění', + help_text='Seznam organizátorů soustředění', + through='Soustredeni_Organizatori') + + text = models.TextField('text k soustředění (HTML)', blank=True, default='') + + TYP_JARNI = 'jarni' + TYP_PODZIMNI = 'podzimni' + TYP_VIKEND = 'vikend' + TYP_VYLET = 'vylet' + TYP_CHOICES = [ + (TYP_JARNI, 'Jarní soustředění'), + (TYP_PODZIMNI, 'Podzimní soustředění'), + (TYP_VIKEND, 'Víkendový sraz'), + (TYP_VYLET, 'Výlet'), + ] + typ = models.CharField('typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI) + + exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False, + help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)') + + def __str__(self): + return '{} ({})'.format(self.misto, self.datum_zacatku) + + def verejne(self): + return self.verejne_db + verejne.boolean = True + + def verejne_url(self): + #return reverse('seminar_soustredeni', kwargs={'pk': self.id}) + return reverse('seminar_seznam_soustredeni') + + +@reversion.register(ignore_duplicates=True) +class Soustredeni_Ucastnici(SeminarModelBase): +# zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu + + class Meta: + managed = False + db_table = 'seminar_soustredeni_ucastnici' + verbose_name = 'Účast na soustředění' + verbose_name_plural = 'Účasti na soustředění' + ordering = ['soustredeni', 'resitel'] + + # Interní ID + id = models.AutoField(primary_key = True) + + resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + + soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', + on_delete=models.PROTECT) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k účasti (plain text)') + + def __str__(self): + return '{} na {}'.format(self.resitel, self.soustredeni) + # NOTE: Poteciální DB HOG bez select_related + + +@reversion.register(ignore_duplicates=True) +class Soustredeni_Organizatori(SeminarModelBase): +# zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu + + class Meta: + managed = False + db_table = 'seminar_soustredeni_organizatori' + verbose_name = 'Účast organizátorů na soustředění' + verbose_name_plural = 'Účasti organizátorů na soustředění' + ordering = ['soustredeni', 'organizator'] + + # Interní ID + id = models.AutoField(primary_key = True) + + organizator = models.ForeignKey(Organizator, verbose_name='organizátor', + on_delete=models.PROTECT) + + soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', + on_delete=models.PROTECT) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k účasti organizátora (plain text)') + + def __str__(self): + return '{} na {}'.format(self.organizator, self.soustredeni) + # NOTE: Poteciální DB HOG bez select_related + + +# FIXME cycle import + + +# Django neumí jednoduše serializovat partial nebo třídu s __call__ +# (https://docs.djangoproject.com/en/1.8/topics/migrations/), +# neprojdou pak migrace. Takže rozlišení funkcí generujících názvy souboru +# podle adresáře řešíme takto. + +## +def generate_filename_konfera(self, filename): + return os.path.join( + settings.SEMINAR_KONFERY_DIR, + am.aux_generate_filename(self, filename) + ) + +## + +@reversion.register(ignore_duplicates=True) +class Konfera(am.Problem): + class Meta: + managed = False + db_table = 'seminar_konfera' + verbose_name = 'Konfera' + verbose_name_plural = 'Konfery' + + anotace = models.TextField('anotace', blank=True, + help_text='Popis, o čem bude konfera.') + + abstrakt = models.TextField('abstrakt', blank=True, + help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') + + # FIXME: Umíme omezit jen na účastníky daného soustřeďka? + ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', + help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') + + soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', + related_name='konfery', on_delete = models.SET_NULL, null=True) + + TYP_VELETRH = 'veletrh' + TYP_PREZENTACE = 'prezentace' + TYP_CHOICES = [ + (TYP_VELETRH, 'Veletrh (postery)'), + (TYP_PREZENTACE, 'Prezentace (přednáška)'), + ] + typ_prezentace = models.CharField('typ prezentace', max_length=16, choices=TYP_CHOICES, + blank=False, default=TYP_VELETRH) + + prezentace = models.FileField('prezentace',help_text = 'Prezentace nebo fotka posteru', + upload_to = generate_filename_konfera, blank=True) + + materialy = models.FileField('materialy', + help_text = 'Další materiály ke konfeře zabalené do jednoho souboru', + upload_to = generate_filename_konfera, blank=True) + + def __str__(self): + return "{}: ({})".format(self.nazev, self.soustredeni) + + def cislo_node(self): + return None + + +@reversion.register(ignore_duplicates=True) +class Konfery_Ucastnici(models.Model): + + class Meta: + managed = False + db_table = 'seminar_konfery_ucastnici' + verbose_name = 'Účast na konfeře' + verbose_name_plural = 'Účasti na konfeře' + ordering = ['konfera', 'resitel'] + + # Interní ID + id = models.AutoField(primary_key = True) + + resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) + + konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE) + + poznamka = models.TextField('neveřejná poznámka', blank=True, + help_text='Neveřejná poznámka k účasti (plain text)') + + def __str__(self): + return '{} na {}'.format(self.resitel, self.konfera) + # NOTE: Poteciální DB HOG bez select_related diff --git a/split-apps-meta/create.notes b/split-apps-meta/create.notes index 8d3174e3..606f76d8 100644 --- a/split-apps-meta/create.notes +++ b/split-apps-meta/create.notes @@ -1,6 +1,7 @@ Prostě zkopírovat vedle, s původními (=správnými) related names. + (Případně opravit *všechny* relativní importy) makemigrations ! Doplnit hack kolem content-types (jako první operace při migraci) -! Doplnit ForeignKeys (TODO: jak? Já jsem je ukradl až zpětně…) +! Doplnit ForeignKeys (Vypadá to, že se dá vesměs zkopírovat předpis z models.py, jen místo prvního fieldu dát `to='app.model'. Dokonce asi funguje použít už novou aplikaci pro vazby v rámci aplikace.) doplnit závislost na unmanage migrate diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes index 846b7314..bce419bf 100644 --- a/split-apps-meta/unmanage.notes +++ b/split-apps-meta/unmanage.notes @@ -16,6 +16,9 @@ vim seminar/models/whatever HINT: Add or change a related_name argument to the definition for 'seminar.Resitel.osoba' or 'seminar.Prijemce.osoba'. Snadné řešení: dočasné related names mít unikátní. Stejně to nikoho nezajímá. !! Zkontrolovat, že všechno má nastavenou db_table (jinak se to potom pokusí vybastlit jméno tabulky podle aplikace…) + Pro tip: related names nejsou součástí DB schématu, takže když se tohle opraví později (typicky při create spadne makemigrations), nevadí to a nemělo by být potřeba měnit migrace). + Pro multi-table inheritance je potřeba explicitně přidat 1to1Field s parent_link=True () + Je potřeba to udělat správně (třeba nemít FK), migrace potřeba není, protože je to stejně unmanaged… makemigrations, bez úprav migrate? From e3771f865d70835e6e84e7200399be0373908216 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 1 May 2024 15:37:54 +0200 Subject: [PATCH 52/59] =?UTF-8?q?Relink=20=E2=80=93=20post,=20asi=20done?= =?UTF-8?q?=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/migrations/0012_soustredeni_relink.py | 20 ++ .../migrations/0013_post_split_soustredeni.py | 14 ++ galerie/models.py | 2 +- .../migrations/0017_soustredeni_relink.py | 20 ++ .../migrations/0018_post_split_soustredeni.py | 14 ++ prednasky/models.py | 2 +- .../0124_remove_sous_from_seminar.py | 67 +++++ .../migrations/0125_post_split_soustredeni.py | 14 ++ seminar/models/__init__.py | 5 +- seminar/models/soustredeni.py | 231 ------------------ soustredeni/admin.py | 2 +- .../migrations/0001_split_from_seminar.py | 5 +- .../migrations/0002_manage_soustredeni.py | 34 +++ .../migrations/0003_post_split_soustredeni.py | 13 + soustredeni/models.py | 5 - split-apps-meta/create.notes | 2 + 16 files changed, 209 insertions(+), 241 deletions(-) create mode 100644 galerie/migrations/0012_soustredeni_relink.py create mode 100644 galerie/migrations/0013_post_split_soustredeni.py create mode 100644 prednasky/migrations/0017_soustredeni_relink.py create mode 100644 prednasky/migrations/0018_post_split_soustredeni.py create mode 100644 seminar/migrations/0124_remove_sous_from_seminar.py create mode 100644 seminar/migrations/0125_post_split_soustredeni.py delete mode 100644 seminar/models/soustredeni.py create mode 100644 soustredeni/migrations/0002_manage_soustredeni.py create mode 100644 soustredeni/migrations/0003_post_split_soustredeni.py diff --git a/galerie/migrations/0012_soustredeni_relink.py b/galerie/migrations/0012_soustredeni_relink.py new file mode 100644 index 00000000..0b8cbaff --- /dev/null +++ b/galerie/migrations/0012_soustredeni_relink.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:07 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('soustredeni', '0001_split_from_seminar'), + ('galerie', '0011_pre_split_soustredeni'), + ] + + operations = [ + migrations.AlterField( + model_name='galerie', + name='soustredeni', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='soustredeni.soustredeni'), + ), + ] diff --git a/galerie/migrations/0013_post_split_soustredeni.py b/galerie/migrations/0013_post_split_soustredeni.py new file mode 100644 index 00000000..de3cfa60 --- /dev/null +++ b/galerie/migrations/0013_post_split_soustredeni.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0012_soustredeni_relink'), + ('soustredeni', '0003_post_split_soustredeni'), + ] + + operations = [ + ] diff --git a/galerie/models.py b/galerie/models.py index 78551969..96225101 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -7,7 +7,7 @@ from imagekit.processors import ResizeToFit, Transpose import os -from seminar.models import Soustredeni +from soustredeni.models import Soustredeni VZDY=0 ORG=1 diff --git a/prednasky/migrations/0017_soustredeni_relink.py b/prednasky/migrations/0017_soustredeni_relink.py new file mode 100644 index 00000000..6542b51d --- /dev/null +++ b/prednasky/migrations/0017_soustredeni_relink.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:07 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('soustredeni', '0001_split_from_seminar'), + ('prednasky', '0016_pre_split_soustredeni'), + ] + + operations = [ + migrations.AlterField( + model_name='seznam', + name='soustredeni', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='soustredeni.soustredeni'), + ), + ] diff --git a/prednasky/migrations/0018_post_split_soustredeni.py b/prednasky/migrations/0018_post_split_soustredeni.py new file mode 100644 index 00000000..bd59819d --- /dev/null +++ b/prednasky/migrations/0018_post_split_soustredeni.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('prednasky', '0017_soustredeni_relink'), + ('soustredeni', '0003_post_split_soustredeni'), + ] + + operations = [ + ] diff --git a/prednasky/models.py b/prednasky/models.py index 7045f4d5..54764381 100644 --- a/prednasky/models.py +++ b/prednasky/models.py @@ -2,7 +2,7 @@ from django.db import models -from seminar.models import Soustredeni +from soustredeni.models import Soustredeni from personalni.models import Organizator STAV_NAVRH = 1 diff --git a/seminar/migrations/0124_remove_sous_from_seminar.py b/seminar/migrations/0124_remove_sous_from_seminar.py new file mode 100644 index 00000000..9acc3bc4 --- /dev/null +++ b/seminar/migrations/0124_remove_sous_from_seminar.py @@ -0,0 +1,67 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0123_soustredeni_unmanage'), + ('soustredeni', '0001_split_from_seminar'), + ('galerie', '0012_soustredeni_relink'), + ('prednasky', '0017_soustredeni_relink'), + ] + + operations = [ + migrations.RemoveField( + model_name='konfery_ucastnici', + name='konfera', + ), + migrations.RemoveField( + model_name='konfery_ucastnici', + name='resitel', + ), + migrations.RemoveField( + model_name='soustredeni', + name='organizatori', + ), + migrations.RemoveField( + model_name='soustredeni', + name='rocnik', + ), + migrations.RemoveField( + model_name='soustredeni', + name='ucastnici', + ), + migrations.RemoveField( + model_name='soustredeni_organizatori', + name='organizator', + ), + migrations.RemoveField( + model_name='soustredeni_organizatori', + name='soustredeni', + ), + migrations.RemoveField( + model_name='soustredeni_ucastnici', + name='resitel', + ), + migrations.RemoveField( + model_name='soustredeni_ucastnici', + name='soustredeni', + ), + migrations.DeleteModel( + name='Konfera', + ), + migrations.DeleteModel( + name='Konfery_Ucastnici', + ), + migrations.DeleteModel( + name='Soustredeni', + ), + migrations.DeleteModel( + name='Soustredeni_Organizatori', + ), + migrations.DeleteModel( + name='Soustredeni_Ucastnici', + ), + ] diff --git a/seminar/migrations/0125_post_split_soustredeni.py b/seminar/migrations/0125_post_split_soustredeni.py new file mode 100644 index 00000000..3d8c8c58 --- /dev/null +++ b/seminar/migrations/0125_post_split_soustredeni.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('seminar', '0124_remove_sous_from_seminar'), + ('soustredeni', '0003_post_split_soustredeni'), + ] + + operations = [ + ] diff --git a/seminar/models/__init__.py b/seminar/models/__init__.py index e3026a2c..121aeb04 100644 --- a/seminar/models/__init__.py +++ b/seminar/models/__init__.py @@ -1,10 +1,13 @@ from .tvorba import * from .odevzdavatko import * from .base import * -from .soustredeni import * from .pomocne import * from .treenode import * from .novinky import * from various.models import Nastaveni from personalni.models import Organizator, Resitel, Skola, Prijemce, Osoba +from soustredeni.models import Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Konfera, Konfery_Ucastnici + +# Kvůli migr. 0041 +from soustredeni.models import generate_filename_konfera diff --git a/seminar/models/soustredeni.py b/seminar/models/soustredeni.py deleted file mode 100644 index 3f761444..00000000 --- a/seminar/models/soustredeni.py +++ /dev/null @@ -1,231 +0,0 @@ -# -*- coding: utf-8 -*- -import logging -import os - -from django.db import models -from django.urls import reverse -from reversion import revisions as reversion - -from django.conf import settings - -from personalni.models import Resitel, Organizator - -from .base import SeminarModelBase -from seminar.models import tvorba as am - -logger = logging.getLogger(__name__) - - -@reversion.register(ignore_duplicates=True) -class Soustredeni(SeminarModelBase): - - class Meta: - managed = False - db_table = 'seminar_soustredeni' - verbose_name = 'Soustředění' - verbose_name_plural = 'Soustředění' - ordering = ['-rocnik__rocnik', '-datum_zacatku'] - - # Interní ID - id = models.AutoField(primary_key = True) - - rocnik = models.ForeignKey(am.Rocnik, verbose_name='ročník', related_name='soustredeni_old', - on_delete=models.PROTECT) - - datum_zacatku = models.DateField('datum začátku', blank=True, null=True, - help_text='První den soustředění') - - datum_konce = models.DateField('datum konce', blank=True, null=True, - help_text='Poslední den soustředění') - - verejne_db = models.BooleanField('soustředění zveřejněno', db_column='verejne', default=False) - - misto = models.CharField('místo soustředění', max_length=256, blank=True, default='', - help_text='Místo (název obce, volitelně též objektu') - - ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci soustředění', - related_name='soustredeni_old', - help_text='Seznam účastníků soustředění', through='Soustredeni_Ucastnici') - - organizatori = models.ManyToManyField(Organizator, - related_name='soustredeni_old', - verbose_name='Organizátoři soustředění', - help_text='Seznam organizátorů soustředění', - through='Soustredeni_Organizatori') - - text = models.TextField('text k soustředění (HTML)', blank=True, default='') - - TYP_JARNI = 'jarni' - TYP_PODZIMNI = 'podzimni' - TYP_VIKEND = 'vikend' - TYP_VYLET = 'vylet' - TYP_CHOICES = [ - (TYP_JARNI, 'Jarní soustředění'), - (TYP_PODZIMNI, 'Podzimní soustředění'), - (TYP_VIKEND, 'Víkendový sraz'), - (TYP_VYLET, 'Výlet'), - ] - typ = models.CharField('typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI) - - exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False, - help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)') - - def __str__(self): - return '{} ({})'.format(self.misto, self.datum_zacatku) - - def verejne(self): - return self.verejne_db - verejne.boolean = True - - def verejne_url(self): - #return reverse('seminar_soustredeni', kwargs={'pk': self.id}) - return reverse('seminar_seznam_soustredeni') - - -@reversion.register(ignore_duplicates=True) -class Soustredeni_Ucastnici(SeminarModelBase): -# zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu - - class Meta: - managed = False - db_table = 'seminar_soustredeni_ucastnici' - verbose_name = 'Účast na soustředění' - verbose_name_plural = 'Účasti na soustředění' - ordering = ['soustredeni', 'resitel'] - - # Interní ID - id = models.AutoField(primary_key = True) - - resitel = models.ForeignKey(Resitel, verbose_name='řešitel', - related_name='sous_ucastnici', - on_delete=models.PROTECT) - - soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', - related_name='sous_ucastnici', - on_delete=models.PROTECT) - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k účasti (plain text)') - - def __str__(self): - return '{} na {}'.format(self.resitel, self.soustredeni) - # NOTE: Poteciální DB HOG bez select_related - - -@reversion.register(ignore_duplicates=True) -class Soustredeni_Organizatori(SeminarModelBase): -# zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu - - class Meta: - managed = False - db_table = 'seminar_soustredeni_organizatori' - verbose_name = 'Účast organizátorů na soustředění' - verbose_name_plural = 'Účasti organizátorů na soustředění' - ordering = ['soustredeni', 'organizator'] - - # Interní ID - id = models.AutoField(primary_key = True) - - organizator = models.ForeignKey(Organizator, verbose_name='organizátor', - related_name='sous_orgove', - on_delete=models.PROTECT) - - soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', - related_name='sous_orgove', - on_delete=models.PROTECT) - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k účasti organizátora (plain text)') - - def __str__(self): - return '{} na {}'.format(self.organizator, self.soustredeni) - # NOTE: Poteciální DB HOG bez select_related - - -# FIXME cycle import - - -# Django neumí jednoduše serializovat partial nebo třídu s __call__ -# (https://docs.djangoproject.com/en/1.8/topics/migrations/), -# neprojdou pak migrace. Takže rozlišení funkcí generujících názvy souboru -# podle adresáře řešíme takto. - -## -def generate_filename_konfera(self, filename): - return os.path.join( - settings.SEMINAR_KONFERY_DIR, - am.aux_generate_filename(self, filename) - ) - -## - -@reversion.register(ignore_duplicates=True) -class Konfera(am.Problem): - class Meta: - managed = False - db_table = 'seminar_konfera' - verbose_name = 'Konfera' - verbose_name_plural = 'Konfery' - - problem_ptr_old = models.OneToOneField(am.Problem, parent_link=True, related_name='konfera_old', on_delete=models.PROTECT, primary_key=True) - - anotace = models.TextField('anotace', blank=True, - help_text='Popis, o čem bude konfera.') - - abstrakt = models.TextField('abstrakt', blank=True, - help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') - - # FIXME: Umíme omezit jen na účastníky daného soustřeďka? - ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', - related_name='konfera_old', - help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') - - soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', - related_name='konfery_old', on_delete = models.SET_NULL, null=True) - - TYP_VELETRH = 'veletrh' - TYP_PREZENTACE = 'prezentace' - TYP_CHOICES = [ - (TYP_VELETRH, 'Veletrh (postery)'), - (TYP_PREZENTACE, 'Prezentace (přednáška)'), - ] - typ_prezentace = models.CharField('typ prezentace', max_length=16, choices=TYP_CHOICES, - blank=False, default=TYP_VELETRH) - - prezentace = models.FileField('prezentace',help_text = 'Prezentace nebo fotka posteru', - upload_to = generate_filename_konfera, blank=True) - - materialy = models.FileField('materialy', - help_text = 'Další materiály ke konfeře zabalené do jednoho souboru', - upload_to = generate_filename_konfera, blank=True) - - def __str__(self): - return "{}: ({})".format(self.nazev, self.soustredeni) - - def cislo_node(self): - return None - - -@reversion.register(ignore_duplicates=True) -class Konfery_Ucastnici(models.Model): - - class Meta: - managed = False - db_table = 'seminar_konfery_ucastnici' - verbose_name = 'Účast na konfeře' - verbose_name_plural = 'Účasti na konfeře' - ordering = ['konfera', 'resitel'] - - # Interní ID - id = models.AutoField(primary_key = True) - - resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT, related_name='konf_uc') - - konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE, related_name='konf_uc') - - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka k účasti (plain text)') - - def __str__(self): - return '{} na {}'.format(self.resitel, self.konfera) - # NOTE: Poteciální DB HOG bez select_related diff --git a/soustredeni/admin.py b/soustredeni/admin.py index c6f048db..048b9ec3 100644 --- a/soustredeni/admin.py +++ b/soustredeni/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.forms import widgets from django.db import models -from seminar.models import soustredeni as m +import soustredeni.models as m class SoustredeniUcastniciInline(admin.TabularInline): diff --git a/soustredeni/migrations/0001_split_from_seminar.py b/soustredeni/migrations/0001_split_from_seminar.py index 745f62e7..c5e432d3 100644 --- a/soustredeni/migrations/0001_split_from_seminar.py +++ b/soustredeni/migrations/0001_split_from_seminar.py @@ -37,7 +37,8 @@ class Migration(migrations.Migration): ('typ_prezentace', models.CharField(choices=[('veletrh', 'Veletrh (postery)'), ('prezentace', 'Prezentace (přednáška)')], default='veletrh', max_length=16, verbose_name='typ prezentace')), ('prezentace', models.FileField(blank=True, help_text='Prezentace nebo fotka posteru', upload_to=soustredeni.models.generate_filename_konfera, verbose_name='prezentace')), ('materialy', models.FileField(blank=True, help_text='Další materiály ke konfeře zabalené do jednoho souboru', upload_to=soustredeni.models.generate_filename_konfera, verbose_name='materialy')), - ('soustredeni', models.ForeignKey(to='soustredeni.soustredeni', verbose_name='soustředění', on_delete=models.PROTECT)), + ('soustredeni', models.ForeignKey(to='soustredeni.soustredeni', verbose_name='soustředění', on_delete=models.SET_NULL, null=True, related_name='konfery')), + ('ucastnici', models.ManyToManyField(help_text='Seznam účastníků konfery', through='soustredeni.Konfery_Ucastnici', to='personalni.resitel', verbose_name='účastníci konfery')), ], options={ 'verbose_name': 'Konfera', @@ -75,6 +76,8 @@ class Migration(migrations.Migration): ('typ', models.CharField(choices=[('jarni', 'Jarní soustředění'), ('podzimni', 'Podzimní soustředění'), ('vikend', 'Víkendový sraz'), ('vylet', 'Výlet')], default='podzimni', max_length=16, verbose_name='typ akce')), ('exportovat', models.BooleanField(db_column='exportovat', default=False, help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)', verbose_name='export do AESOPa')), ('rocnik', models.ForeignKey(to='seminar.rocnik', verbose_name='ročník', related_name='soustredeni', on_delete=models.PROTECT)), + ('organizatori', models.ManyToManyField(help_text='Seznam organizátorů soustředění', through='soustredeni.Soustredeni_Organizatori', to='personalni.organizator', verbose_name='Organizátoři soustředění')), + ('ucastnici', models.ManyToManyField(help_text='Seznam účastníků soustředění', through='soustredeni.Soustredeni_Ucastnici', to='personalni.resitel', verbose_name='účastníci soustředění')), ], options={ 'verbose_name': 'Soustředění', diff --git a/soustredeni/migrations/0002_manage_soustredeni.py b/soustredeni/migrations/0002_manage_soustredeni.py new file mode 100644 index 00000000..1a535eb0 --- /dev/null +++ b/soustredeni/migrations/0002_manage_soustredeni.py @@ -0,0 +1,34 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('soustredeni', '0001_split_from_seminar'), + ('seminar', '0124_remove_sous_from_seminar'), + ] + + operations = [ + migrations.AlterModelOptions( + name='konfera', + options={'verbose_name': 'Konfera', 'verbose_name_plural': 'Konfery'}, + ), + migrations.AlterModelOptions( + name='konfery_ucastnici', + options={'ordering': ['konfera', 'resitel'], 'verbose_name': 'Účast na konfeře', 'verbose_name_plural': 'Účasti na konfeře'}, + ), + migrations.AlterModelOptions( + name='soustredeni', + options={'ordering': ['-rocnik__rocnik', '-datum_zacatku'], 'verbose_name': 'Soustředění', 'verbose_name_plural': 'Soustředění'}, + ), + migrations.AlterModelOptions( + name='soustredeni_organizatori', + options={'ordering': ['soustredeni', 'organizator'], 'verbose_name': 'Účast organizátorů na soustředění', 'verbose_name_plural': 'Účasti organizátorů na soustředění'}, + ), + migrations.AlterModelOptions( + name='soustredeni_ucastnici', + options={'ordering': ['soustredeni', 'resitel'], 'verbose_name': 'Účast na soustředění', 'verbose_name_plural': 'Účasti na soustředění'}, + ), + ] diff --git a/soustredeni/migrations/0003_post_split_soustredeni.py b/soustredeni/migrations/0003_post_split_soustredeni.py new file mode 100644 index 00000000..ad1821ee --- /dev/null +++ b/soustredeni/migrations/0003_post_split_soustredeni.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.11 on 2024-05-01 13:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('soustredeni', '0002_manage_soustredeni'), + ] + + operations = [ + ] diff --git a/soustredeni/models.py b/soustredeni/models.py index 4429e2bf..78582565 100644 --- a/soustredeni/models.py +++ b/soustredeni/models.py @@ -20,7 +20,6 @@ logger = logging.getLogger(__name__) class Soustredeni(SeminarModelBase): class Meta: - managed = False db_table = 'seminar_soustredeni' verbose_name = 'Soustředění' verbose_name_plural = 'Soustředění' @@ -85,7 +84,6 @@ class Soustredeni_Ucastnici(SeminarModelBase): # zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu class Meta: - managed = False db_table = 'seminar_soustredeni_ucastnici' verbose_name = 'Účast na soustředění' verbose_name_plural = 'Účasti na soustředění' @@ -112,7 +110,6 @@ class Soustredeni_Organizatori(SeminarModelBase): # zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu class Meta: - managed = False db_table = 'seminar_soustredeni_organizatori' verbose_name = 'Účast organizátorů na soustředění' verbose_name_plural = 'Účasti organizátorů na soustředění' @@ -155,7 +152,6 @@ def generate_filename_konfera(self, filename): @reversion.register(ignore_duplicates=True) class Konfera(am.Problem): class Meta: - managed = False db_table = 'seminar_konfera' verbose_name = 'Konfera' verbose_name_plural = 'Konfery' @@ -200,7 +196,6 @@ class Konfera(am.Problem): class Konfery_Ucastnici(models.Model): class Meta: - managed = False db_table = 'seminar_konfery_ucastnici' verbose_name = 'Účast na konfeře' verbose_name_plural = 'Účasti na konfeře' diff --git a/split-apps-meta/create.notes b/split-apps-meta/create.notes index 606f76d8..a48a17f8 100644 --- a/split-apps-meta/create.notes +++ b/split-apps-meta/create.notes @@ -3,5 +3,7 @@ Prostě zkopírovat vedle, s původními (=správnými) related names. makemigrations ! Doplnit hack kolem content-types (jako první operace při migraci) ! Doplnit ForeignKeys (Vypadá to, že se dá vesměs zkopírovat předpis z models.py, jen místo prvního fieldu dát `to='app.model'. Dokonce asi funguje použít už novou aplikaci pro vazby v rámci aplikace.) + To samé s ManyToManyFieldy (through= musí taky být 'app.model') +(Zdá se, že jde dobastlit tuhle migraci polozpětně – doplnit co chybělo až podle toho, co vygeneruje migrace po zamanagování nového modelu.) doplnit závislost na unmanage migrate From 8c4bf4d19a99980e3e3430c26bc759d18a9df8d8 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 1 May 2024 15:48:33 +0200 Subject: [PATCH 53/59] =?UTF-8?q?Oprava=20jmen=20model=C5=AF=20v=20org=20p?= =?UTF-8?q?r=C3=A1vech?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy_v2/admin_org_prava.json | 70 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/deploy_v2/admin_org_prava.json b/deploy_v2/admin_org_prava.json index 3ef169a5..01de7476 100644 --- a/deploy_v2/admin_org_prava.json +++ b/deploy_v2/admin_org_prava.json @@ -271,42 +271,42 @@ }, { "codename": "add_konfera", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfera" }, { "codename": "change_konfera", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfera" }, { "codename": "delete_konfera", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfera" }, { "codename": "view_konfera", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfera" }, { "codename": "add_konfery_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfery_ucastnici" }, { "codename": "change_konfery_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfery_ucastnici" }, { "codename": "delete_konfery_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfery_ucastnici" }, { "codename": "view_konfery_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "konfery_ucastnici" }, { @@ -351,22 +351,22 @@ }, { "codename": "change_organizator", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "organizator" }, { "codename": "view_organizator", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "organizator" }, { "codename": "change_osoba", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "osoba" }, { "codename": "view_osoba", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "osoba" }, { @@ -391,22 +391,22 @@ }, { "codename": "add_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { "codename": "change_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { "codename": "delete_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { "codename": "view_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { @@ -431,12 +431,12 @@ }, { "codename": "change_resitel", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "resitel" }, { "codename": "view_resitel", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "resitel" }, { @@ -461,82 +461,82 @@ }, { "codename": "add_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "change_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "delete_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "view_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "add_soustredeni", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni" }, { "codename": "change_soustredeni", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni" }, { "codename": "delete_soustredeni", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni" }, { "codename": "view_soustredeni", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni" }, { "codename": "add_soustredeni_organizatori", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_organizatori" }, { "codename": "change_soustredeni_organizatori", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_organizatori" }, { "codename": "delete_soustredeni_organizatori", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_organizatori" }, { "codename": "view_soustredeni_organizatori", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_organizatori" }, { "codename": "add_soustredeni_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_ucastnici" }, { "codename": "change_soustredeni_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_ucastnici" }, { "codename": "delete_soustredeni_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_ucastnici" }, { "codename": "view_soustredeni_ucastnici", - "ct_app_label": "seminar", + "ct_app_label": "soustredeni", "ct_model": "soustredeni_ucastnici" }, { @@ -619,4 +619,4 @@ "ct_app_label": "taggit", "ct_model": "taggeditem" } -] \ No newline at end of file +] From e075a9e749613c4bf9081e065af5b394371e28fd Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 1 May 2024 16:27:39 +0200 Subject: [PATCH 54/59] =?UTF-8?q?Oprava=20jmen=20model=C5=AF=20po=20odst?= =?UTF-8?q?=C5=99elu=20person=C3=A1li=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy_v2/admin_org_prava.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/deploy_v2/admin_org_prava.json b/deploy_v2/admin_org_prava.json index 3ef169a5..0bc582fb 100644 --- a/deploy_v2/admin_org_prava.json +++ b/deploy_v2/admin_org_prava.json @@ -351,22 +351,22 @@ }, { "codename": "change_organizator", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "organizator" }, { "codename": "view_organizator", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "organizator" }, { "codename": "change_osoba", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "osoba" }, { "codename": "view_osoba", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "osoba" }, { @@ -391,22 +391,22 @@ }, { "codename": "add_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { "codename": "change_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { "codename": "delete_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { "codename": "view_prijemce", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "prijemce" }, { @@ -431,12 +431,12 @@ }, { "codename": "change_resitel", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "resitel" }, { "codename": "view_resitel", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "resitel" }, { @@ -461,22 +461,22 @@ }, { "codename": "add_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "change_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "delete_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { "codename": "view_skola", - "ct_app_label": "seminar", + "ct_app_label": "personalni", "ct_model": "skola" }, { From 9f08ec332faa94ea591f84915ba6507c0b176f72 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 1 May 2024 16:31:54 +0200 Subject: [PATCH 55/59] =?UTF-8?q?Oprava=20jmen=20model=C5=AF=20po=20odst?= =?UTF-8?q?=C5=99elu=20nastaven=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy_v2/admin_org_prava.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy_v2/admin_org_prava.json b/deploy_v2/admin_org_prava.json index 0bc582fb..bfac6c77 100644 --- a/deploy_v2/admin_org_prava.json +++ b/deploy_v2/admin_org_prava.json @@ -311,22 +311,22 @@ }, { "codename": "add_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { "codename": "change_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { "codename": "delete_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { "codename": "view_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { @@ -619,4 +619,4 @@ "ct_app_label": "taggit", "ct_model": "taggeditem" } -] \ No newline at end of file +] From 6c59c3c2ed1169b0e3e3c5d421a7eec043adf873 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 1 May 2024 16:31:54 +0200 Subject: [PATCH 56/59] =?UTF-8?q?Oprava=20jmen=20model=C5=AF=20po=20odst?= =?UTF-8?q?=C5=99elu=20nastaven=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy_v2/admin_org_prava.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy_v2/admin_org_prava.json b/deploy_v2/admin_org_prava.json index 01de7476..9caa6eb2 100644 --- a/deploy_v2/admin_org_prava.json +++ b/deploy_v2/admin_org_prava.json @@ -311,22 +311,22 @@ }, { "codename": "add_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { "codename": "change_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { "codename": "delete_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { "codename": "view_nastaveni", - "ct_app_label": "seminar", + "ct_app_label": "various", "ct_model": "nastaveni" }, { From 7569447baaf9f51a3efd44b0cd3cdb75aa93b8f0 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 13 May 2024 22:12:51 +0200 Subject: [PATCH 57/59] Oprava assertEquals na assertEqual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit první je deprecated a v Py3.12 už nefunguje. --- various/tests.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/various/tests.py b/various/tests.py index 0abf4e26..0bb094fb 100644 --- a/various/tests.py +++ b/various/tests.py @@ -6,18 +6,18 @@ class MailTagsTest(TestCase): """Testuje template tagy ohledně mailů.""" def test_maillink(self): # Tohle nedává smysl dělit do víc funkcí, bylo by v nich víc boilerplatu než užitečného kódu. - self.assertEquals(maillink('Hello', to='some@body.test'), r'Hello') - self.assertEquals(maillink('Hello', to=['some@body.test']), r'Hello') - self.assertEquals( + self.assertEqual(maillink('Hello', to='some@body.test'), r'Hello') + self.assertEqual(maillink('Hello', to=['some@body.test']), r'Hello') + self.assertEqual( maillink('Hello', to=['alice@test.test', 'bob@jinde.test']), r'Hello', ) - self.assertEquals( + self.assertEqual( maillink('Hello', to='some@body.test', attrs='class="trida" id="id"'), r'Hello', ) # Následující test toho testuje moc zároveň, měly by předcházet dedikované testy… (kašlu na ně :-P) - self.assertEquals( + self.assertEqual( maillink('Text odkazu', to='prijemce@wtf.test', subject="Předmět", body="Čau"), r'Text odkazu', ) @@ -25,10 +25,10 @@ class MailTagsTest(TestCase): self.assertRaises(TypeError, lambda: maillink()) # Nemá text, takže to shodí python def test_mailurl(self): - self.assertEquals(mailurl(to='some@body.test'), r'mailto:some@body.test') - self.assertEquals(mailurl(to=['some@body.test']), r'mailto:some@body.test') - self.assertEquals(mailurl(to=['alice@test.test', 'bob@jinde.test']), r'mailto:alice@test.test,bob@jinde.test') - self.assertEquals( + self.assertEqual(mailurl(to='some@body.test'), r'mailto:some@body.test') + self.assertEqual(mailurl(to=['some@body.test']), r'mailto:some@body.test') + self.assertEqual(mailurl(to=['alice@test.test', 'bob@jinde.test']), r'mailto:alice@test.test,bob@jinde.test') + self.assertEqual( mailurl(to='some@body.test', body='Tělo', subject='Předmět'), r'mailto:some@body.test?subject=P%C5%99edm%C4%9Bt&body=T%C4%9Blo', ) @@ -48,7 +48,7 @@ class MailTagsTest(TestCase): # TODO: Vyzkoušet i víc adresátů. (Nepamatuji si z hlavy syntaxi…) r'{% maillink "Text" to="alice@test.test" subject="Oprava řešení" %}' ) - self.assertEquals( + self.assertEqual( render_template(template), r'Text', ) @@ -57,4 +57,4 @@ class MailTagsTest(TestCase): r'{% load mail %}' r'{% mailurl to="alice@test.test" subject="Čau Alice" %}' ) - self.assertEquals(render_template(mailurltemplate), r'mailto:alice@test.test?subject=%C4%8Cau%20Alice') + self.assertEqual(render_template(mailurltemplate), r'mailto:alice@test.test?subject=%C4%8Cau%20Alice') From e618d390de20365dec01fe3cb1317d8b487932d9 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Mon, 13 May 2024 23:44:26 +0200 Subject: [PATCH 58/59] =?UTF-8?q?Orgorozcestn=C3=ADk=20pou=C5=BE=C3=ADv?= =?UTF-8?q?=C3=A1=20urls,=20ne=20hardcodovan=C3=A9=20cesty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../personalni/profil/orgorozcestnik.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/personalni/templates/personalni/profil/orgorozcestnik.html b/personalni/templates/personalni/profil/orgorozcestnik.html index 34c4daba..46a26826 100644 --- a/personalni/templates/personalni/profil/orgorozcestnik.html +++ b/personalni/templates/personalni/profil/orgorozcestnik.html @@ -13,18 +13,18 @@
  • soustředění
  • -
  • přidat novinku na web
  • +
  • přidat novinku na web

  • Tvorba čísla