207 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import os
 | |
| 
 | |
| from colorfield.fields import ColorField
 | |
| 
 | |
| 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 = 'PDF ke korekturování'
 | |
| 		verbose_name_plural = 'PDFka ke korekturování'
 | |
| 	
 | |
| 	#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ř. „42.6 | analýza v4“ nebo „propagace | letáček v0“) korekturovaného PDF, v seznamu se seskupují podle textu do první mezery, tedy zde „42.6“ respektive „propagace“.')
 | |
| 
 | |
| 	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})
 | |
| 
 | |
| 
 | |
| class KorekturaTag(models.Model):
 | |
| 	nazev = models.CharField("název tagu", blank = False, max_length=20, help_text="Název daného tagu, <20 znaků")
 | |
| 	barva = ColorField("barva daného tagu", default="#FFFFFF")
 | |
| 
 | |
| 	def __str__(self):
 | |
| 		return self.nazev
 | |
| 
 | |
| 
 | |
| @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)
 | |
| 
 | |
| 	informovani_orgove = models.ManyToManyField(
 | |
| 		Organizator, blank=True, default=None,
 | |
| 		verbose_name='Informovaní organizátoři',
 | |
| 		help_text="Orgové informovaní při přidání komentáře ke korektuře",
 | |
| 		related_name='informovan_o_opravach',
 | |
| 	)
 | |
| 
 | |
| 	tagy = models.ManyToManyField(KorekturaTag, blank=True, default=None,)
 | |
| 
 | |
| 
 | |
| @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)
 | |
| 
 | |
| 	def save(self, *args, **kwargs):
 | |
| 		super().save(*args, **kwargs)
 | |
| 		if self.autor is not None:
 | |
| 			self.oprava.informovani_orgove.add(self.autor)
 |