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): diff --git a/deploy_v2/admin_org_prava.json b/deploy_v2/admin_org_prava.json index 3ef169a5..9caa6eb2 100644 --- a/deploy_v2/admin_org_prava.json +++ b/deploy_v2/admin_org_prava.json @@ -271,62 +271,62 @@ }, { "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" }, { "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" }, { @@ -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 +] 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/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/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/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/migrations/0023_personalni_post_migrate.py b/korektury/migrations/0023_personalni_post_migrate.py new file mode 100644 index 00000000..048ece7a --- /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'), + ('personalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] 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/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/personalni/migrations/0003_initial.py b/personalni/migrations/0003_initial.py new file mode 100644 index 00000000..4103295e --- /dev/null +++ b/personalni/migrations/0003_initial.py @@ -0,0 +1,146 @@ +# 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 + +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'): + 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): + + initial = True + + dependencies = [ + ('personalni', '0002_auto_20240312_2118'), + ('seminar', '0118_alter_organizator_options_alter_osoba_options_and_more'), + ] + + operations = [ + migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes), + 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')), + ('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', + 'verbose_name_plural': 'Organizátoři', + 'db_table': 'seminar_organizator', + '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')), + ('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', + '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')), + ('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', + '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')), + ('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', + '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')), + ('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', + 'verbose_name_plural': 'Školy', + 'db_table': 'seminar_skoly', + 'ordering': ['mesto', 'nazev'], + 'managed': False, + }, + ), + ] 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..6065e58f --- /dev/null +++ b/personalni/migrations/0004_alter_organizator_options_alter_osoba_options_and_more.py @@ -0,0 +1,34 @@ +# 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'), + ('seminar', '0120_remove_osoba_user_remove_prijemce_osoba_and_more'), + ] + + 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/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/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/seminar/models/personalni.py b/personalni/models.py similarity index 98% rename from seminar/models/personalni.py rename to personalni/models.py index 61313e87..dfcc7372 100644 --- a/seminar/models/personalni.py +++ b/personalni/models.py @@ -12,7 +12,7 @@ from django_countries.fields import CountryField from reversion import revisions as reversion -from .base import SeminarModelBase +from seminar.models.base import SeminarModelBase logger = logging.getLogger(__name__) @@ -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.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 .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 .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()) @@ -395,6 +395,17 @@ class Resitel(SeminarModelBase): @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 + db_table = 'seminar_organizator' + ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] + osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org', help_text='osobní údaje organizátora', null=False, blank=False, on_delete=models.PROTECT) @@ -436,12 +447,3 @@ class Organizator(SeminarModelBase): 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'] 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/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/migrations/0015_personalni_post_migrate.py b/prednasky/migrations/0015_personalni_post_migrate.py new file mode 100644 index 00000000..04553e8f --- /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'), + ('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/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 dcf44cbc..54764381 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 soustredeni.models import Soustredeni +from personalni.models import Organizator STAV_NAVRH = 1 STAV_BUDE = 2 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/migrations/0116_delete_nastaveni.py b/seminar/migrations/0116_delete_nastaveni.py new file mode 100644 index 00000000..21d90b63 --- /dev/null +++ b/seminar/migrations/0116_delete_nastaveni.py @@ -0,0 +1,17 @@ +# 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'), + ('various', '0001_initial'), + ] + + operations = [ + migrations.DeleteModel( + name='Nastaveni', + ), + ] 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/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/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/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..1bbfcff0 --- /dev/null +++ b/seminar/migrations/0120_remove_osoba_user_remove_prijemce_osoba_and_more.py @@ -0,0 +1,52 @@ +# 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'), + ('personalni', '0003_initial'), + ('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'), + ('prednasky', '0014_alter_prednaska_org'), + ('sifrovacka', '0005_alter_odpoveducastnika_resitel'), + ] + + 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/migrations/0121_personalni_post_migrate.py b/seminar/migrations/0121_personalni_post_migrate.py new file mode 100644 index 00000000..51840894 --- /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'), + ('personalni', '0005_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/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 34712ee4..121aeb04 100644 --- a/seminar/models/__init__.py +++ b/seminar/models/__init__.py @@ -1,8 +1,13 @@ 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 +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/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/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 1c1a3285..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 @@ -722,34 +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' - -# 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 diff --git a/sifrovacka/migrations/0004_auto_20240312_2124.py b/sifrovacka/migrations/0004_auto_20240312_2124.py new file mode 100644 index 00000000..252268a6 --- /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', '0004_napoveda_napovezenoucastnikovi'), + ] + + operations = [ + ] diff --git a/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py new file mode 100644 index 00000000..d21d65d6 --- /dev/null +++ b/sifrovacka/migrations/0005_alter_odpoveducastnika_resitel.py @@ -0,0 +1,25 @@ +# 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'), + ), + migrations.AlterField( + model_name='napovezenoucastnikovi', + name='resitel', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='personalni.resitel'), + ), + ] diff --git a/sifrovacka/migrations/0006_personalni_post_migrate.py b/sifrovacka/migrations/0006_personalni_post_migrate.py new file mode 100644 index 00000000..cf2c8ad5 --- /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'), + ('personalni', '0005_personalni_post_migrate'), + ] + + operations = [ + ] diff --git a/sifrovacka/models.py b/sifrovacka/models.py index beabd0a7..49565252 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. diff --git a/sifrovacka/views.py b/sifrovacka/views.py index 59f3deec..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.personalni import Resitel +from personalni.models import Resitel # Create your views here. 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 new file mode 100644 index 00000000..c5e432d3 --- /dev/null +++ b/soustredeni/migrations/0001_split_from_seminar.py @@ -0,0 +1,122 @@ +# 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.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', + '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)), + ('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í', + '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/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/seminar/models/soustredeni.py b/soustredeni/models.py similarity index 91% rename from seminar/models/soustredeni.py rename to soustredeni/models.py index 03ff5909..78582565 100644 --- a/seminar/models/soustredeni.py +++ b/soustredeni/models.py @@ -8,9 +8,9 @@ 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.base import SeminarModelBase from seminar.models import tvorba as am logger = logging.getLogger(__name__) @@ -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/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 new file mode 100644 index 00000000..a48a17f8 --- /dev/null +++ b/split-apps-meta/create.notes @@ -0,0 +1,9 @@ +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 (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 diff --git a/split-apps-meta/delete.notes b/split-apps-meta/delete.notes new file mode 100644 index 00000000..dad0e6d4 --- /dev/null +++ b/split-apps-meta/delete.notes @@ -0,0 +1,9 @@ +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 + +(Pozor: pokud něco (JSON serializace, data/… atp.) má starý identifikátor modelu, tak se to teď rozbije.) 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/manage.notes b/split-apps-meta/manage.notes new file mode 100644 index 00000000..c6d4b189 --- /dev/null +++ b/split-apps-meta/manage.notes @@ -0,0 +1,4 @@ +1. smazat `managed = False` +2. makemigrations + Vazba na delete! +3. migrate 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. 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. diff --git a/split-apps-meta/relink.notes b/split-apps-meta/relink.notes new file mode 100644 index 00000000..5465c47d --- /dev/null +++ b/split-apps-meta/relink.notes @@ -0,0 +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 diff --git a/split-apps-meta/unmanage.notes b/split-apps-meta/unmanage.notes new file mode 100644 index 00000000..bce419bf --- /dev/null +++ b/split-apps-meta/unmanage.notes @@ -0,0 +1,24 @@ +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 :-) + 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á. + !! 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? diff --git a/various/migrations/0001_initial.py b/various/migrations/0001_initial.py new file mode 100644 index 00000000..43b77171 --- /dev/null +++ b/various/migrations/0001_initial.py @@ -0,0 +1,40 @@ +# Generated by Django 3.2.23 on 2023-12-11 19:19 + +from django.db import migrations, models + +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í')), + ('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', + 'db_table': 'seminar_nastaveni', + 'managed': False, + }, + ), + migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes), + ] 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/migrations/0003_fix_permissions.py b/various/migrations/0003_fix_permissions.py new file mode 100644 index 00000000..9c3396f6 --- /dev/null +++ b/various/migrations/0003_fix_permissions.py @@ -0,0 +1,40 @@ +# 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 = [ + ] diff --git a/various/models.py b/various/models.py index 71a83623..17632c46 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' + +# 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=True, blank=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 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')