Odstřel modelu TreeNode #67

Merged
zelvuska merged 5 commits from odstrel_modelu_treenode into master 2 months ago
  1. 1
      make/schema
  2. 13
      odevzdavatko/migrations/0007_odstrel_treenode_pre.py
  3. 20
      odevzdavatko/migrations/0008_odstrel_treenode_relink.py
  4. 14
      odevzdavatko/migrations/0009_odstrel_treenode_post.py
  5. 2
      odevzdavatko/models.py
  6. 13
      personalni/migrations/0016_odstrel_treenode_pre.py
  7. 14
      personalni/migrations/0017_odstrel_treenode_post.py
  8. 17
      seminar/migrations/0140_odstrel_treenode_pre.py
  9. 69
      seminar/migrations/0141_odstrel_treenode_unmanage.py
  10. 153
      seminar/migrations/0142_odstrel_treenode_delete.py
  11. 14
      seminar/migrations/0143_odstrel_treenode_post.py
  12. 43
      seminar/migrations/0144_post_odstrel_vseho.py
  13. 4
      seminar/models/__init__.py
  14. 20
      seminar/models/odevzdavatko.py
  15. 69
      seminar/models/pomocne.py
  16. 231
      treenode/migrations/0001_odstrel_treenode_create.py
  17. 70
      treenode/migrations/0002_odstrel_treenode_manage.py
  18. 13
      treenode/migrations/0003_odstrel_treenode_post.py
  19. 91
      treenode/models.py
  20. 13
      tvorba/migrations/0004_odstrel_treenode_pre.py
  21. 14
      tvorba/migrations/0005_odstrel_treenode_post.py
  22. 6
      tvorba/models.py

1
make/schema

@ -5,5 +5,4 @@ set -exuo pipefail
ensure_web_installed
./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf
./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf

13
odevzdavatko/migrations/0007_odstrel_treenode_pre.py

@ -0,0 +1,13 @@
# Generated by Django 4.2.16 on 2024-11-02 19:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('odevzdavatko', '0006_tvorba_post'),
]
operations = [
]

20
odevzdavatko/migrations/0008_odstrel_treenode_relink.py

@ -0,0 +1,20 @@
# Generated by Django 4.2.16 on 2024-11-02 20:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('treenode', '0001_odstrel_treenode_create'),
('odevzdavatko', '0007_odstrel_treenode_pre'),
]
operations = [
migrations.AlterField(
model_name='reseni',
name='text_cely',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='reseni_cely_set', to='treenode.reseninode', verbose_name='Plná verze textu řešení'),
),
]

14
odevzdavatko/migrations/0009_odstrel_treenode_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-11-02 20:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('odevzdavatko', '0008_odstrel_treenode_relink'),
('treenode', '0003_odstrel_treenode_post'),
]
operations = [
]

2
odevzdavatko/models.py

@ -49,7 +49,7 @@ class Reseni(bm.SeminarModelBase):
forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False,
default=FORMA_EMAIL)
text_cely = models.OneToOneField('seminar.ReseniNode', verbose_name='Plná verze textu řešení',
text_cely = models.OneToOneField('treenode.ReseniNode', verbose_name='Plná verze textu řešení',
blank=True, null=True, related_name="reseni_cely_set",
on_delete=models.PROTECT)

13
personalni/migrations/0016_odstrel_treenode_pre.py

@ -0,0 +1,13 @@
# Generated by Django 4.2.16 on 2024-11-02 19:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('personalni', '0015_tvorba_post'),
]
operations = [
]

14
personalni/migrations/0017_odstrel_treenode_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-11-02 20:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('personalni', '0016_odstrel_treenode_pre'),
('treenode', '0003_odstrel_treenode_post'),
]
operations = [
]

17
seminar/migrations/0140_odstrel_treenode_pre.py

@ -0,0 +1,17 @@
# Generated by Django 4.2.16 on 2024-11-02 19:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0139_tvorba_post'),
('odevzdavatko', '0007_odstrel_treenode_pre'),
('personalni', '0016_odstrel_treenode_pre'),
('tvorba', '0004_odstrel_treenode_pre'),
('contenttypes', '0002_remove_content_type_name'),
]
operations = [
]

69
seminar/migrations/0141_odstrel_treenode_unmanage.py

@ -0,0 +1,69 @@
# Generated by Django 4.2.16 on 2024-11-02 19:56
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0140_odstrel_treenode_pre'),
]
operations = [
migrations.AlterModelOptions(
name='castnode',
options={'managed': False, 'verbose_name': 'Část (Node)', 'verbose_name_plural': 'Části (Node)'},
),
migrations.AlterModelOptions(
name='cislonode',
options={'managed': False, 'verbose_name': 'Číslo (Node)', 'verbose_name_plural': 'Čísla (Node)'},
),
migrations.AlterModelOptions(
name='mezicislonode',
options={'managed': False, 'verbose_name': 'Mezičíslo (Node)', 'verbose_name_plural': 'Mezičísla (Node)'},
),
migrations.AlterModelOptions(
name='obrazek',
options={'managed': False, 'verbose_name': 'obrázek', 'verbose_name_plural': 'obrázky'},
),
migrations.AlterModelOptions(
name='orgtextnode',
options={'managed': False, 'verbose_name': 'Organizátorský článek (Node)', 'verbose_name_plural': 'Organizátorské články (Node)'},
),
migrations.AlterModelOptions(
name='pohadkanode',
options={'managed': False, 'verbose_name': 'Pohádka (Node)', 'verbose_name_plural': 'Pohádky (Node)'},
),
migrations.AlterModelOptions(
name='reseninode',
options={'managed': False, 'verbose_name': 'Otištěné řešení (Node)', 'verbose_name_plural': 'Otištěná řešení (Node)'},
),
migrations.AlterModelOptions(
name='rocniknode',
options={'managed': False, 'verbose_name': 'Ročník (Node)', 'verbose_name_plural': 'Ročníky (Node)'},
),
migrations.AlterModelOptions(
name='temavcislenode',
options={'managed': False, 'verbose_name': 'Téma v čísle (Node)', 'verbose_name_plural': 'Témata v čísle (Node)'},
),
migrations.AlterModelOptions(
name='text',
options={'managed': False, 'verbose_name': 'text', 'verbose_name_plural': 'texty'},
),
migrations.AlterModelOptions(
name='textnode',
options={'managed': False, 'verbose_name': 'Text (Node)', 'verbose_name_plural': 'Text (Node)'},
),
migrations.AlterModelOptions(
name='treenode',
options={'managed': False, 'verbose_name': 'TreeNode', 'verbose_name_plural': 'TreeNody'},
),
migrations.AlterModelOptions(
name='ulohavzoraknode',
options={'managed': False, 'verbose_name': 'Vzorák úlohy (Node)', 'verbose_name_plural': 'Vzoráky úloh (Node)'},
),
migrations.AlterModelOptions(
name='ulohazadaninode',
options={'managed': False, 'verbose_name': 'Zadání úlohy (Node)', 'verbose_name_plural': 'Zadání úloh (Node)'},
),
]

153
seminar/migrations/0142_odstrel_treenode_delete.py

@ -0,0 +1,153 @@
# Generated by Django 4.2.16 on 2024-11-02 20:47
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0141_odstrel_treenode_unmanage'),
('odevzdavatko', '0008_odstrel_treenode_relink'),
('treenode', '0001_odstrel_treenode_create'),
]
operations = [
migrations.RemoveField(
model_name='cislonode',
name='cislo',
),
migrations.RemoveField(
model_name='cislonode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='mezicislonode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='obrazek',
name='text',
),
migrations.RemoveField(
model_name='orgtextnode',
name='organizator',
),
migrations.RemoveField(
model_name='orgtextnode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='pohadkanode',
name='pohadka',
),
migrations.RemoveField(
model_name='pohadkanode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='reseninode',
name='reseni',
),
migrations.RemoveField(
model_name='reseninode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='rocniknode',
name='rocnik',
),
migrations.RemoveField(
model_name='rocniknode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='temavcislenode',
name='tema',
),
migrations.RemoveField(
model_name='temavcislenode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='textnode',
name='text',
),
migrations.RemoveField(
model_name='textnode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='treenode',
name='first_child',
),
migrations.RemoveField(
model_name='treenode',
name='polymorphic_ctype',
),
migrations.RemoveField(
model_name='treenode',
name='root',
),
migrations.RemoveField(
model_name='treenode',
name='succ',
),
migrations.RemoveField(
model_name='ulohavzoraknode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='ulohavzoraknode',
name='uloha',
),
migrations.RemoveField(
model_name='ulohazadaninode',
name='treenode_ptr',
),
migrations.RemoveField(
model_name='ulohazadaninode',
name='uloha',
),
migrations.DeleteModel(
name='CastNode',
),
migrations.DeleteModel(
name='CisloNode',
),
migrations.DeleteModel(
name='MezicisloNode',
),
migrations.DeleteModel(
name='Obrazek',
),
migrations.DeleteModel(
name='OrgTextNode',
),
migrations.DeleteModel(
name='PohadkaNode',
),
migrations.DeleteModel(
name='ReseniNode',
),
migrations.DeleteModel(
name='RocnikNode',
),
migrations.DeleteModel(
name='TemaVCisleNode',
),
migrations.DeleteModel(
name='Text',
),
migrations.DeleteModel(
name='TextNode',
),
migrations.DeleteModel(
name='TreeNode',
),
migrations.DeleteModel(
name='UlohaVzorakNode',
),
migrations.DeleteModel(
name='UlohaZadaniNode',
),
]

14
seminar/migrations/0143_odstrel_treenode_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-11-02 20:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0142_odstrel_treenode_delete'),
('treenode', '0003_odstrel_treenode_post'),
]
operations = [
]

43
seminar/migrations/0144_post_odstrel_vseho.py

@ -0,0 +1,43 @@
# Generated by Django 4.2.16 on 2024-11-03 01:55
from django.db import migrations
# Myšlenka: Tahle migrace o sobě prohlašuje, že závisí na všem, co se do téhle chvíle stalo. To má dva důsledky:
# 1. V okamžiku, kdy tahle migrace proběhne, tak už máme model ve stavu který očekáváme. IOW slouží jako bariéra, za kterou nemůžou přetéct úpravy ostatních aplikací (hlavně těch našich)
# 2. Zároveň ale tvrdíme, že k tomu, aby tahle migrace proběhla, potřebujeme (potenciálně relativně staré) verze cizích aplikací, což způsobí uspořádání opačným směrem: DB změny cizích aplikací naopak proběhnou až po této migraci
# Vzhledem k tomu, že by i naše předchozí aplikace měly záviset na těchto změnách, tak tím efektivně vynucujeme zachování stavu pro ty mezilehlé migrace, které možná (chybou) nedokumentovaně spoléhají na to, jak vypadají cizí aplikace.
# Plán do budoucna: Jakmile tahle migrace proběhne na všech myslitelných databázích, můžeme její předchůdce prostě smazat a nahradit nějakou výrazně snazší sadou migrací, která jen vygeneruje správně tabulky a závislosti podle aktuálního modelu.
# - To se ve skutečnosti vesměs už stalo, v odstřelených aplikacích jsou modely stejně všechny „nové s daty spadlými z nebe“. Je moc pozdě v noci, ale myslím si, že prostě bude stačit smazat závislosti na migracích v `seminar`i a celou aplikaci `seminar` zrušit. (Největší problém je to při nasazování DB z nuly např. u generování testdat…)
# Je otázka, jestli tahle migrace nemá bydlet ve `various` či jinde, aby se dala smazat celá složka `seminar`.
class Migration(migrations.Migration):
dependencies = [
('admin', '0003_logentry_add_action_flag_choices'),
('auth', '0012_alter_user_first_name_max_length'),
('authtoken', '0004_alter_tokenproxy_options'),
('contenttypes', '0002_remove_content_type_name'),
('flatpages', '0001_initial'),
('galerie', '0013_post_split_soustredeni'),
('header_fotky', '0001_initial'),
('korektury', '0024_vic_orgu_k_pdf'),
('novinky', '0004_alter_novinky_id'),
('odevzdavatko', '0009_odstrel_treenode_post'),
('personalni', '0017_odstrel_treenode_post'),
('prednasky', '0018_post_split_soustredeni'),
('reversion', '0002_add_index_on_version_for_content_type_and_db'),
('seminar', '0143_odstrel_treenode_post'),
('sessions', '0001_initial'),
('sifrovacka', '0006_personalni_post_migrate'),
('sites', '0002_alter_domain_unique'),
('sitetree', '0002_alter_treeitem_parent_alter_treeitem_tree'),
('soustredeni', '0010_tvorba_post'),
('taggit', '0006_rename_taggeditem_content_type_object_id_taggit_tagg_content_8fc721_idx'),
('treenode', '0003_odstrel_treenode_post'),
('tvorba', '0005_odstrel_treenode_post'),
('various', '0006_tvorba_post'),
('vyroci', '0001_initial'),
]
operations = [
]

4
seminar/models/__init__.py

@ -1,8 +1,5 @@
from .tvorba import *
from .odevzdavatko import *
from .base import *
from .pomocne import *
from .treenode import *
from various.models import Nastaveni
from personalni.models import Organizator, Resitel, Skola, Prijemce, Osoba
@ -10,6 +7,7 @@ from soustredeni.models import Soustredeni, Soustredeni_Ucastnici, Soustredeni_O
from novinky.models import Novinky
from odevzdavatko.models import Reseni, PrilohaReseni, Reseni_Resitele, Hodnoceni
from tvorba.models import ZmrazenaVysledkovka, Deadline, Cislo, Rocnik, Pohadka, Tema, Problem, Problemy_Opravovatele, Uloha, Clanek
from treenode.models import UlohaVzorakNode, UlohaZadaniNode, CisloNode, TemaVCisleNode, OrgTextNode, Obrazek, RocnikNode, PohadkaNode, TextNode, MezicisloNode, ReseniNode, CastNode, Text, TreeNode
# Kvůli migr. 0041
from soustredeni.models import generate_filename_konfera

20
seminar/models/odevzdavatko.py

@ -1,20 +0,0 @@
from django.db import models
from seminar.models import treenode as tm
from odevzdavatko.models import Reseni
class ReseniNode(tm.TreeNode):
class Meta:
db_table = 'seminar_nodes_otistene_reseni'
verbose_name = 'Otištěné řešení (Node)'
verbose_name_plural = 'Otištěná řešení (Node)'
reseni = models.ForeignKey(Reseni,
on_delete=models.PROTECT,
verbose_name = 'reseni')
def aktualizuj_nazev(self):
self.nazev = "ReseniNode: "+str(self.reseni)
def getOdkazStr(self):
return str(self.reseni)

69
seminar/models/pomocne.py

@ -1,69 +0,0 @@
import logging
import os
from django.db import models
from .base import SeminarModelBase
logger = logging.getLogger(__name__)
class Text(SeminarModelBase):
class Meta:
db_table = 'seminar_texty'
verbose_name = 'text'
verbose_name_plural = 'texty'
na_web = models.TextField(
'text na web', blank=True,
help_text='Text ke zveřejnění na webu')
do_cisla = models.TextField(
'text do čísla', blank=True,
help_text='Text ke zveřejnění v čísle')
# má OneToOneField s:
# Reseni (je u něj jako reseni_cele)
# obrázky mají návaznost opačným směrem (vazba z druhé strany)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# *Node.save() aktualizuje název *Nodu.
for tn in self.textnode_set.all():
tn.save()
def __str__(self):
return str(self.na_web)[:20]
class Obrazek(SeminarModelBase):
class Meta:
db_table = 'seminar_obrazky'
verbose_name = 'obrázek'
verbose_name_plural = 'obrázky'
# Interní ID
id = models.AutoField(primary_key=True)
na_web = models.ImageField(
'obrázek na web', upload_to='obrazky/%Y/%m/%d/',
null=True, blank=True)
text = models.ForeignKey(
Text, verbose_name='text',
help_text='text, ve kterém se obrázek vyskytuje',
null=False, blank=False, on_delete=models.CASCADE)
do_cisla_barevny = models.FileField(
'barevný obrázek do čísla',
help_text='Barevná verze obrázku do čísla',
upload_to='obrazky/%Y/%m/%d/', blank=True, null=True)
do_cisla_cernobily = models.FileField(
'černobílý obrázek do čísla',
help_text='Černobílá verze obrázku do čísla',
upload_to='obrazky/%Y/%m/%d/', blank=True, null=True)
# TODO placement hint - chci ho tady / pred textem / za textem

231
treenode/migrations/0001_odstrel_treenode_create.py

@ -0,0 +1,231 @@
# Generated by Django 4.2.16 on 2024-11-02 20:06
from django.db import migrations, models
import django.db.models.deletion
def nastav_nove_contenttypes(apps, schema_editor):
ContentType = apps.get_model('contenttypes', 'ContentType')
# Seznam níž ověřen tím, že se skutečně při téhle migraci tabulka `django_content_type` (lokální v SQLite) změní správně :-)
for m in ('ulohavzoraknode', 'ulohazadaninode', 'cislonode', 'temavcislenode', 'orgtextnode', 'obrazek', 'rocniknode', 'pohadkanode', 'textnode', 'mezicislonode', 'reseninode', 'castnode', 'text', 'treenode'):
ContentType.objects.filter(app_label='seminar', model=m).update(app_label='treenode')
def nastav_stare_contenttypes(apps, schema_editor):
ContentType = apps.get_model('contenttypes', 'ContentType')
for m in ('ulohavzoraknode', 'ulohazadaninode', 'cislonode', 'temavcislenode', 'orgtextnode', 'obrazek', 'rocniknode', 'pohadkanode', 'textnode', 'mezicislonode', 'reseninode', 'castnode', 'text', 'treenode'):
ContentType.objects.filter(app_label='treenode', model=m).update(app_label='seminar')
class Migration(migrations.Migration):
initial = True
dependencies = [
('seminar', '0141_odstrel_treenode_unmanage'),
]
operations = [
migrations.CreateModel(
name='Obrazek',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('na_web', models.ImageField(blank=True, null=True, upload_to='obrazky/%Y/%m/%d/', verbose_name='obrázek na web')),
('do_cisla_barevny', models.FileField(blank=True, help_text='Barevná verze obrázku do čísla', null=True, upload_to='obrazky/%Y/%m/%d/', verbose_name='barevný obrázek do čísla')),
('do_cisla_cernobily', models.FileField(blank=True, help_text='Černobílá verze obrázku do čísla', null=True, upload_to='obrazky/%Y/%m/%d/', verbose_name='černobílý obrázek do čísla')),
('text', models.ForeignKey(help_text='text, ve kterém se obrázek vyskytuje', on_delete=django.db.models.deletion.CASCADE, to='treenode.text', verbose_name='text')),
],
options={
'verbose_name': 'obrázek',
'verbose_name_plural': 'obrázky',
'db_table': 'seminar_obrazky',
'managed': False,
},
),
migrations.CreateModel(
name='Text',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('na_web', models.TextField(blank=True, help_text='Text ke zveřejnění na webu', verbose_name='text na web')),
('do_cisla', models.TextField(blank=True, help_text='Text ke zveřejnění v čísle', verbose_name='text do čísla')),
],
options={
'verbose_name': 'text',
'verbose_name_plural': 'texty',
'db_table': 'seminar_texty',
'managed': False,
},
),
migrations.CreateModel(
name='TreeNode',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nazev', models.TextField(help_text='Tento název se zobrazuje v nabídkách pro výběr vhodného TreeNode', null=True, verbose_name='název tohoto node')),
('zajimave', models.BooleanField(default=False, help_text='Zobrazí se daná věc na rozcestníku témátek', verbose_name='Zajímavé')),
('srolovatelne', models.BooleanField(blank=True, help_text='Bude na stránce témátka možnost tuto položku skrýt', null=True, verbose_name='Srolovatelné')),
('first_child', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='father_of_first', to='treenode.treenode', verbose_name='první potomek')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
('root', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='potomci_set', to='treenode.treenode', verbose_name='kořen stromu')),
('succ', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='prev', to='treenode.treenode', verbose_name='další element na stejné úrovni')),
],
options={
'verbose_name': 'TreeNode',
'verbose_name_plural': 'TreeNody',
'db_table': 'seminar_nodes_treenode',
'managed': False,
},
),
migrations.CreateModel(
name='CastNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('nadpis', models.CharField(help_text='Nadpis podvěšené části obsahu', max_length=100, verbose_name='Nadpis')),
],
options={
'verbose_name': 'Část (Node)',
'verbose_name_plural': 'Části (Node)',
'db_table': 'seminar_nodes_cast',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='CisloNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('cislo', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='tvorba.cislo', verbose_name='číslo')),
],
options={
'verbose_name': 'Číslo (Node)',
'verbose_name_plural': 'Čísla (Node)',
'db_table': 'seminar_nodes_cislo',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='MezicisloNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
],
options={
'verbose_name': 'Mezičíslo (Node)',
'verbose_name_plural': 'Mezičísla (Node)',
'db_table': 'seminar_nodes_mezicislo',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='OrgTextNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('org_verejny', models.BooleanField(default=True, help_text='Pokud ano, bude org pod článkem podepsaný', verbose_name='Org je veřejný?')),
('organizator', models.ForeignKey( on_delete=django.db.models.deletion.DO_NOTHING, to='personalni.organizator', verbose_name='Organizátor')),
],
options={
'verbose_name': 'Organizátorský článek (Node)',
'verbose_name_plural': 'Organizátorské články (Node)',
'db_table': 'seminar_nodes_orgtextnode',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='PohadkaNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('pohadka', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='tvorba.pohadka', verbose_name='pohádka')),
],
options={
'verbose_name': 'Pohádka (Node)',
'verbose_name_plural': 'Pohádky (Node)',
'db_table': 'seminar_nodes_pohadka',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='ReseniNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('reseni', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='odevzdavatko.reseni', verbose_name='reseni')),
],
options={
'verbose_name': 'Otištěné řešení (Node)',
'verbose_name_plural': 'Otištěná řešení (Node)',
'db_table': 'seminar_nodes_otistene_reseni',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='RocnikNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('rocnik', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='tvorba.rocnik', verbose_name='ročník')),
],
options={
'verbose_name': 'Ročník (Node)',
'verbose_name_plural': 'Ročníky (Node)',
'db_table': 'seminar_nodes_rocnik',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='TemaVCisleNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('tema', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='tvorba.tema', verbose_name='téma v čísle')),
],
options={
'verbose_name': 'Téma v čísle (Node)',
'verbose_name_plural': 'Témata v čísle (Node)',
'db_table': 'seminar_nodes_temavcisle',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='TextNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('text', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='treenode.text', verbose_name='text')),
],
options={
'verbose_name': 'Text (Node)',
'verbose_name_plural': 'Text (Node)',
'db_table': 'seminar_nodes_obsah',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='UlohaVzorakNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('uloha', models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, to='tvorba.uloha', verbose_name='úloha')),
],
options={
'verbose_name': 'Vzorák úlohy (Node)',
'verbose_name_plural': 'Vzoráky úloh (Node)',
'db_table': 'seminar_nodes_uloha_vzorak',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.CreateModel(
name='UlohaZadaniNode',
fields=[
('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='treenode.treenode')),
('uloha', models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, to='tvorba.uloha', verbose_name='úloha')),
],
options={
'verbose_name': 'Zadání úlohy (Node)',
'verbose_name_plural': 'Zadání úloh (Node)',
'db_table': 'seminar_nodes_uloha_zadani',
'managed': False,
},
bases=('treenode.treenode',),
),
migrations.RunPython(nastav_nove_contenttypes, nastav_stare_contenttypes),
]

70
treenode/migrations/0002_odstrel_treenode_manage.py

@ -0,0 +1,70 @@
# Generated by Django 4.2.16 on 2024-11-02 20:50
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('treenode', '0001_odstrel_treenode_create'),
('seminar', '0142_odstrel_treenode_delete'),
]
operations = [
migrations.AlterModelOptions(
name='castnode',
options={'verbose_name': 'Část (Node)', 'verbose_name_plural': 'Části (Node)'},
),
migrations.AlterModelOptions(
name='cislonode',
options={'verbose_name': 'Číslo (Node)', 'verbose_name_plural': 'Čísla (Node)'},
),
migrations.AlterModelOptions(
name='mezicislonode',
options={'verbose_name': 'Mezičíslo (Node)', 'verbose_name_plural': 'Mezičísla (Node)'},
),
migrations.AlterModelOptions(
name='obrazek',
options={'verbose_name': 'obrázek', 'verbose_name_plural': 'obrázky'},
),
migrations.AlterModelOptions(
name='orgtextnode',
options={'verbose_name': 'Organizátorský článek (Node)', 'verbose_name_plural': 'Organizátorské články (Node)'},
),
migrations.AlterModelOptions(
name='pohadkanode',
options={'verbose_name': 'Pohádka (Node)', 'verbose_name_plural': 'Pohádky (Node)'},
),
migrations.AlterModelOptions(
name='reseninode',
options={'verbose_name': 'Otištěné řešení (Node)', 'verbose_name_plural': 'Otištěná řešení (Node)'},
),
migrations.AlterModelOptions(
name='rocniknode',
options={'verbose_name': 'Ročník (Node)', 'verbose_name_plural': 'Ročníky (Node)'},
),
migrations.AlterModelOptions(
name='temavcislenode',
options={'verbose_name': 'Téma v čísle (Node)', 'verbose_name_plural': 'Témata v čísle (Node)'},
),
migrations.AlterModelOptions(
name='text',
options={'verbose_name': 'text', 'verbose_name_plural': 'texty'},
),
migrations.AlterModelOptions(
name='textnode',
options={'verbose_name': 'Text (Node)', 'verbose_name_plural': 'Text (Node)'},
),
migrations.AlterModelOptions(
name='treenode',
options={'verbose_name': 'TreeNode', 'verbose_name_plural': 'TreeNody'},
),
migrations.AlterModelOptions(
name='ulohavzoraknode',
options={'verbose_name': 'Vzorák úlohy (Node)', 'verbose_name_plural': 'Vzoráky úloh (Node)'},
),
migrations.AlterModelOptions(
name='ulohazadaninode',
options={'verbose_name': 'Zadání úlohy (Node)', 'verbose_name_plural': 'Zadání úloh (Node)'},
),
]

13
treenode/migrations/0003_odstrel_treenode_post.py

@ -0,0 +1,13 @@
# Generated by Django 4.2.16 on 2024-11-02 20:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('treenode', '0002_odstrel_treenode_manage'),
]
operations = [
]

91
seminar/models/treenode.py → treenode/models.py

@ -8,9 +8,10 @@ from unidecode import unidecode # Používám pro získání ID odkazu (ještě
from polymorphic.models import PolymorphicModel
from personalni.models import Organizator
from seminar.models import SeminarModelBase
from .pomocne import Text
from personalni.models import Organizator
from odevzdavatko.models import Reseni
logger = logging.getLogger(__name__)
@ -233,6 +234,58 @@ class UlohaVzorakNode(TreeNode):
def getOdkazStr(self):
return str(self.uloha)
class ReseniNode(TreeNode):
class Meta:
db_table = 'seminar_nodes_otistene_reseni'
verbose_name = 'Otištěné řešení (Node)'
verbose_name_plural = 'Otištěná řešení (Node)'
reseni = models.ForeignKey(Reseni,
on_delete=models.PROTECT,
verbose_name = 'reseni')
def aktualizuj_nazev(self):
self.nazev = "ReseniNode: "+str(self.reseni)
def getOdkazStr(self):
return str(self.reseni)
# LEdoian: Můžu prostě odstřelit Text a Obrázek do aplikace `treenode`, kam podle mě
# stejně patří? (Myšlenka, proč by tam měly patřit: tak, jak teď jsou je stejně
# využívají jen TreeNody a žádné rozhraní k nim stejně není, takže aktuálně
# použít nejdou (jako zbytek TN) a jejich sémantika pro „společnou tvorbu čísla
# na web a PDF“ je ze stejné školy. A taky kvůli nemíchání – pokud vbrzku bude
# potřeba nějaký podobný model, navrhuji ho udělat znovu a klidně úplně stejně,
# staré věci pak buď zůstanou skryté, nebo je datově namigrujeme – taková
# migrace bude snadná.) – Jidáš: jo, a napiš tam tyhle myšlenky do komentáře.
# (zhruba přepis diskuse ve web-dev, 2024-10-30.)
class Text(SeminarModelBase):
class Meta:
db_table = 'seminar_texty'
verbose_name = 'text'
verbose_name_plural = 'texty'
na_web = models.TextField(
'text na web', blank=True,
help_text='Text ke zveřejnění na webu')
do_cisla = models.TextField(
'text do čísla', blank=True,
help_text='Text ke zveřejnění v čísle')
# má OneToOneField s:
# Reseni (je u něj jako reseni_cele)
# obrázky mají návaznost opačným směrem (vazba z druhé strany)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# *Node.save() aktualizuje název *Nodu.
for tn in self.textnode_set.all():
tn.save()
def __str__(self):
return str(self.na_web)[:20]
class TextNode(TreeNode):
class Meta:
@ -249,7 +302,6 @@ class TextNode(TreeNode):
def getOdkazStr(self):
return str(self.text)
class CastNode(TreeNode):
class Meta:
db_table = 'seminar_nodes_cast'
@ -263,3 +315,36 @@ class CastNode(TreeNode):
def getOdkazStr(self):
return str(self.nadpis)
class Obrazek(SeminarModelBase):
class Meta:
db_table = 'seminar_obrazky'
verbose_name = 'obrázek'
verbose_name_plural = 'obrázky'
# Interní ID
id = models.AutoField(primary_key=True)
na_web = models.ImageField(
'obrázek na web', upload_to='obrazky/%Y/%m/%d/',
null=True, blank=True)
text = models.ForeignKey(
Text, verbose_name='text',
help_text='text, ve kterém se obrázek vyskytuje',
null=False, blank=False, on_delete=models.CASCADE)
do_cisla_barevny = models.FileField(
'barevný obrázek do čísla',
help_text='Barevná verze obrázku do čísla',
upload_to='obrazky/%Y/%m/%d/', blank=True, null=True)
do_cisla_cernobily = models.FileField(
'černobílý obrázek do čísla',
help_text='Černobílá verze obrázku do čísla',
upload_to='obrazky/%Y/%m/%d/', blank=True, null=True)
# TODO placement hint - chci ho tady / pred textem / za textem

13
tvorba/migrations/0004_odstrel_treenode_pre.py

@ -0,0 +1,13 @@
# Generated by Django 4.2.16 on 2024-11-02 19:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tvorba', '0003_tvorba_post'),
]
operations = [
]

14
tvorba/migrations/0005_odstrel_treenode_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-11-02 20:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tvorba', '0004_odstrel_treenode_pre'),
('treenode', '0003_odstrel_treenode_post'),
]
operations = [
]

6
tvorba/models.py

@ -297,7 +297,7 @@ class Cislo(SeminarModelBase):
except ObjectDoesNotExist:
# Neexistující *Node nemá smysl aktualizovat, ale je potřeba ho naopak vyrobit
logger.warning(f'Číslo {self} nemělo ČísloNode, vyrábím…')
from seminar.models.treenode import CisloNode
from treenode.models import CisloNode
CisloNode.objects.create(cislo=self)
def zlomovy_deadline_pro_papirove_cislo(self):
@ -572,7 +572,7 @@ class Tema(Problem):
def cislo_node(self):
tema_node_set = self.temavcislenode_set.all()
tema_cisla_vyskyt = []
from seminar.models.treenode import CisloNode
from treenode.models import CisloNode
for tn in tema_node_set:
tema_cisla_vyskyt.append(
treelib.get_upper_node_of_type(tn, CisloNode).cislo)
@ -648,7 +648,7 @@ class Uloha(Problem):
def cislo_node(self):
zadani_node = self.ulohazadaninode
from seminar.models.treenode import CisloNode
from treenode.models import CisloNode
return treelib.get_upper_node_of_type(zadani_node, CisloNode)

Loading…
Cancel
Save