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/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/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/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/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/models/__init__.py b/seminar/models/__init__.py
index 34712ee4..e3026a2c 100644
--- a/seminar/models/__init__.py
+++ b/seminar/models/__init__.py
@@ -1,8 +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 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/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..8d3174e3
--- /dev/null
+++ b/split-apps-meta/create.notes
@@ -0,0 +1,6 @@
+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 (TODO: jak? Já jsem je ukradl až zpětně…)
+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..846b7314
--- /dev/null
+++ b/split-apps-meta/unmanage.notes
@@ -0,0 +1,21 @@
+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…)
+
+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