import os import reversion from django.contrib.sites.shortcuts import get_current_site from django.db import models from django.db.models import Sum from django.urls import reverse_lazy from django.utils import timezone from django.conf import settings from seminar.models import models_all as am from seminar.models import personalni as pm from seminar.models.base import SeminarModelBase @reversion.register(ignore_duplicates=True) class Reseni(am.SeminarModelBase): class Meta: db_table = 'seminar_reseni' verbose_name = 'Řešení' verbose_name_plural = 'Řešení' #ordering = ['-problem', 'resitele'] # FIXME: Takhle to chceme, ale nefunguje to. ordering = ['-cas_doruceni'] # Interní ID id = models.AutoField(primary_key = True) # Ke každé dvojici řešní a problém existuje nanejvýš jedno hodnocení, doplnění vazby. 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í', help_text='Seznam autorů řešení', through='Reseni_Resitele') cas_doruceni = models.DateTimeField('čas_doručení', default=timezone.now, blank=True) FORMA_PAPIR = 'papir' FORMA_EMAIL = 'email' FORMA_UPLOAD = 'upload' FORMA_CHOICES = [ (FORMA_PAPIR, 'Papírové řešení'), (FORMA_EMAIL, 'Emailem'), (FORMA_UPLOAD, 'Upload přes web'), ] forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, default=FORMA_EMAIL) text_cely = models.OneToOneField('ReseniNode', verbose_name='Plná verze textu řešení', blank=True, null=True, related_name="reseni_cely_set", on_delete=models.PROTECT) poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k řešení (plain text)') zverejneno = models.BooleanField('řešení zveřejněno', default=False, help_text='Udává, zda je řešení zveřejněno') def verejne_url(self): return str(reverse_lazy('odevzdavatko_detail_reseni', args=[self.id])) def absolute_url(self): return "https://" + str(get_current_site(None)) + self.verejne_url() # má OneToOneField s: # Konfera # má ForeignKey s: # Hodnoceni def sum_body(self): return self.hodnoceni_set.all().aggregate(Sum('body'))["body__sum"] def __str__(self): return "{}({}): {}({})".format(self.resitele.first(),len(self.resitele.all()), self.problem.first() ,len(self.problem.all())) # NOTE: Potenciální DB HOG (bez select_related) ## Pravdepodobne uz nebude potreba: # def save(self, *args, **kwargs): # if ((self.cislo_body is None) and (self.problem.cislo_reseni) and # (self.problem.typ == Problem.TYP_ULOHA)): # self.cislo_body = self.problem.cislo_reseni # super(Reseni, self).save(*args, **kwargs) class Hodnoceni(am.SeminarModelBase): class Meta: db_table = 'seminar_hodnoceni' verbose_name = 'Hodnocení' verbose_name_plural = 'Hodnocení' # Interní ID id = models.AutoField(primary_key = True) body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='body', blank=True, null=True) cislo_body = models.ForeignKey(am.Cislo, verbose_name='číslo pro body', related_name='hodnoceni', blank=True, null=True, on_delete=models.PROTECT) reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE) problem = models.ForeignKey(am.Problem, verbose_name='problém', related_name='hodnoceni', on_delete=models.PROTECT) def __str__(self): return "{}, {}, {}".format(self.problem, self.reseni, self.body) def generate_filename(self, filename): return os.path.join( settings.SEMINAR_RESENI_DIR, am.aux_generate_filename(self, filename) ) @reversion.register(ignore_duplicates=True) class PrilohaReseni(am.SeminarModelBase): class Meta: db_table = 'seminar_priloha_reseni' verbose_name = 'Příloha řešení' verbose_name_plural = 'Přílohy řešení' ordering = ['reseni', 'vytvoreno'] # Interní ID id = models.AutoField(primary_key = True) reseni = models.ForeignKey(Reseni, verbose_name='řešení', related_name='prilohy', on_delete=models.CASCADE) vytvoreno = models.DateTimeField('vytvořeno', default=timezone.now, blank=True, editable=False) soubor = models.FileField('soubor', upload_to = generate_filename) poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k příloze řešení (plain text), např. o původu') res_poznamka = models.TextField('poznámka řešitele', blank=True, help_text='Poznámka k příloze řešení, např. co daný soubor obsahuje') def __str__(self): return str(self.soubor) def split(self): "Vrátí cestu rozsekanou po složkách. To se hodí v templatech" # Věřím, že tohle funguje, případně použít os.path nebo pathlib. return self.soubor.url.split('/') # Vazebna tabulka. Mozna se generuje automaticky. @reversion.register(ignore_duplicates=True) class Reseni_Resitele(models.Model): class Meta: db_table = 'seminar_reseni_resitele' verbose_name = 'Řešení řešitelů' verbose_name_plural = 'Řešení řešitelů' ordering = ['reseni', 'resitele'] # Interní ID id = models.AutoField(primary_key = True) resitele = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) reseni = models.ForeignKey(Reseni, verbose_name='řešení', on_delete=models.CASCADE) # podil - jakou merou se ktery resitel podilel na danem reseni # - pouziti v budoucnu, pokud by resitele nemeli dostat vsichni stejne bodu za spolecne reseni def __str__(self): return '{} od {}'.format(self.reseni, self.resitel) # NOTE: Poteciální DB HOG bez select_related class ReseniNode(am.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)