Browse Source

odstřel tvorby: relink – post

pull/66/head
Pavel 'LEdoian' Turinsky 3 weeks ago
parent
commit
062f70e947
  1. 62
      deploy_v2/admin_org_prava.json
  2. 14
      odevzdavatko/migrations/0006_tvorba_post.py
  3. 14
      personalni/migrations/0015_tvorba_post.py
  4. 150
      seminar/migrations/0138_tvorba_delete.py
  5. 14
      seminar/migrations/0139_tvorba_post.py
  6. 6
      seminar/models/__init__.py
  7. 2
      seminar/models/treenode.py
  8. 731
      seminar/models/tvorba.py
  9. 13
      soustredeni/migrations/0005_tvorba_relink.py
  10. 17
      soustredeni/migrations/0006_tvorba_relink2.py
  11. 15
      soustredeni/migrations/0007_tvorba_relink3.py
  12. 34
      soustredeni/migrations/0008_tvorba_relink4.py
  13. 17
      soustredeni/migrations/0009_tvorba_relink5.py
  14. 14
      soustredeni/migrations/0010_tvorba_post.py
  15. 54
      tvorba/migrations/0002_tvorba_manage.py
  16. 13
      tvorba/migrations/0003_tvorba_post.py
  17. 13
      tvorba/models.py
  18. 14
      various/migrations/0006_tvorba_post.py

62
deploy_v2/admin_org_prava.json

@ -216,57 +216,57 @@
}, },
{ {
"codename": "add_cislo", "codename": "add_cislo",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "cislo" "ct_model": "cislo"
}, },
{ {
"codename": "change_cislo", "codename": "change_cislo",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "cislo" "ct_model": "cislo"
}, },
{ {
"codename": "delete_cislo", "codename": "delete_cislo",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "cislo" "ct_model": "cislo"
}, },
{ {
"codename": "view_cislo", "codename": "view_cislo",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "cislo" "ct_model": "cislo"
}, },
{ {
"codename": "add_clanek", "codename": "add_clanek",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "clanek" "ct_model": "clanek"
}, },
{ {
"codename": "change_clanek", "codename": "change_clanek",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "clanek" "ct_model": "clanek"
}, },
{ {
"codename": "delete_clanek", "codename": "delete_clanek",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "clanek" "ct_model": "clanek"
}, },
{ {
"codename": "view_clanek", "codename": "view_clanek",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "clanek" "ct_model": "clanek"
}, },
{ {
"codename": "add_deadline", "codename": "add_deadline",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "deadline" "ct_model": "deadline"
}, },
{ {
"codename": "change_deadline", "codename": "change_deadline",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "deadline" "ct_model": "deadline"
}, },
{ {
"codename": "view_deadline", "codename": "view_deadline",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "deadline" "ct_model": "deadline"
}, },
{ {
@ -371,22 +371,22 @@
}, },
{ {
"codename": "add_pohadka", "codename": "add_pohadka",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "pohadka" "ct_model": "pohadka"
}, },
{ {
"codename": "change_pohadka", "codename": "change_pohadka",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "pohadka" "ct_model": "pohadka"
}, },
{ {
"codename": "delete_pohadka", "codename": "delete_pohadka",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "pohadka" "ct_model": "pohadka"
}, },
{ {
"codename": "view_pohadka", "codename": "view_pohadka",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "pohadka" "ct_model": "pohadka"
}, },
{ {
@ -411,22 +411,22 @@
}, },
{ {
"codename": "add_problem", "codename": "add_problem",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "problem" "ct_model": "problem"
}, },
{ {
"codename": "change_problem", "codename": "change_problem",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "problem" "ct_model": "problem"
}, },
{ {
"codename": "delete_problem", "codename": "delete_problem",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "problem" "ct_model": "problem"
}, },
{ {
"codename": "view_problem", "codename": "view_problem",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "problem" "ct_model": "problem"
}, },
{ {
@ -441,22 +441,22 @@
}, },
{ {
"codename": "add_rocnik", "codename": "add_rocnik",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "rocnik" "ct_model": "rocnik"
}, },
{ {
"codename": "change_rocnik", "codename": "change_rocnik",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "rocnik" "ct_model": "rocnik"
}, },
{ {
"codename": "delete_rocnik", "codename": "delete_rocnik",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "rocnik" "ct_model": "rocnik"
}, },
{ {
"codename": "view_rocnik", "codename": "view_rocnik",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "rocnik" "ct_model": "rocnik"
}, },
{ {
@ -541,42 +541,42 @@
}, },
{ {
"codename": "add_tema", "codename": "add_tema",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "tema" "ct_model": "tema"
}, },
{ {
"codename": "change_tema", "codename": "change_tema",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "tema" "ct_model": "tema"
}, },
{ {
"codename": "delete_tema", "codename": "delete_tema",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "tema" "ct_model": "tema"
}, },
{ {
"codename": "view_tema", "codename": "view_tema",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "tema" "ct_model": "tema"
}, },
{ {
"codename": "add_uloha", "codename": "add_uloha",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "uloha" "ct_model": "uloha"
}, },
{ {
"codename": "change_uloha", "codename": "change_uloha",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "uloha" "ct_model": "uloha"
}, },
{ {
"codename": "delete_uloha", "codename": "delete_uloha",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "uloha" "ct_model": "uloha"
}, },
{ {
"codename": "view_uloha", "codename": "view_uloha",
"ct_app_label": "seminar", "ct_app_label": "tvorba",
"ct_model": "uloha" "ct_model": "uloha"
}, },
{ {

14
odevzdavatko/migrations/0006_tvorba_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-10-30 21:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('odevzdavatko', '0005_tvorba_relink'),
('tvorba', '0003_tvorba_post'),
]
operations = [
]

14
personalni/migrations/0015_tvorba_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-10-30 21:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('personalni', '0014_tvorba_pre'),
('tvorba', '0003_tvorba_post'),
]
operations = [
]

150
seminar/migrations/0138_tvorba_delete.py

@ -0,0 +1,150 @@
# Generated by Django 4.2.16 on 2024-10-30 14:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tvorba', '0001_tvorba_create'),
('seminar', '0137_tvorba_unmanage'),
('odevzdavatko', '0005_tvorba_relink'),
('soustredeni', '0009_tvorba_relink5'),
('various', '0005_tvorba_relink'),
]
operations = [
migrations.RemoveField(
model_name='cislo',
name='rocnik',
),
migrations.RemoveField(
model_name='clanek',
name='cislo',
),
migrations.RemoveField(
model_name='clanek',
name='problem_ptr',
),
migrations.RemoveField(
model_name='deadline',
name='cislo',
),
migrations.RemoveField(
model_name='pohadka',
name='autor',
),
migrations.RemoveField(
model_name='problem',
name='autor',
),
migrations.RemoveField(
model_name='problem',
name='garant',
),
migrations.RemoveField(
model_name='problem',
name='nadproblem',
),
migrations.RemoveField(
model_name='problem',
name='opravovatele',
),
migrations.RemoveField(
model_name='problem',
name='polymorphic_ctype',
),
migrations.RemoveField(
model_name='problem',
name='zamereni',
),
migrations.DeleteModel(
name='Problemy_Opravovatele',
),
migrations.RemoveField(
model_name='tema',
name='problem_ptr',
),
migrations.RemoveField(
model_name='tema',
name='rocnik',
),
migrations.RemoveField(
model_name='uloha',
name='cislo_deadline',
),
migrations.RemoveField(
model_name='uloha',
name='cislo_reseni',
),
migrations.RemoveField(
model_name='uloha',
name='cislo_zadani',
),
migrations.RemoveField(
model_name='uloha',
name='problem_ptr',
),
migrations.RemoveField(
model_name='zmrazenavysledkovka',
name='deadline',
),
migrations.AlterField(
model_name='cislonode',
name='cislo',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='tvorba.cislo', verbose_name='číslo'),
),
migrations.AlterField(
model_name='pohadkanode',
name='pohadka',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='tvorba.pohadka', verbose_name='pohádka'),
),
migrations.AlterField(
model_name='rocniknode',
name='rocnik',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='tvorba.rocnik', verbose_name='ročník'),
),
migrations.AlterField(
model_name='temavcislenode',
name='tema',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='tvorba.tema', verbose_name='téma v čísle'),
),
migrations.AlterField(
model_name='ulohavzoraknode',
name='uloha',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, to='tvorba.uloha', verbose_name='úloha'),
),
migrations.AlterField(
model_name='ulohazadaninode',
name='uloha',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, to='tvorba.uloha', verbose_name='úloha'),
),
migrations.DeleteModel(
name='Cislo',
),
migrations.DeleteModel(
name='Clanek',
),
migrations.DeleteModel(
name='Deadline',
),
migrations.DeleteModel(
name='Pohadka',
),
migrations.DeleteModel(
name='Problem',
),
migrations.DeleteModel(
name='Rocnik',
),
migrations.DeleteModel(
name='Tema',
),
migrations.DeleteModel(
name='Uloha',
),
migrations.DeleteModel(
name='ZmrazenaVysledkovka',
),
]

14
seminar/migrations/0139_tvorba_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-10-30 21:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0138_tvorba_delete'),
('tvorba', '0003_tvorba_post'),
]
operations = [
]

6
seminar/models/__init__.py

@ -15,3 +15,9 @@ from tvorba.models import ZmrazenaVysledkovka, Deadline, Cislo, Rocnik, Pohadka,
from soustredeni.models import generate_filename_konfera from soustredeni.models import generate_filename_konfera
# migr. 0001 # migr. 0001
from odevzdavatko.models import generate_filename from odevzdavatko.models import generate_filename
# migr. 0031, 0032, 0081
from tvorba.models import cislo_pdf_filename
# migr. 0082
from tvorba.models import cislo_png_filename
# migr 0100 (hack)
import tvorba.models as tvorba

2
seminar/models/treenode.py

@ -14,7 +14,7 @@ from .pomocne import Text
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from seminar.models import tvorba as am import tvorba.models as am
class TreeNode(PolymorphicModel): class TreeNode(PolymorphicModel):
class Meta: class Meta:

731
seminar/models/tvorba.py

@ -1,40 +1,7 @@
import datetime
import os import os
import subprocess
import pathlib
import tempfile
import logging import logging
from django.contrib.sites.shortcuts import get_current_site
from django.db import models
from django.db.models import Q
from django.template.loader import render_to_string
from django.utils import timezone
from django.conf import settings
from django.urls import reverse
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.utils.text import get_valid_filename
from django.utils.functional import cached_property
from solo.models import SingletonModel
from taggit.managers import TaggableManager
from reversion import revisions as reversion
from tvorba.utils import roman, aktivniResitele
from treenode import treelib
from unidecode import unidecode # Používám pro získání ID odkazu (ještě je to někde po někom zakomentované)
from polymorphic.models import PolymorphicModel
from django.core.mail import EmailMessage
from personalni.models import Prijemce, Organizator
from .base import SeminarModelBase
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -45,701 +12,3 @@ class OverwriteStorage(FileSystemStorage):
if self.exists(name): if self.exists(name):
os.remove(os.path.join(self.location,name)) os.remove(os.path.join(self.location,name))
return super().get_available_name(name,max_length) return super().get_available_name(name,max_length)
@reversion.register(ignore_duplicates=True)
class Rocnik(SeminarModelBase):
class Meta:
db_table = 'seminar_rocniky'
verbose_name = 'Ročník'
verbose_name_plural = 'Ročníky'
ordering = ['-rocnik']
managed = False
# Interní ID
id = models.AutoField(primary_key = True)
prvni_rok = models.IntegerField('první rok', db_index=True, unique=True)
rocnik = models.IntegerField('číslo ročníku', db_index=True, unique=True)
exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False,
help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti),'
' a to jen čísla s veřejnou výsledkovkou')
# má OneToOneField s:
# RocnikNode
def __str__(self):
return '{} ({}/{})'.format(self.rocnik, self.prvni_rok, self.prvni_rok+1)
# Ročník v římských číslech
def roman(self):
return roman(int(self.rocnik))
def verejne(self):
return len(self.verejna_cisla()) > 0
verejne.boolean = True
verejne.short_description = 'Veřejný (jen dle čísel)'
def neverejna_cisla(self):
vc = [c for c in self.cisla.all() if not c.verejne()]
vc.sort(key=lambda c: c.poradi)
return vc
def verejna_cisla(self):
vc = [c for c in self.cisla.all() if c.verejne()]
vc.sort(key=lambda c: c.poradi)
return vc
def posledni_verejne_cislo(self):
vc = self.verejna_cisla()
return vc[-1] if vc else None
def verejne_vysledkovky_cisla(self):
vc = list(self.cisla.filter(deadline_v_cisle__verejna_vysledkovka=True).distinct())
vc.sort(key=lambda c: c.poradi)
return vc
def posledni_zverejnena_vysledkovka_cislo(self):
vc = self.verejne_vysledkovky_cisla()
return vc[-1] if vc else None
def druhy_rok(self):
return self.prvni_rok + 1
def verejne_url(self):
return reverse('seminar_rocnik', kwargs={'rocnik': self.rocnik})
@classmethod
def cached_rocnik(cls, r_id):
name = 'rocnik_%s' % (r_id, )
c = cache.get(name)
if c is None:
c = cls.objects.get(id=r_id)
cache.set(name, c, 300)
return c
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# *Node.save() aktualizuje název *Nodu.
try:
self.rocniknode.save()
except ObjectDoesNotExist:
# Neexistující *Node nemá smysl aktualizovat.
pass
def cislo_pdf_filename(self, filename):
rocnik = str(self.rocnik.rocnik)
return pathlib.Path('cislo', 'pdf', rocnik, '{}-{}.pdf'.format(rocnik, self.poradi))
def cislo_png_filename(self, filename):
rocnik = str(self.rocnik.rocnik)
return pathlib.Path('cislo', 'png', rocnik, '{}-{}.png'.format(rocnik, self.poradi))
@reversion.register(ignore_duplicates=True)
class Cislo(SeminarModelBase):
class Meta:
db_table = 'seminar_cisla'
verbose_name = 'Číslo'
verbose_name_plural = 'Čísla'
ordering = ['-rocnik__rocnik', '-poradi']
managed = False
# Interní ID
id = models.AutoField(primary_key = True)
rocnik = models.ForeignKey(Rocnik, verbose_name='ročník', related_name='cisla_old',
db_index=True,on_delete=models.PROTECT)
poradi = models.CharField('název čísla', max_length=32, db_index=True,
help_text='Většinou jen "1", vyjímečně "7-8", lexikograficky určuje pořadí v ročníku!')
datum_vydani = models.DateField('datum vydání', blank=True, null=True,
help_text='Datum vydání finální verze')
verejne_db = models.BooleanField('číslo zveřejněno',
db_column='verejne', default=False)
poznamka = models.TextField('neveřejná poznámka', blank=True,
help_text='Neveřejná poznámka k číslu (plain text)')
pdf = models.FileField('pdf', upload_to=cislo_pdf_filename, null=True, blank=True,
help_text='PDF čísla, které si mohou řešitelé stáhnout', storage=OverwriteStorage())
titulka_nahled = models.ImageField('Obrázek titulní strany', upload_to=cislo_png_filename, null=True, blank=True,
help_text='Obrázek titulní strany, generuje se automaticky')
# má OneToOneField s:
# CisloNode
def kod(self):
return '%s.%s' % (self.rocnik.rocnik, self.poradi)
kod.short_description = 'Kód čísla'
def __str__(self):
# Potenciální DB HOG, pokud by se ročník necachoval
r = Rocnik.cached_rocnik(self.rocnik_id)
return '{}.{}'.format(r.rocnik, self.poradi)
def verejne(self):
return self.verejne_db
verejne.boolean = True
def verejne_url(self):
return reverse('seminar_cislo', kwargs={'rocnik': self.rocnik.rocnik, 'cislo': self.poradi})
def absolute_url(self):
return "https://" + str(get_current_site(None)) + self.verejne_url()
def nasledujici(self):
"Vrací None, pokud je toto poslední"
return self.relativni_v_rocniku(1)
def predchozi(self):
"Vrací None, pokud je toto první"
return self.relativni_v_rocniku(-1)
def relativni_v_rocniku(self, rel_index):
"Číslo o `index` dále v ročníku. None pokud neexistuje."
cs = self.rocnik.cisla.order_by('poradi').all()
i = list(cs).index(self) + rel_index
if (i < 0) or (i >= len(cs)):
return None
return cs[i]
def vygeneruj_nahled(self):
VYSKA = 594
sirka = int(VYSKA*210/297)
if not self.pdf:
return
# Pokud obrázek neexistuje nebo není aktuální, vytvoř jej
if not self.titulka_nahled or os.path.getmtime(self.titulka_nahled.path) < os.path.getmtime(self.pdf.path):
png_filename = pathlib.Path(tempfile.mkdtemp(), 'nahled.png')
subprocess.run([
"gs",
"-sstdout=%stderr",
"-dSAFER",
"-dNOPAUSE",
"-dBATCH",
"-dNOPROMPT",
"-sDEVICE=png16m",
"-r300x300",
"-dFirstPage=1d",
"-dLastPage=1d",
"-sOutputFile=" + str(png_filename),
"-f%s" % self.pdf.path
],
check=True,
capture_output=True
)
with open(png_filename,'rb') as f:
self.titulka_nahled.save('',f,True)
png_filename.unlink()
png_filename.parent.rmdir()
@classmethod
def get(cls, rocnik, cislo):
try:
r = Rocnik.objects.get(rocnik=rocnik)
c = r.cisla.get(poradi=cislo)
except ObjectDoesNotExist:
return None
return c
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__original_verejne = self.verejne_db
def posli_cislo_mailem(self):
# parametry e-mailu
odkaz = self.absolute_url()
poslat_z_mailu = 'zadani@mam.mff.cuni.cz'
predmet = 'Vyšlo číslo {}'.format(self.kod())
# TODO Možná nechceme všem psát „Ahoj“, např. příjemcům…
text_mailu = 'Ahoj,\n' \
'na adrese {} najdete nejnovější číslo.\n' \
'Vaše M&M\n'.format(odkaz)
predmet_prvni = 'Právě vyšlo 1. číslo M&M, pomoz nám ho poslat dál!'
text_mailu_prvni = 'Milý řešiteli,\n'\
'právě jsme na našem webu zveřejnili první číslo {}. ročníku, najdeš ho na tomto odkazu: {}.\n\n'\
'Doufáme, že tě M&M baví, a byli bychom rádi, kdyby mohlo dělat radost i dalším středoškolákům. Máme na tebe proto jednu prosbu. Sdílej prosím odkaz alespoň s jedním svým kamarádem, který by mohl mít o řešení M&M zájem. Je to pro nás moc důležité a velmi nám tím pomůžeš. Díky!\n\n'\
'Organizátoři M&M\n'.format(self.rocnik.rocnik, odkaz)
predmet_resitel = predmet_prvni if self.poradi == "1" else predmet
text_mailu_resitel = text_mailu_prvni if self.poradi == "1" else text_mailu
# Prijemci e-mailu
resitele_vsichni = aktivniResitele(self).filter(zasilat_cislo_emailem=True)
def posli(subject, text, resitele):
emaily = map(lambda resitel: resitel.osoba.email, resitele)
email = EmailMessage(
subject=subject,
body=text,
from_email=poslat_z_mailu,
bcc=list(emaily)
#bcc = příjemci skryté kopie
)
email.send()
paticka = "---\nK odběru těchto e-mailů jste se přihlásili na stránkách https://mam.matfyz.cz. Z odběru se lze odhlásit na https://mam.matfyz.cz/resitel/osobni-udaje/"
posli(predmet_resitel, text_mailu_resitel + paticka, resitele_vsichni.filter(zasilat_cislo_papirove=False))
posli(predmet_resitel, text_mailu_resitel + 'P. S. Brzy budeme též rozesílat papírovou verzi čísla. Připomínáme, že pokud papírovou verzi čísla nevyužijete, můžete v https://mam.mff.cuni.cz/resitel/osobni-udaje/ zaškrtnout, abychom vám ji neposílali. Čísla vždy můžete nalézt v našem archivu a dál vám budou chodit e-mailem. Děkujeme.\n' + paticka,
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, Prijemce.objects.filter(zasilat_cislo_emailem=True))
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.vygeneruj_nahled()
# Při zveřejnění pošle mail
if self.verejne_db and not self.__original_verejne:
self.posli_cislo_mailem()
# *Node.save() aktualizuje název *Nodu.
try:
self.cislonode.save()
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
CisloNode.objects.create(cislo=self)
def zlomovy_deadline_pro_papirove_cislo(self):
prvni_deadline = Deadline.objects.filter(Q(typ=Deadline.TYP_PRVNI) | Q(typ=Deadline.TYP_PRVNI_A_SOUS), cislo=self).first()
if prvni_deadline is None:
posledni_deadline = self.posledni_deadline
if posledni_deadline is None:
# TODO promyslet, co se má stát tady
return Deadline.objects.filter(Q(cislo__poradi__lt=self.poradi, cislo__rocnik=self.rocnik) | Q(cislo__rocnik__rocnik__lt=self.rocnik.rocnik)).order_by("deadline").last()
return posledni_deadline
return prvni_deadline
@property
def posledni_deadline(self):
return self.deadline_v_cisle.all().order_by("deadline").last()
class Deadline(SeminarModelBase):
class Meta:
db_table = 'seminar_deadliny'
verbose_name = 'Deadline'
verbose_name_plural = 'Deadliny'
ordering = ['deadline']
managed = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__original_verejna_vysledkovka = self.verejna_vysledkovka
id = models.AutoField(primary_key=True)
# V ročníku < 26 nastaveno na datetime.datetime.combine(datetime.date(1994 + cislo.rocnik.rocnik, 6, int(cislo.poradi[0])), datetime.time.min)
deadline = models.DateTimeField(blank=False, default=timezone.make_aware(datetime.datetime.combine(timezone.now(), datetime.time.max)))
cislo = models.ForeignKey(Cislo, verbose_name='deadline v čísle',
related_name='deadline_v_cisle_old', blank=False,
on_delete=models.CASCADE)
TYP_CISLA = 'cisla'
TYP_PRVNI_A_SOUS = 'prvniasous'
TYP_PRVNI = 'prvni'
TYP_SOUS = 'sous'
TYP_CHOICES = [
(TYP_CISLA, 'Deadline celého čísla'),
(TYP_PRVNI, 'První deadline'),
(TYP_PRVNI_A_SOUS, 'Sousový a první deadline'),
(TYP_SOUS, 'Sousový deadline'),
]
CHOICES_MAP = dict(TYP_CHOICES)
typ = models.CharField('typ deadlinu', max_length=32,
choices=TYP_CHOICES, blank=False)
verejna_vysledkovka = models.BooleanField('veřejná výsledkovka',
db_column='verejna_vysledkovka',
default=False)
def __str__(self):
return self.CHOICES_MAP[self.typ] + " " + str(self.cislo)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if self.verejna_vysledkovka and not self.__original_verejna_vysledkovka:
self.vygeneruj_vysledkovku()
if not self.verejna_vysledkovka and hasattr(self, "vysledkovka_v_deadlinu"):
self.vysledkovka_v_deadlinu.delete()
def vygeneruj_vysledkovku(self):
from vysledkovky.utils import VysledkovkaCisla
if hasattr(self, "vysledkovka_v_deadlinu"):
self.vysledkovka_v_deadlinu.delete()
vysledkovka = VysledkovkaCisla(self.cislo, jen_verejne=True, do_deadlinu=self)
if len(vysledkovka.radky_vysledkovky) != 0:
ZmrazenaVysledkovka.objects.create(
deadline=self,
html=render_to_string(
"vysledkovky/vysledkovka_cisla.html",
context={"vysledkovka": vysledkovka, "oznaceni_vysledkovky": self.id}
)
)
class ZmrazenaVysledkovka(SeminarModelBase):
class Meta:
db_table = 'seminar_vysledkovky'
verbose_name = 'Zmražená výsledkovka'
verbose_name_plural = 'Zmražené výsledkovky'
managed = False
deadline = models.OneToOneField(
Deadline,
on_delete=models.CASCADE,
primary_key=True,
related_name="vysledkovka_v_deadlinu_old"
)
html = models.TextField(null=False, blank=False)
class Problemy_Opravovatele(SeminarModelBase):
"""Jen vazebná tabulka pro opravovatele.
Ona stejně existovala, při přesunu mezi aplikacemi jen potřebujeme zajistit nepřejmenování DB tabulky.
Proto taky nepotřebuje žádná specifika, ze :py:class:SeminarModelBase: dědí ze zvyku než že by to k něčemu kdy měo být.
"""
class Meta:
db_table = 'seminar_problemy_opravovatele'
managed = False
id = models.AutoField(primary_key = True)
problem = models.ForeignKey('Problem', on_delete=models.CASCADE, related_name='awawa1_old')
organizator = models.ForeignKey(Organizator, on_delete=models.CASCADE, related_name='awawa2_old')
@reversion.register(ignore_duplicates=True)
# Pozor na následující řádek. *Nekrmit, asi kouše!*
class Problem(SeminarModelBase,PolymorphicModel):
class Meta:
# Není abstraktní, protože se na něj jinak nedají dělat ForeignKeys.
# TODO: Udělat to polymorfní (pomocí django-polymorphic), abychom dostali
# po těch vazbách přímo tu úlohu/témátko vč. fieldů, které nejsou součástí
# modelu Problem?
#abstract = True
db_table = 'seminar_problemy'
verbose_name = 'Problém'
verbose_name_plural = 'Problémy'
ordering = ['nazev']
managed = False
# Interní ID
id = models.AutoField(primary_key = True)
# Název
nazev = models.CharField('název', max_length=256) # Zveřejnitelný na stránky
# Problém má podproblémy
nadproblem = models.ForeignKey('self', verbose_name='nadřazený problém',
related_name='podproblem_old', null=True, blank=True,
on_delete=models.SET_NULL)
STAV_NAVRH = 'navrh'
STAV_ZADANY = 'zadany'
STAV_VYRESENY = 'vyreseny'
STAV_SMAZANY = 'smazany'
STAV_CHOICES = [
(STAV_NAVRH, 'Návrh'),
(STAV_ZADANY, 'Zadaný'),
(STAV_VYRESENY, 'Vyřešený'),
(STAV_SMAZANY, 'Smazaný'),
]
stav = models.CharField('stav problému', max_length=32, choices=STAV_CHOICES, blank=False, default=STAV_NAVRH)
# Téma je taky Problém, takže má stavy, "zadané" témátko je aktuálně otevřené a dá se k němu něco poslat (řešení nebo článek)
zamereni = TaggableManager(verbose_name='zaměření', related_name='zamereni_old',
help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True)
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(Organizator, verbose_name='autor problému',
related_name='autor_problemu_%(class)s_old', null=True, blank=True,
on_delete=models.SET_NULL)
garant = models.ForeignKey(Organizator, verbose_name='garant zadaného problému',
related_name='garant_problemu_%(class)s_old', null=True, blank=True,
on_delete=models.SET_NULL)
opravovatele = models.ManyToManyField(Organizator, verbose_name='opravovatelé',
blank=True, related_name='opravovatele_%(class)s_old', through=Problemy_Opravovatele)
kod = models.CharField('lokální kód', max_length=32, blank=True, default='',
help_text='Číslo/kód úlohy v čísle nebo kód tématu/článku/seriálu v ročníku')
vytvoreno = models.DateTimeField('vytvořeno', default=timezone.now, blank=True, editable=False)
def __str__(self):
return self.nazev
# Implicitini implementace, jednotlivé dědící třídy si přepíšou
@cached_property
def kod_v_rocniku(self):
if self.stav == Problem.STAV_ZADANY or self.stav == Problem.STAV_VYRESENY:
if self.nadproblem:
return self.nadproblem.kod_v_rocniku+".{}".format(self.kod)
return str(self.kod)
logger.warning(f"K problému {self} byl vyžadován kód v ročníku, i když není zadaný ani vyřešený.")
return f'<Není zadaný: {self.kod}>'
# def verejne(self):
# # aktuálně podle stavu problému
# # FIXME pro některé problémy možná chceme override
# # FIXME vrací veřejnost čistě problému, nezávisle na čísle, ve kterém je.
# # Je to tak správně? Podle aktuální představy ano.
# stav_verejny = False
# if self.stav == 'zadany' or self.stav == 'vyreseny':
# stav_verejny = True
# print("stav_verejny: {}".format(stav_verejny))
#
# cislo_verejne = False
# cislonode = self.cislo_node()
# if cislonode is None:
# # problém nemá vlastní node, veřejnost posuzujeme jen podle stavu
# print("empty node")
# return stav_verejny
# else:
# cislo_zadani = cislonode.cislo
# if (cislo_zadani and cislo_zadani.verejne()):
# print("cislo: {}".format(cislo_zadani))
# cislo_verejne = True
# print("stav_verejny: {}".format(stav_verejny))
# print("cislo_verejne: {}".format(cislo_verejne))
# return (stav_verejny and cislo_verejne)
# verejne.boolean = True
def verejne_url(self):
return reverse('seminar_problem', kwargs={'pk': self.id})
def admin_url(self):
return reverse('admin:seminar_problem_change', args=(self.id, ))
@cached_property
def hlavni_problem(self):
""" Pro daný problém vrátí jeho nejvyšší nadproblém."""
problem = self
while not (problem.nadproblem is None):
problem = problem.nadproblem
return problem
# FIXME - k úloze
def body_v_zavorce(self):
"""Vrať string s body v závorce jsou-li u problému vyplněné, jinak ''
Je-li desetinná část nulová, nezobrazuj ji.
"""
pocet_bodu = None
if self.body:
b = self.body
pocet_bodu = int(b) if int(b) == b else b
return "({}\u2009b)".format(pocet_bodu) if self.body else ""
class Tema(Problem):
class Meta:
db_table = 'seminar_temata'
verbose_name = 'Téma'
verbose_name_plural = 'Témata'
managed = False
TEMA_TEMA = 'tema'
TEMA_SERIAL = 'serial'
TEMA_CHOICES = [
(TEMA_TEMA, 'Téma'),
(TEMA_SERIAL, 'Seriál'),
]
tema_typ = models.CharField('Typ tématu', max_length=16, choices=TEMA_CHOICES,
blank=False, default=TEMA_TEMA)
rocnik = models.ForeignKey(Rocnik, verbose_name='ročník',related_name='temata_old',blank=True, null=True,
on_delete=models.PROTECT)
abstrakt = models.TextField('Abstrakt na rozcestník', blank=True)
obrazek = models.ImageField('Obrázek na rozcestník', null=True, blank=True)
@cached_property
def kod_v_rocniku(self):
if self.stav == Problem.STAV_ZADANY or self.stav == Problem.STAV_VYRESENY:
if self.nadproblem:
return self.nadproblem.kod_v_rocniku+".t{}".format(self.kod)
return 't'+self.kod
logger.warning(f"K problému {self} byl vyžadován kód v ročníku, i když není zadaný ani vyřešený.")
return f'<Není zadaný: {self.kod}>'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# *Node.save() aktualizuje název *Nodu.
for tvcn in self.temavcislenode_set.all():
tvcn.save()
def cislo_node(self):
tema_node_set = self.temavcislenode_set.all()
tema_cisla_vyskyt = []
from seminar.models.treenode import CisloNode
for tn in tema_node_set:
tema_cisla_vyskyt.append(
treelib.get_upper_node_of_type(tn, CisloNode).cislo)
tema_cisla_vyskyt.sort(key=lambda x:x.datum_vydani)
prvni_zadani = tema_cisla_vyskyt[0]
return prvni_zadani.cislonode
class Clanek(Problem):
class Meta:
db_table = 'seminar_clanky'
verbose_name = 'Článek'
verbose_name_plural = 'Články'
managed = False
cislo = models.ForeignKey(Cislo, blank=True, null=True, on_delete=models.PROTECT,
verbose_name='číslo vydání', related_name='vydane_clanky_old')
strana = models.PositiveIntegerField(verbose_name="první strana", blank=True, null=True)
@cached_property
def kod_v_rocniku(self):
if self.stav == Problem.STAV_ZADANY or self.stav == Problem.STAV_VYRESENY:
# Nemělo by být potřeba
# if self.nadproblem:
# return self.nadproblem.kod_v_rocniku+".c{}".format(self.kod)
return "c" + self.kod
logger.warning(f"K problému {self} byl vyžadován kód v ročníku, i když není zadaný ani vyřešený.")
return f'<Není zadaný: {self.kod}>'
def node(self):
return None
class Uloha(Problem):
class Meta:
db_table = 'seminar_ulohy'
verbose_name = 'Úloha'
verbose_name_plural = 'Úlohy'
managed = False
cislo_zadani = models.ForeignKey(Cislo, verbose_name='číslo zadání', blank=True,
null=True, related_name='zadane_ulohy_old', on_delete=models.PROTECT)
cislo_deadline = models.ForeignKey(Cislo, verbose_name='číslo deadlinu', blank=True,
null=True, related_name='deadlinove_ulohy_old', on_delete=models.PROTECT)
cislo_reseni = models.ForeignKey(Cislo, verbose_name='číslo řešení', blank=True,
null=True, related_name='resene_ulohy_old',
help_text='Číslo s řešením úlohy, jen pro úlohy',
on_delete=models.PROTECT)
max_body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='maximum bodů',
blank=True, null=True)
# má OneToOneField s:
# UlohaZadaniNode
# UlohaVzorakNode
@cached_property
def kod_v_rocniku(self):
if self.stav == Problem.STAV_ZADANY or self.stav == Problem.STAV_VYRESENY:
return f"{self.cislo_zadani.poradi}.{self.kod}"
logger.warning(f"K problému {self} byl vyžadován kód v ročníku, i když není zadaný ani vyřešený.")
return f'<Není zadaný: {self.kod}>'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# *Node.save() aktualizuje název *Nodu.
try:
self.ulohazadaninode.save()
except ObjectDoesNotExist:
# Neexistující *Node nemá smysl aktualizovat.
pass
try:
self.ulohavzoraknode.save()
except ObjectDoesNotExist:
# Neexistující *Node nemá smysl aktualizovat.
pass
def cislo_node(self):
zadani_node = self.ulohazadaninode
from seminar.models.treenode import CisloNode
return treelib.get_upper_node_of_type(zadani_node, CisloNode)
def aux_generate_filename(self, filename):
"""Pomocná funkce generující ošetřený název souboru v adresáři s datem"""
clean = get_valid_filename(
unidecode(filename.replace('/', '-').replace('\0', ''))
)
datedir = timezone.now().strftime('%Y-%m')
fname = "{}/{}".format(
timezone.now().strftime('%Y-%m-%d-%H:%M'),
clean)
return os.path.join(datedir, fname)
class Pohadka(SeminarModelBase):
"""Kus pohádky před/za úlohou v čísle"""
class Meta:
db_table = 'seminar_pohadky'
verbose_name = 'Pohádka'
verbose_name_plural = 'Pohádky'
ordering = ['vytvoreno']
managed = False
# Interní ID
id = models.AutoField(primary_key=True)
autor = models.ForeignKey(
Organizator,
verbose_name="Autor pohádky",
# Při nahrávání z TeXu není vyplnění vyžadováno, v adminu je
null=True,
blank=False,
on_delete=models.SET_NULL,
related_name='awawa3_old',
)
vytvoreno = models.DateTimeField(
'Vytvořeno',
default=timezone.now,
blank=True,
editable=False
)
# má OneToOneField s:
# PohadkaNode
def __str__(self):
uryvek = self.text if len(self.text) < 50 else self.text[:(50-3)]+"..."
return uryvek
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# *Node.save() aktualizuje název *Nodu.
try:
self.pohadkanode.save()
except ObjectDoesNotExist:
# Neexistující *Node nemá smysl aktualizovat.
pass

13
soustredeni/migrations/0005_tvorba_relink.py

@ -12,11 +12,14 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.AlterField( ## Konferu zmigrujeme jinak, kvůli <https://code.djangoproject.com/ticket/23521> jí nejde přepsat někde ve stavu `bases`.
model_name='konfera', ## Proto si ji unmanagujeme a vyrobíme celou znovu, to by nemělo vadit (zvlášť když t.č. v DB žádná instance Konfery není).
name='problem_ptr', ## (Šlo by `SeparateStateAndData`, což v principu děláme taky ale ty migrace jsou lehce čitelnější a o poznání konzistentnější.)
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tvorba.problem'), #migrations.AlterField(
), # model_name='konfera',
# name='problem_ptr',
# field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tvorba.problem'),
#),
migrations.AlterField( migrations.AlterField(
model_name='soustredeni', model_name='soustredeni',
name='rocnik', name='rocnik',

17
soustredeni/migrations/0006_tvorba_relink2.py

@ -0,0 +1,17 @@
# Generated by Django 4.2.16 on 2024-10-30 19:37
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('soustredeni', '0005_tvorba_relink'),
]
operations = [
migrations.AlterModelOptions(
name='konfera',
options={'managed': False, 'verbose_name': 'Konfera', 'verbose_name_plural': 'Konfery'},
),
]

15
soustredeni/migrations/0007_tvorba_relink3.py

@ -0,0 +1,15 @@
# Generated by Django 4.2.16 on 2024-10-30 19:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('soustredeni', '0006_tvorba_relink2'),
]
operations = [
migrations.DeleteModel(
name='Konfera',
),
]

34
soustredeni/migrations/0008_tvorba_relink4.py

@ -0,0 +1,34 @@
# Generated by Django 4.2.16 on 2024-10-30 19:45
from django.db import migrations,models
import django.db.models.deletion
import soustredeni.models
class Migration(migrations.Migration):
dependencies = [
('soustredeni', '0007_tvorba_relink3'),
]
operations = [
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='tvorba.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=('tvorba.problem',),
),
]

17
soustredeni/migrations/0009_tvorba_relink5.py

@ -0,0 +1,17 @@
# Generated by Django 4.2.16 on 2024-10-30 20:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('soustredeni', '0008_tvorba_relink4'),
]
operations = [
migrations.AlterModelOptions(
name='konfera',
options={'verbose_name': 'Konfera', 'verbose_name_plural': 'Konfery'},
),
]

14
soustredeni/migrations/0010_tvorba_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-10-30 21:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('soustredeni', '0009_tvorba_relink5'),
('tvorba', '0003_tvorba_post'),
]
operations = [
]

54
tvorba/migrations/0002_tvorba_manage.py

@ -0,0 +1,54 @@
# Generated by Django 4.2.16 on 2024-10-30 21:29
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tvorba', '0001_tvorba_create'),
('seminar', '0138_tvorba_delete'),
]
operations = [
migrations.AlterModelOptions(
name='cislo',
options={'ordering': ['-rocnik__rocnik', '-poradi'], 'verbose_name': 'Číslo', 'verbose_name_plural': 'Čísla'},
),
migrations.AlterModelOptions(
name='clanek',
options={'verbose_name': 'Článek', 'verbose_name_plural': 'Články'},
),
migrations.AlterModelOptions(
name='deadline',
options={'ordering': ['deadline'], 'verbose_name': 'Deadline', 'verbose_name_plural': 'Deadliny'},
),
migrations.AlterModelOptions(
name='pohadka',
options={'ordering': ['vytvoreno'], 'verbose_name': 'Pohádka', 'verbose_name_plural': 'Pohádky'},
),
migrations.AlterModelOptions(
name='problem',
options={'ordering': ['nazev'], 'verbose_name': 'Problém', 'verbose_name_plural': 'Problémy'},
),
migrations.AlterModelOptions(
name='problemy_opravovatele',
options={},
),
migrations.AlterModelOptions(
name='rocnik',
options={'ordering': ['-rocnik'], 'verbose_name': 'Ročník', 'verbose_name_plural': 'Ročníky'},
),
migrations.AlterModelOptions(
name='tema',
options={'verbose_name': 'Téma', 'verbose_name_plural': 'Témata'},
),
migrations.AlterModelOptions(
name='uloha',
options={'verbose_name': 'Úloha', 'verbose_name_plural': 'Úlohy'},
),
migrations.AlterModelOptions(
name='zmrazenavysledkovka',
options={'verbose_name': 'Zmražená výsledkovka', 'verbose_name_plural': 'Zmražené výsledkovky'},
),
]

13
tvorba/migrations/0003_tvorba_post.py

@ -0,0 +1,13 @@
# Generated by Django 4.2.16 on 2024-10-30 21:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tvorba', '0002_tvorba_manage'),
]
operations = [
]

13
tvorba/models.py

@ -31,7 +31,8 @@ from polymorphic.models import PolymorphicModel
from django.core.mail import EmailMessage from django.core.mail import EmailMessage
from seminar.models import SeminarModelBase, OverwriteStorage from seminar.models.base import SeminarModelBase
from seminar.models.tvorba import OverwriteStorage
from personalni.models import Prijemce, Organizator from personalni.models import Prijemce, Organizator
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -44,7 +45,6 @@ class Rocnik(SeminarModelBase):
verbose_name = 'Ročník' verbose_name = 'Ročník'
verbose_name_plural = 'Ročníky' verbose_name_plural = 'Ročníky'
ordering = ['-rocnik'] ordering = ['-rocnik']
managed = False
# Interní ID # Interní ID
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -132,7 +132,6 @@ class Cislo(SeminarModelBase):
verbose_name = 'Číslo' verbose_name = 'Číslo'
verbose_name_plural = 'Čísla' verbose_name_plural = 'Čísla'
ordering = ['-rocnik__rocnik', '-poradi'] ordering = ['-rocnik__rocnik', '-poradi']
managed = False
# Interní ID # Interní ID
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -321,7 +320,6 @@ class Deadline(SeminarModelBase):
verbose_name = 'Deadline' verbose_name = 'Deadline'
verbose_name_plural = 'Deadliny' verbose_name_plural = 'Deadliny'
ordering = ['deadline'] ordering = ['deadline']
managed = False
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -384,7 +382,6 @@ class ZmrazenaVysledkovka(SeminarModelBase):
db_table = 'seminar_vysledkovky' db_table = 'seminar_vysledkovky'
verbose_name = 'Zmražená výsledkovka' verbose_name = 'Zmražená výsledkovka'
verbose_name_plural = 'Zmražené výsledkovky' verbose_name_plural = 'Zmražené výsledkovky'
managed = False
deadline = models.OneToOneField( deadline = models.OneToOneField(
Deadline, Deadline,
@ -403,7 +400,6 @@ class Problemy_Opravovatele(SeminarModelBase):
""" """
class Meta: class Meta:
db_table = 'seminar_problemy_opravovatele' db_table = 'seminar_problemy_opravovatele'
managed = False
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -425,7 +421,6 @@ class Problem(SeminarModelBase,PolymorphicModel):
verbose_name = 'Problém' verbose_name = 'Problém'
verbose_name_plural = 'Problémy' verbose_name_plural = 'Problémy'
ordering = ['nazev'] ordering = ['nazev']
managed = False
# Interní ID # Interní ID
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -543,7 +538,6 @@ class Tema(Problem):
db_table = 'seminar_temata' db_table = 'seminar_temata'
verbose_name = 'Téma' verbose_name = 'Téma'
verbose_name_plural = 'Témata' verbose_name_plural = 'Témata'
managed = False
TEMA_TEMA = 'tema' TEMA_TEMA = 'tema'
TEMA_SERIAL = 'serial' TEMA_SERIAL = 'serial'
@ -591,7 +585,6 @@ class Clanek(Problem):
db_table = 'seminar_clanky' db_table = 'seminar_clanky'
verbose_name = 'Článek' verbose_name = 'Článek'
verbose_name_plural = 'Články' verbose_name_plural = 'Články'
managed = False
cislo = models.ForeignKey(Cislo, blank=True, null=True, on_delete=models.PROTECT, cislo = models.ForeignKey(Cislo, blank=True, null=True, on_delete=models.PROTECT,
verbose_name='číslo vydání', related_name='vydane_clanky') verbose_name='číslo vydání', related_name='vydane_clanky')
@ -617,7 +610,6 @@ class Uloha(Problem):
db_table = 'seminar_ulohy' db_table = 'seminar_ulohy'
verbose_name = 'Úloha' verbose_name = 'Úloha'
verbose_name_plural = 'Úlohy' verbose_name_plural = 'Úlohy'
managed = False
cislo_zadani = models.ForeignKey(Cislo, verbose_name='číslo zadání', blank=True, cislo_zadani = models.ForeignKey(Cislo, verbose_name='číslo zadání', blank=True,
null=True, related_name='zadane_ulohy', on_delete=models.PROTECT) null=True, related_name='zadane_ulohy', on_delete=models.PROTECT)
@ -680,7 +672,6 @@ class Pohadka(SeminarModelBase):
verbose_name = 'Pohádka' verbose_name = 'Pohádka'
verbose_name_plural = 'Pohádky' verbose_name_plural = 'Pohádky'
ordering = ['vytvoreno'] ordering = ['vytvoreno']
managed = False
# Interní ID # Interní ID
id = models.AutoField(primary_key=True) id = models.AutoField(primary_key=True)

14
various/migrations/0006_tvorba_post.py

@ -0,0 +1,14 @@
# Generated by Django 4.2.16 on 2024-10-30 21:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('various', '0005_tvorba_relink'),
('tvorba', '0003_tvorba_post'),
]
operations = [
]
Loading…
Cancel
Save