import os from django.db import models from django.urls import reverse from django.utils import timezone from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.utils.functional import cached_property from django.utils.text import get_valid_filename from personalni.models import Organizator import subprocess from reversion import revisions as reversion from unidecode import unidecode def generate_filename(self, filename): """ vyrobí jméno souboru podle původního jména a času nahrátí """ clean = get_valid_filename( unidecode( filename.replace('/', '-').replace('\0', '').replace(":", "_") ) ) fname = "%s_%s" % ( timezone.now().strftime('%Y-%m-%d-%H_%M'), clean) return os.path.join(settings.KOREKTURY_PDF_DIR, fname) #@reversion.register(ignore_duplicates=True) class KorekturovanePDF(models.Model): class Meta: ordering = ['-cas'] db_table = 'korekturovane_cislo' verbose_name = u'PDF k opravám' verbose_name_plural = u'PDF k opravám' #Interní ID id = models.AutoField(primary_key = True) cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF') nazev = models.CharField(u'název PDF',blank = False,max_length=50, help_text='Název (např. `22.1 | analyza v4` nebo `propagace | letacek v0`) korekturovaného PDF') komentar = models.TextField(u'komentář k PDF',blank = True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)') pdf = models.FileField(u'PDF', upload_to = generate_filename) orgove = models.ManyToManyField(Organizator, blank=True, help_text='Zodpovědní organizátoři za obsah (chodí jim maily o nových korekturách)', default=None) stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF', default=0) class STATUS(models.TextChoices): PRIDAVANI = 'pridavani', 'Přidávání korektur' ZANASENI = 'zanaseni', 'Korektury jsou zanášeny' ZASTARALE = 'zastarale', 'Stará verze, nekorigovat' status = models.CharField(u'stav PDF',max_length=16, choices=STATUS.choices, blank=False, default = STATUS.PRIDAVANI) poslat_mail = models.BooleanField('Poslat mail o novém PDF', default=True, help_text='Určuje, zda se má o nově nahraném PDF poslat e-mail do mam-org. Při upravování existujícího souboru už nemá žádný vliv.', ) #TODO Nepovinný foreign key k číslu def get_prefix(self): """Vrať řetězec, ke kterému se připojí číslo a .png""" # vrátíme jméno souboru bez cesty return os.path.basename(self.pdf.file.name) def convert(self): """Vytvoří jedno png za každou stranu pdf a uloží se""" dirname = os.path.join(settings.MEDIA_ROOT, settings.KOREKTURY_IMG_DIR) if not os.path.exists(dirname): os.mkdir(dirname) self.stran = 0 while True: res = subprocess.call([ #Parametry inspirovány chybovou hláškou imagemagicku "gs", "-sstdout=%stderr", "-dSAFER", "-dNOPAUSE", "-dBATCH", "-dNOPROMPT", "-sDEVICE=pngalpha", "-r180x180", "-dFirstPage=%d" % (self.stran+1), "-dLastPage=%d" % (self.stran+1), "-sOutputFile="+os.path.join( dirname, "%s-%d.png" % (self.get_prefix(), self.stran)), "-f%s" % (self.pdf.path) ]) if not os.path.exists(os.path.join( dirname, "%s-%d.png" % (self.get_prefix(), self.stran))): break self.stran += 1 # Změnil se počet stran, ukládáme super(KorekturovanePDF, self).save() def save(self, **kwargs): # Pokud se nezmenilo PDF, tak nepregenerovavej nahledy try: original = KorekturovanePDF.objects.get(pk=self.pk) if original.pdf == self.pdf: super(KorekturovanePDF, self).save() return except ObjectDoesNotExist: pass # uložíme nahrávané pdf super(KorekturovanePDF, self).save(kwargs) # uložíme png a změněný počet stran self.convert() @cached_property def cislo_a_tema(self): nazev_split = self.nazev.split() try: return nazev_split[0] # + " " + nazev_split[2] except IndexError: return self.nazev def get_absolute_url(self): return reverse('korektury', kwargs={'pdf': self.id}) @reversion.register(ignore_duplicates=True) class Oprava(models.Model): class Meta: db_table = 'opravy' verbose_name = u'Oprava' verbose_name_plural = u'Opravy' ordering = ['y','x'] #Interní ID id = models.AutoField(primary_key = True) pdf = models.ForeignKey(KorekturovanePDF, default=-1, on_delete=models.PROTECT) strana = models.IntegerField(u'strana s opravou', help_text='Strana s opravou (od 0)') x = models.IntegerField(u'x-ová souřadnice bugu') y = models.IntegerField(u'y-ová souřadnice bugu') class STATUS(models.TextChoices): K_OPRAVE = 'k_oprave', 'K opravě' OPRAVENO = 'opraveno', 'Opraveno' NENI_CHYBA = 'neni_chyba', 'Není chyba' K_ZANESENI = 'k_zaneseni', 'K zanesení do TeXu' status = models.CharField(u'stav opravy',max_length=16, choices=STATUS.choices, blank=False, default = STATUS.K_OPRAVE) @reversion.register(ignore_duplicates=True) class Komentar(models.Model): class Meta: db_table = 'komentare' verbose_name = u'Komentář k opravě' verbose_name_plural = u'Komentáře k opravě' ordering = ['cas'] #Interní ID id = models.AutoField(primary_key = True) cas = models.DateTimeField(u'čas komentáře',default=timezone.now,help_text = 'Čas zadání komentáře') oprava = models.ForeignKey(Oprava, on_delete=models.CASCADE) autor = models.ForeignKey(Organizator, blank = True, help_text = u'Autor komentáře', null = True, on_delete=models.SET_NULL) text = models.TextField(u'text komentáře',blank = True, help_text='Text komentáře') def __str__(self): return '{} od {}: {}'.format(self.cas,self.autor,self.text)