# -*- coding: utf-8 -*- import os import random from django.db import models from django.contrib import auth from django.utils import timezone from django.conf import settings from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import force_unicode from django.utils.text import slugify from django.core.urlresolvers import reverse from django.core.cache import cache from imagekit.models import ImageSpecField, ProcessedImageField from imagekit.processors import ResizeToFit, Transpose from PIL import Image import os from functools import partial from cStringIO import StringIO from django.core.files.base import ContentFile from django_countries.fields import CountryField from solo.models import SingletonModel from taggit.managers import TaggableManager import reversion from seminar.utils import roman class SeminarModelBase(models.Model): class Meta: abstract = True def verejne(self): return False def get_absolute_url(self): return self.verejne_url() # TODO "absolute" def admin_url(self): model_name = self.__class__.__name__.lower() return reverse('admin:seminar_%s_change'%(model_name, ), args=(self.id, )) def verejne_url(self): return None # # Mělo by být částečně vytaženo z Aesopa # viz https://ovvp.mff.cuni.cz/wiki/aesop/export-skol. # @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Skola(SeminarModelBase): class Meta: db_table = 'seminar_skoly' verbose_name = u'Škola' verbose_name_plural = u'Školy' ordering = ['mesto', 'nazev'] # Interní ID id = models.AutoField(primary_key = True) # Aesopi ID "izo:..." nebo "aesop:..." # NULL znamená v exportu do aesopa "ufo" aesop_id = models.CharField(u'Aesop ID', max_length=32, blank=True, default='', help_text=u'Aesopi ID typu "izo:..." nebo "aesop:..."') # Staré (do 2015) MAMOPER.MM_RIESITELIA.ID z DAKOSu -- jen u importovaných záznamů import_dakos_id = models.CharField(u'importované DKSROOT.V_SKOLA.ID', max_length=32, blank=True, default='', help_text=u'DKSROOT.V_SKOLA.ID z DAKOS importu, jen historický význam') # IZO školy (jen české školy) izo = models.CharField(u'IZO', max_length=32, blank=True, help_text=u'IZO školy (jen české školy)') # Celý název školy nazev = models.CharField(u'název', max_length=256, help_text=u'Celý název školy') # Zkraceny nazev pro zobrazení ve výsledkovce, volitelné. # Není v Aesopovi, musíme vytvářet sami. kratky_nazev = models.CharField(u'zkrácený název', max_length=256, blank=True, help_text="Zkrácený název pro zobrazení ve výsledkovce") # Ulice může být jen číslo ulice = models.CharField(u'ulice', max_length=256) mesto = models.CharField(u'město', max_length=256) psc = models.CharField(u'PSČ', max_length=32) # ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) # Ekvivalentní s CharField(max_length=2, default='CZ', ...) stat = CountryField(u'stát', default='CZ', help_text=u'ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') # Jaké vzdělání škpla poskytuje? je_zs = models.BooleanField(u'základní stupeň', default=True) je_ss = models.BooleanField(u'střední stupeň', default=True) poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka ke škole (plain text)') def __str__(self): return force_unicode(u'%s, %s, %s' % (self.nazev, self.ulice, self.mesto)) @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Resitel(SeminarModelBase): class Meta: db_table = 'seminar_resitele' verbose_name = u'Řešitel' verbose_name_plural = u'Řešitelé' ordering = ['prijmeni', 'jmeno'] # Interní ID id = models.AutoField(primary_key = True) jmeno = models.CharField(u'jméno', max_length=256) prijmeni = models.CharField(u'příjmení', max_length=256) # User, pokud má na webu účet user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=u'uživatel') # Pohlaví. Že ho neznáme se snad nestane (a ušetří to práci při programování) pohlavi_muz = models.BooleanField(u'pohlaví (muž)', default=False) skola = models.ForeignKey(Skola, blank=True, null=True, verbose_name=u'škola') # Očekávaný rok maturity a vyřazení z aktivních řešitelů rok_maturity = models.IntegerField(u'rok maturity', blank=True, null=True) email = models.EmailField(u'e-mail', max_length=256, blank=True, default='') telefon = models.CharField(u'telefon', max_length=256, blank=True, default='') datum_narozeni = models.DateField(u'datum narození', blank=True, null=True) # NULL dokud nedali souhlas datum_souhlasu_udaje = models.DateField(u'datum souhlasu (údaje)', blank=True, null=True, help_text=u'Datum souhlasu se zpracováním osobních údajů') # NULL dokud nedali souhlas datum_souhlasu_zasilani = models.DateField(u'datum souhlasu (spam)', blank=True, null=True, help_text=u'Datum souhlasu se zasíláním MFF materiálů') # Alespoň odhad (rok či i měsíc) datum_prihlaseni = models.DateField(u'datum přihlášení', default=timezone.now) ZASILAT_DOMU = 'domu' ZASILAT_DO_SKOLY = 'do_skoly' ZASILAT_NIKAM = 'nikam' ZASILAT_CHOICES = [ (ZASILAT_DOMU, u'Domů'), (ZASILAT_DO_SKOLY, u'Do školy'), (ZASILAT_NIKAM, u'Nikam'), ] zasilat = models.CharField(u'kam zasílat', max_length=32, choices=ZASILAT_CHOICES, blank=False, default=ZASILAT_DOMU) # Ulice může být i jen číslo ulice = models.CharField(u'ulice', max_length=256, blank=True, default='') mesto = models.CharField(u'město', max_length=256, blank=True, default='') psc = models.CharField(u'PSČ', max_length=32, blank=True, default='') # ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) # Ekvivalentní s CharField(max_length=2, default='CZ', ...) stat = CountryField(u'stát', default='CZ', help_text=u'ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k řešiteli (plain text)') # Staré (do 2015) MAMOPER.MM_RIESITELIA.ID z DAKOS -- jen u importovaných záznamů import_mamoper_id = models.CharField(u'importované MM_RIESITELIA.ID', max_length=32, blank=True, default='', help_text=u'MAMOPER.MM_RIESITELIA.ID z DAKOS importu, jen historický význam') def plne_jmeno(self): return force_unicode(u'%s %s' % (self.jmeno, self.prijmeni)) def inicial_krestni(self): return force_unicode(u'%s.' % (self.jmeno[0])) def __str__(self): return force_unicode(self.plne_jmeno()) def export_row(self): "Slovnik pro pouziti v OVVP exportu" return { 'id': self.id, 'name': self.jmeno, 'surname': self.prijmeni, 'gender': 'M' if self.pohlavi_muz else 'F', 'born': self.datum_narozeni.isoformat() if self.datum_narozeni else '', 'email': self.email, 'end-year': self.rok_maturity or '', # TODO(gavento): Adresa skoly, kdyz preferuje zasilani tam? 'street': self.ulice, 'town': self.mesto, 'postcode': self.psc, 'country': self.stat, 'spam-flag': 'Y' if self.datum_souhlasu_zasilani else '', 'spam-date': self.datum_souhlasu_zasilani.isoformat() if self.datum_souhlasu_zasilani else '', 'school': self.skola.aesop_id if self.skola else '', 'school-name': str(self.skola) if self.skola else 'Skola neni znama', } def rocnik(self, rocnik): """Vrati skolni rocnik resitele pro zadany Rocnik. Vraci '' pro neznamy rok maturity resitele, Z* pro ekvivalent ZŠ.""" if self.rok_maturity is None: return '' rozdil = 5 - (self.rok_maturity - rocnik.prvni_rok) if rozdil >= 1: return str(rozdil) else: return 'Z' + str(rozdil + 9) def get_titul(self, celkove_body): "Vrati titul podle zadaneho poctu bodu." if celkove_body < 10: return '' elif celkove_body < 20: return 'Bc.' elif celkove_body < 50: return 'Mgr.' elif celkove_body < 100: return 'Dr.' elif celkove_body < 200: return 'Doc.' elif celkove_body < 500: return 'Prof.' else: return 'Akad.' @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Rocnik(SeminarModelBase): class Meta: db_table = 'seminar_rocniky' verbose_name = u'Ročník' verbose_name_plural = u'Ročníky' ordering = ['-rocnik'] # Interní ID id = models.AutoField(primary_key = True) prvni_rok = models.IntegerField(u'první rok', db_index=True, unique=True) rocnik = models.IntegerField(u'číslo ročníku', db_index=True, unique=True) exportovat = models.BooleanField(u'export do AESOPa', db_column='exportovat', default=False, help_text=u'Exportuje se jen podle tohoto flagu (ne veřejnosti), a to jen čísla s veřejnou výsledkovkou') def __str__(self): return force_unicode(u'%s (%d/%d)' % (self.rocnik, self.prvni_rok, self.prvni_rok+1)) def roman(self): return force_unicode(roman(int(self.rocnik))) def verejne(self): return len(self.verejna_cisla()) > 0 verejne.boolean = True verejne.short_description = u'Veřejný (jen dle čísel)' def verejna_cisla(self): vc = [c for c in self.cisla.all() if c.verejne()] vc.sort(key=lambda c: c.cislo) 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(verejna_vysledkovka=True)) vc.sort(key=lambda c: c.cislo) 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 cislo_pdf_filename(self, filename): rocnik = str(self.rocnik.rocnik) return os.path.join('cislo', 'pdf', rocnik, '{}-{}.pdf'.format(rocnik, self.cislo)) @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Cislo(SeminarModelBase): class Meta: db_table = 'seminar_cisla' verbose_name = u'Číslo' verbose_name_plural = u'Čísla' ordering = ['-rocnik__rocnik', '-cislo'] # Interní ID id = models.AutoField(primary_key = True) rocnik = models.ForeignKey(Rocnik, verbose_name=u'ročník', related_name='cisla', db_index=True) cislo = models.CharField(u'název čísla', max_length=32, db_index=True, help_text=u'Většinou jen "1", vyjímečně "7-8", lexikograficky určuje pořadí v ročníku!') datum_vydani = models.DateField(u'datum vydání', blank=True, null=True, help_text=u'Datum vydání finální verze') datum_deadline = models.DateField(u'datum deadline', blank=True, null=True, help_text=u'Datum pro příjem řešení úloh zadaných v tomto čísle') verejne_db = models.BooleanField(u'číslo zveřejněno', db_column='verejne', default=False) verejna_vysledkovka = models.BooleanField(u'zveřejněna výsledkovka', default=False, help_text=u'Je-li false u veřejného čísla, není výsledkovka zatím veřejná.') poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k číslu (plain text)') pdf = models.FileField(u'pdf', upload_to=cislo_pdf_filename, null=True, blank=True, help_text=u'Pdf čísla, které si mohou řešitelé stáhnout') def kod(self): return u'%s.%s' % (self.rocnik.rocnik, self.cislo) kod.short_description = u'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 force_unicode(u'%s.%s' % (r.rocnik, self.cislo, )) 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.cislo}) def nasledujici(self): u"Vrací None, pokud je toto poslední" return self.relativni_v_rocniku(1) def predchozi(self): u"Vrací None, pokud je toto první" return self.relativni_v_rocniku(-1) def relativni_v_rocniku(self, rel_index): u"Číslo o `index` dále v ročníku. None pokud neexistuje." cs = self.rocnik.cisla.order_by('cislo').all() i = list(cs).index(self) + rel_index if (i < 0) or (i >= len(cs)): return None return cs[i] @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Problem(SeminarModelBase): class Meta: db_table = 'seminar_problemy' verbose_name = u'Problém' verbose_name_plural = u'Problémy' ordering = ['nazev'] # Interní ID id = models.AutoField(primary_key = True) # Název nazev = models.CharField(u'název', max_length=256) TYP_ULOHA = 'uloha' TYP_TEMA = 'tema' TYP_SERIAL = 'serial' TYP_ORG_CLANEK = 'org-clanek' TYP_RES_CLANEK = 'res-clanek' TYP_CHOICES = [ (TYP_ULOHA, u'Úloha'), (TYP_TEMA, u'Téma'), (TYP_SERIAL, u'Seriál'), (TYP_ORG_CLANEK, u'Organizátorský článek'), (TYP_RES_CLANEK, u'Řešitelský článek'), ] typ = models.CharField(u'typ problému', max_length=32, choices=TYP_CHOICES, blank=False, default=TYP_ULOHA) STAV_NAVRH = 'navrh' STAV_ZADANY = 'zadany' STAV_SMAZANY = 'smazany' STAV_CHOICES = [ (STAV_NAVRH, u'Návrh'), (STAV_ZADANY, u'Zadaný'), (STAV_SMAZANY, u'Smazaný'), ] stav = models.CharField(u'stav problému', max_length=32, choices=STAV_CHOICES, blank=False, default=STAV_NAVRH) zamereni = TaggableManager(verbose_name=u'zaměření', help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True) text_org = models.TextField(u'org poznámky (HTML)', blank=True, help_text=u'Neveřejný návrh úlohy, návrh řešení, text zadání, poznámky ...') text_zadani = models.TextField(u'veřejné zadání (HTML)', blank=True, help_text=u'Veřejný text zadání (HTML)') text_reseni = models.TextField(u'veřejné řešení (HTML)', blank=True, help_text=u'Veřejný text řešení (HTML, u témat i příspěvky a komentáře)') autor = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'autor problému', related_name='autor_uloh', null=True, blank=True) opravovatel = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'opravovatel', null=True, blank=True, related_name='opravovatel_uloh') kod = models.CharField(u'lokální kód', max_length=32, blank=True, default='', help_text=u'Číslo/kód úlohy v čísle nebo kód tématu/článku/seriálu v ročníku') cislo_zadani = models.ForeignKey(Cislo, verbose_name=u'číslo zadání', blank=True, null=True, related_name=u'zadane_problemy') cislo_reseni = models.ForeignKey(Cislo, verbose_name=u'číslo řešení', blank=True, null=True, related_name=u'resene_problemy', help_text=u'Číslo s řešením úlohy, jen pro úlohy') body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name=u'maximum bodů', blank=True, null=True) timestamp = models.DateTimeField(u'vytvořeno', default=timezone.now, blank=True, editable=False) # Staré (do 2014) ID problému z DAKOSU -- jen u importovaných záznamů import_dakos_id = models.CharField(u'importované ID s typem', max_length=32, blank=True, default='', help_text=(u'ID z importu z DAKOSU s prefixem podle původu: "AZAD:xxx (MAMOPER.MM_AZAD), "' + u'"DOZ:xxx" (MAMOPER.MM_DOZ), "ZAD:rocnik.cislo.uloha.typ" (MAMOPER.MM_ZADANIA), "ULOHA:xxx" (MAMOPER.MM_ULOHY)')) def __str__(self): return force_unicode(u'%s' % (self.nazev, )) def kod_v_rocniku(self): if self.stav == 'zadany': if self.typ == self.TYP_ULOHA: return force_unicode(u"%s.u%s" % (self.cislo_zadani.cislo, self.kod,)) if self.typ == self.TYP_TEMA: return force_unicode(u"t%s" % (self.kod,)) else: return force_unicode(self.kod) return u'' def nazev_typu(self): return dict(self.TYP_CHOICES)[self.typ] def verejne(self): return (self.cislo_zadani and self.cislo_zadani.verejne()) verejne.boolean = True def verejne_url(self): return reverse('seminar_problem', kwargs={'pk': self.id}) def admin_url(self): if self.stav == Problem.STAV_ZADANY: return reverse('admin:seminar_problemzadany_change', args=(self.id, )) else: return reverse('admin:seminar_problemnavrh_change', args=(self.id, )) 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 u"({}\u2009b)".format(pocet_bodu) if self.body else "" @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Reseni(SeminarModelBase): class Meta: db_table = 'seminar_reseni' verbose_name = u'Řešení' verbose_name_plural = u'Řešení' ordering = ['problem_id', 'resitel__prijmeni', 'resitel__jmeno',] # Interní ID id = models.AutoField(primary_key = True) problem = models.ForeignKey(Problem, verbose_name=u'problém', related_name='reseni') resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', related_name='reseni') body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name=u'body', blank=True, null=True) cislo_body = models.ForeignKey(Cislo, verbose_name=u'číslo pro body', related_name='bodovana_reseni', blank=True, null=True) timestamp = models.DateTimeField(u'vytvořeno', default=timezone.now, blank=True, editable=False) FORMA_PAPIR = 'papir' FORMA_EMAIL = 'email' FORMA_UPLOAD = 'upload' FORMA_CHOICES = [ (FORMA_PAPIR, u'Papírové řešení'), (FORMA_EMAIL, u'Emailem'), (FORMA_UPLOAD, u'Upload přes web'), ] forma = models.CharField(u'forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, default=FORMA_EMAIL) poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k řešení (plain text)') def __str__(self): return force_unicode(u"%s: %s (%sb)" % (self.resitel.plne_jmeno(), self.problem.nazev, self.body)) # NOTE: Potenciální DB HOG (bez select_related) 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) # PrilohaReseni method def generate_filename(self, filename, directory): clean = filename.replace('/','-').replace('\0', '') datedir = timezone.now().strftime('%Y-%m') fname = "%s_%s" % ( timezone.now().strftime('%Y-%m-%d-%H:%M'), clean) return os.path.join(directory, datedir, fname) @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class PrilohaReseni(SeminarModelBase): class Meta: db_table = 'seminar_priloha_reseni' verbose_name = u'Příloha řešení' verbose_name_plural = u'Přílohy řešení' ordering = ['reseni', 'timestamp'] # Interní ID id = models.AutoField(primary_key = True) reseni = models.ForeignKey(Reseni, verbose_name=u'řešení', related_name='prilohy') timestamp = models.DateTimeField(u'vytvořeno', default=timezone.now, blank=True, editable=False) soubor = models.FileField(u'soubor', upload_to = partial(generate_filename,directory=settings.SEMINAR_RESENI_DIR)) poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k příloze řešení (plain text), např. o původu') def __str__(self): return force_unicode(self.soubor) @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Organizator(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name='Osoba', help_text = 'Vyber účet spřažený s organizátorem.') prezdivka = models.CharField('Přezdívka', max_length = 32, null = True, blank = True) organizuje_od_roku = models.IntegerField('Organizuje od roku', null = True, blank = True) organizuje_do_roku = models.IntegerField('Organizuje do roku', null = True, blank = True) studuje = models.CharField('Studium aj.', max_length = 256, null = True, 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'") strucny_popis_organizatora = models.TextField('Stručný popis organizátora', null = True, blank = True) foto = ProcessedImageField(verbose_name='Fotografie organizátora', upload_to='image_organizatori/velke/%Y/', null = True, blank = True, help_text = 'Vlož fotografii organizátora o libovolné velikosti', processors=[ Transpose(Transpose.AUTO), ResizeToFit(500, 500, upscale=False) ], options={'quality': 95}) foto_male = ImageSpecField(source='foto', processors=[ ResizeToFit(200, 200, upscale=False) ], options={'quality': 95}) def __str__(self): if self.prezdivka: return u"%s '%s' %s" % (self.user.first_name, self.prezdivka, self.user.last_name) else: return u"%s %s" % (self.user.first_name, self.user.last_name) class Meta: verbose_name = 'Organizátor' verbose_name_plural = 'Organizátoři' @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Soustredeni(SeminarModelBase): class Meta: db_table = 'seminar_soustredeni' verbose_name = u'Soustředění' verbose_name_plural = u'Soustředění' ordering = ['-rocnik__rocnik', '-datum_zacatku'] # Interní ID id = models.AutoField(primary_key = True) rocnik = models.ForeignKey(Rocnik, verbose_name=u'ročník', related_name='soustredeni') datum_zacatku = models.DateField(u'datum začátku', blank=True, null=True, help_text=u'První den soustředění') datum_konce = models.DateField(u'datum konce', blank=True, null=True, help_text=u'Poslední den soustředění') verejne_db = models.BooleanField(u'soustředění zveřejněno', db_column='verejne', default=False) misto = models.CharField(u'místo soustředění', max_length=256, blank=True, default='', help_text=u'Místo (název obce, volitelně též objektu') ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci soustředění', help_text=u'Seznam účastníků soustředění', through='Soustredeni_Ucastnici') organizatori = models.ManyToManyField(Organizator, verbose_name=u'Organizátoři soustředění', help_text=u'Seznam organizátorů soustředění', through='Soustredeni_Organizatori') text = models.TextField(u'text k soustředění (HTML)', blank=True, default='') TYP_JARNI = 'jarni' TYP_PODZIMNI = 'podzimni' TYP_VIKEND = 'vikend' TYP_CHOICES = [ (TYP_JARNI, u'Jarní soustředění'), (TYP_PODZIMNI, u'Podzimní soustředění'), (TYP_VIKEND, u'Víkendový sraz'), ] typ = models.CharField(u'typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI) exportovat = models.BooleanField(u'export do AESOPa', db_column='exportovat', default=False, help_text=u'Exportuje se jen podle tohoto flagu (ne veřejnosti)') def __str__(self): return force_unicode(u'%s (%s)' % (self.misto, self.datum_zacatku)) def verejne(self): return self.verejne_db verejne.boolean = True def verejne_url(self): #return reverse('seminar_soustredeni', kwargs={'pk': self.id}) return reverse('seminar_seznam_soustredeni') @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Soustredeni_Ucastnici(models.Model): class Meta: db_table = 'seminar_soustredeni_ucastnici' verbose_name = u'Účast na soustředění' verbose_name_plural = u'Účasti na soustředění' ordering = ['soustredeni', 'resitel'] # Interní ID id = models.AutoField(primary_key = True) resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel') soustredeni = models.ForeignKey(Soustredeni, verbose_name=u'soustředění') poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k účasti (plain text)') def __str__(self): return force_unicode(u'%s na %s' % (self.resitel, self.soustredeni, )) # NOTE: Poteciální DB HOG bez select_related @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Soustredeni_Organizatori(models.Model): class Meta: db_table = 'seminar_soustredeni_organizatori' verbose_name = u'Účast organizátorů na soustředění' verbose_name_plural = u'Účasti organizátorů na soustředění' ordering = ['soustredeni', 'organizator'] # Interní ID id = models.AutoField(primary_key = True) organizator = models.ForeignKey(Organizator, verbose_name=u'organizátor') soustredeni = models.ForeignKey(Soustredeni, verbose_name=u'soustředění') poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k účasti organizátora (plain text)') def __str__(self): return force_unicode(u'%s na %s' % (self.organizator, self.soustredeni, )) # NOTE: Poteciální DB HOG bez select_related @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Konfera(models.Model): class Meta: db_table = 'seminar_konfera' verbose_name = u'Konfera' verbose_name_plural = u'Konfery' # Interní ID id = models.AutoField(primary_key = True) nazev = models.CharField(u'název konfery', max_length=40, help_text = u'Název konfery') popis = models.TextField(u'popis konfery', blank=True, help_text=u'Popis konfery k zobrazení na webu') abstrakt = models.TextField(u'abstrakt', blank=True, help_text=u'Abstrakt konfery tak, jak byl uveden ve sborníku') organizator = models.ForeignKey(Organizator, verbose_name=u'organizátor', related_name='konfery', on_delete = models.SET_NULL, null=True) ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci konfery', help_text=u'Seznam účastníků konfery', through='Konfery_Ucastnici') soustredeni = models.ForeignKey(Soustredeni, verbose_name=u'soustředění', related_name='konfery', on_delete = models.SET_NULL, null=True) org_poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka ke konfeře(plain text)') #prispevek #TODO TYP_VELETRH = 'veletrh' TYP_PREZENTACE = 'prezentace' TYP_CHOICES = [ (TYP_VELETRH, u'Veletrh (postery)'), (TYP_PREZENTACE, u'Prezentace (přednáška)'), ] typ_prezentace = models.CharField(u'typ prezentace', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_VELETRH) prezentace = models.FileField(u'prezentace',help_text = u'Prezentace nebo fotka posteru', upload_to = partial(generate_filename,directory=settings.SEMINAR_KONFERY_DIR)) materialy = models.FileField(u'materialy',help_text = u'Další materiály ke konfeře zabalené do jednoho souboru', upload_to = partial(generate_filename,directory=settings.SEMINAR_KONFERY_DIR)) def __str__(self): return force_unicode(u"%s: (%s)" % (self.nazev, self.soustredeni)) @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Konfery_Ucastnici(models.Model): class Meta: db_table = 'seminar_konfery_ucastnici' verbose_name = u'Účast na konfeře' verbose_name_plural = u'Účasti na konfeře' ordering = ['konfera', 'resitel'] # Interní ID id = models.AutoField(primary_key = True) resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel') konfera = models.ForeignKey(Konfera, verbose_name=u'konfera') poznamka = models.TextField(u'neveřejná poznámka', blank=True, help_text=u'Neveřejná poznámka k účasti (plain text)') def __str__(self): return force_unicode(u'%s na %s' % (self.resitel, self.konfera, )) # NOTE: Poteciální DB HOG bez select_related @python_2_unicode_compatible class VysledkyBase(SeminarModelBase): class Meta: verbose_name = u'Řádek výsledkovky' verbose_name_plural = u'Řádky výsledkovky' ordering = ['body'] abstract = True managed = False dummy_id = models.CharField(u'dummy ID pro view', max_length=32, primary_key=True, db_column='id') cislo = models.ForeignKey(Cislo, verbose_name=u'číslo pro body', db_column='cislo_id', on_delete=models.DO_NOTHING) resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', db_column='resitel_id', on_delete=models.DO_NOTHING) body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body', verbose_name=u'body za číslo') def __str__(self): return force_unicode(u"%s: %sb (%s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo))) # NOTE: DB zatez pri vypisu (ale nepouzivany) class VysledkyZaCislo(VysledkyBase): class Meta: db_table = 'seminar_body_za_cislo' abstract = False managed = False class VysledkyKCisluZaRocnik(VysledkyBase): class Meta: db_table = 'seminar_body_k_cislu_rocnik' abstract = False managed = False # body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body', # verbose_name=u'body do čísla (za ročník)') class VysledkyKCisluOdjakziva(VysledkyBase): class Meta: db_table = 'seminar_body_k_cislu_odjakziva' abstract = False managed = False # body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body', # verbose_name=u'body do čísla (i minulé ročníky)') @python_2_unicode_compatible class VysledkyCelkemKCislu(VysledkyBase): class Meta: db_table = 'seminar_body_celkem_k_cislu' abstract = False managed = False body_celkem = models.DecimalField(max_digits=8, decimal_places=1, db_column='body_celkem', verbose_name=u'body celkem do čísla včetně minulých ročníků') def __str__(self): # NOTE: DB HOG (ale nepouzivany) return force_unicode(u"%s: %sb / %sb (do %s)" % (self.resitel.plne_jmeno(), self.body, self.body_celkem, str(self.cislo))) #mozna potreba upravit @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Nastaveni(SingletonModel): class Meta: db_table = 'seminar_nastaveni' verbose_name = u'Nastavení semináře' aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name=u'aktuální ročník', null=False) aktualni_cislo = models.ForeignKey(Cislo, verbose_name=u'poslední vydané číslo', null=False) def __str__(self): return u'Nastavení semináře' def admin_url(self): return reverse('admin:seminar_nastaveni_change', args=(self.id, )) def verejne(self): return False @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Novinky(models.Model): datum = models.DateField(auto_now_add=True) text = models.TextField('Text novinky', blank=True, null=True) obrazek = models.ImageField('Obrázek', upload_to='image_novinky/%Y/%m/%d/', null=True, blank=True) obrazek_maly = ImageSpecField(source='obrazek', processors=[ ResizeToFit(350, 200, upscale=False) ], options={'quality': 95}) autor = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='Autor novinky') zverejneno = models.BooleanField('Zveřejněno', default="False") def __str__(self): return '[' + str(self.datum) + '] ' + self.text[0:50] class Meta: verbose_name = 'Novinka' verbose_name_plural = 'Novinky'