import logging import os from django.db import models from django.urls import reverse from reversion import revisions as reversion from django.conf import settings from personalni.models import Resitel, Organizator from various.models import SeminarModelBase from tvorba.models import Rocnik, Problem, aux_generate_filename import secrets import string from django.utils import timezone def generate_filename_vcf(self, filename): return generate_filename_kontaktnicek(self, filename, 'vcf') def generate_filemane_pdf(self, filename): return generate_filename_kontaktnicek(self, filename, 'pdf') def generate_filename_kontaktnicek(self, filename, file_type): # generate random string length = 32 fname = timezone.now().strftime('%Y-%m-%d-%H_%M') + "-" fname += ''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(length)) fname += '.' + file_type return os.path.join(settings.SOUSTREDENI_KONTAKTNICKY_DIR, fname) logger = logging.getLogger(__name__) @reversion.register(ignore_duplicates=True) class Soustredeni(SeminarModelBase): class Meta: db_table = 'seminar_soustredeni' verbose_name = 'Soustředění' verbose_name_plural = 'Soustředění' ordering = ['-rocnik__rocnik', '-datum_zacatku'] # Interní ID id = models.AutoField(primary_key = True) rocnik = models.ForeignKey(Rocnik, verbose_name='ročník', related_name='soustredeni', on_delete=models.PROTECT) datum_zacatku = models.DateField('datum začátku', blank=True, null=True, help_text='První den soustředění') datum_konce = models.DateField('datum konce', blank=True, null=True, help_text='Poslední den soustředění') verejne_db = models.BooleanField('soustředění zveřejněno', db_column='verejne', default=False) misto = models.CharField('místo soustředění', max_length=256, blank=True, default='', help_text='Místo (název obce, volitelně též objektu') ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci soustředění', help_text='Seznam účastníků soustředění', through='Soustredeni_Ucastnici') organizatori = models.ManyToManyField(Organizator, verbose_name='Organizátoři soustředění', help_text='Seznam organizátorů soustředění', through='Soustredeni_Organizatori') text = models.TextField('text k soustředění (HTML)', blank=True, default='') TYP_JARNI = 'jarni' TYP_PODZIMNI = 'podzimni' TYP_VIKEND = 'vikend' TYP_VYLET = 'vylet' TYP_CHOICES = [ (TYP_JARNI, 'Jarní soustředění'), (TYP_PODZIMNI, 'Podzimní soustředění'), (TYP_VIKEND, 'Víkendový sraz'), (TYP_VYLET, 'Výlet'), ] typ = models.CharField('typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI) exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False, help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)') #using lambda to avoid circular import kontaktnicek_vcf = models.FileField('kontaktníček vcf', upload_to=generate_filename_vcf, blank=True, null=True) kontaktnicek_pdf = models.FileField('kontaktníček pdf', upload_to=generate_filemane_pdf, blank=True, null=True) def __str__(self): return '{} ({})'.format(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('soustredeni_seznam') @reversion.register(ignore_duplicates=True) class Soustredeni_Ucastnici(SeminarModelBase): # zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu class Meta: db_table = 'seminar_soustredeni_ucastnici' verbose_name = 'Účast na soustředění' verbose_name_plural = 'Účasti na soustředění' ordering = ['soustredeni', 'resitel'] # Interní ID id = models.AutoField(primary_key = True) resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', on_delete=models.PROTECT) poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k účasti (plain text)') def __str__(self): return '{} na {}'.format(self.resitel, self.soustredeni) # NOTE: Poteciální DB HOG bez select_related @reversion.register(ignore_duplicates=True) class Soustredeni_Organizatori(SeminarModelBase): # zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu class Meta: db_table = 'seminar_soustredeni_organizatori' verbose_name = 'Účast organizátorů na soustředění' verbose_name_plural = 'Účasti organizátorů na soustředění' ordering = ['soustredeni', 'organizator'] # Interní ID id = models.AutoField(primary_key = True) organizator = models.ForeignKey(Organizator, verbose_name='organizátor', on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', on_delete=models.PROTECT) poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k účasti organizátora (plain text)') def __str__(self): return '{} na {}'.format(self.organizator, self.soustredeni) # NOTE: Poteciální DB HOG bez select_related # FIXME cycle import # Django neumí jednoduše serializovat partial nebo třídu s __call__ # (https://docs.djangoproject.com/en/1.8/topics/migrations/), # neprojdou pak migrace. Takže rozlišení funkcí generujících názvy souboru # podle adresáře řešíme takto. ## def generate_filename_konfera(self, filename): return os.path.join( settings.SEMINAR_KONFERY_DIR, aux_generate_filename(self, filename) ) ## @reversion.register(ignore_duplicates=True) class Konfera(Problem): class Meta: db_table = 'seminar_konfera' verbose_name = 'Konfera' verbose_name_plural = 'Konfery' anotace = models.TextField('anotace', blank=True, help_text='Popis, o čem bude konfera.') abstrakt = models.TextField('abstrakt', blank=True, help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') # FIXME: Umíme omezit jen na účastníky daného soustřeďka? ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', related_name='konfery', on_delete = models.SET_NULL, null=True) TYP_VELETRH = 'veletrh' TYP_PREZENTACE = 'prezentace' TYP_CHOICES = [ (TYP_VELETRH, 'Veletrh (postery)'), (TYP_PREZENTACE, 'Prezentace (přednáška)'), ] typ_prezentace = models.CharField('typ prezentace', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_VELETRH) prezentace = models.FileField('prezentace',help_text = 'Prezentace nebo fotka posteru', upload_to = generate_filename_konfera, blank=True) materialy = models.FileField('materialy', help_text = 'Další materiály ke konfeře zabalené do jednoho souboru', upload_to = generate_filename_konfera, blank=True) def __str__(self): return "{}: ({})".format(self.nazev, self.soustredeni) def cislo_node(self): return None @reversion.register(ignore_duplicates=True) class Konfery_Ucastnici(models.Model): class Meta: db_table = 'seminar_konfery_ucastnici' verbose_name = 'Účast na konfeře' verbose_name_plural = 'Účasti na konfeře' ordering = ['konfera', 'resitel'] # Interní ID id = models.AutoField(primary_key = True) resitel = models.ForeignKey(Resitel, verbose_name='řešitel', on_delete=models.PROTECT) konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE) poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k účasti (plain text)') def __str__(self): return '{} na {}'.format(self.resitel, self.konfera) # NOTE: Poteciální DB HOG bez select_related