@ -12,6 +12,10 @@ from django.utils.text import slugify
from django . core . urlresolvers import reverse
from django . core . cache import cache
from PIL import Image
import os
from cStringIO import StringIO
from django . core . files . base import ContentFile
from django_countries . fields import CountryField
from solo . models import SingletonModel
@ -29,12 +33,6 @@ class SeminarModelBase(models.Model):
def verejne ( self ) :
return False
# def public_url(self):
# if self.Meta.url_name:
# return reverse(self.Meta.url_name,
# kwargs={'id': self.id, 'pk': self.id})
# return None
def get_absolute_url ( self ) :
return self . verejne_url ( ) # TODO "absolute"
@ -188,6 +186,30 @@ class Resitel(SeminarModelBase):
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 ,
# 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 ' ,
}
@reversion . register ( ignore_duplicate_revisions = True )
@python_2_unicode_compatible
@ -202,18 +224,15 @@ class Rocnik(SeminarModelBase):
# Interní ID
id = models . AutoField ( primary_key = True )
prvni_rok = models . IntegerField ( u ' první rok ' )
prvni_rok = models . IntegerField ( u ' první rok ' , db_index = True , unique = True )
rocnik = models . Cha rField( u ' číslo ročníku ' , max_length = 16 )
rocnik = models . Intege rField( u ' číslo ročníku ' , db_index = True , unique = True )
def __str__ ( self ) :
return force_unicode ( u ' %s ( %d / %d ) ' % ( self . rocnik , self . prvni_rok , self . prvni_rok + 1 ) )
def roman ( self ) :
if self . rocnik . isdigit ( ) :
return force_unicode ( roman ( int ( self . rocnik ) ) )
else :
return force_unicode ( self . rocnik )
def verejne ( self ) :
return len ( self . verejna_cisla ( ) ) > 0
@ -232,7 +251,7 @@ class Rocnik(SeminarModelBase):
return self . prvni_rok + 1
def verejne_url ( self ) :
return reverse ( ' seminar_rocnik ' , kwargs = { ' p k' : self . id } )
return reverse ( ' seminar_rocnik ' , kwargs = { ' rocni k' : self . rocnik } )
@classmethod
def cached_rocnik ( cls , r_id ) :
@ -258,9 +277,9 @@ class Cislo(SeminarModelBase):
# Interní ID
id = models . AutoField ( primary_key = True )
rocnik = models . ForeignKey ( Rocnik , verbose_name = u ' ročník ' , related_name = ' cisla ' )
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 ,
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čije pořadí v ročníku! ' )
datum_vydani = models . DateField ( u ' datum vydání ' , blank = True , null = True ,
@ -271,6 +290,9 @@ class Cislo(SeminarModelBase):
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) ' )
@ -288,7 +310,7 @@ class Cislo(SeminarModelBase):
verejne . boolean = True
def verejne_url ( self ) :
return reverse ( ' seminar_cislo ' , kwargs = { ' p k ': self . id } )
return reverse ( ' seminar_cislo ' , kwargs = { ' rocnik ' : self . rocni k. rocnik , ' cislo ': self . cislo } )
def nasledujici ( self ) :
u " Vrací None, pokud je toto poslední "
@ -370,7 +392,7 @@ class Problem(SeminarModelBase):
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 . IntegerField ( u ' maximum bodů ' , blank = True , null = True )
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 )
@ -411,7 +433,7 @@ class Reseni(SeminarModelBase):
db_table = ' seminar_reseni '
verbose_name = u ' Řešení '
verbose_name_plural = u ' Řešení '
ordering = [ ' problem_id ' , ' resitel_id ' ]
ordering = [ ' problem_id ' , ' resitel__prijmeni ' , ' resitel__jmeno ' , ]
# Interní ID
id = models . AutoField ( primary_key = True )
@ -420,7 +442,7 @@ class Reseni(SeminarModelBase):
resitel = models . ForeignKey ( Resitel , verbose_name = u ' řešitel ' , related_name = ' reseni ' )
body = models . IntegerField ( u ' body ' , blank = True , null = True )
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 )
@ -443,6 +465,12 @@ class Reseni(SeminarModelBase):
return force_unicode ( u " %s : %s ( %s b) " % ( 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 ) :
@ -562,7 +590,8 @@ class VysledkyBase(SeminarModelBase):
resitel = models . ForeignKey ( Resitel , verbose_name = u ' řešitel ' , db_column = ' resitel_id ' , on_delete = models . DO_NOTHING )
body = models . IntegerField ( u ' body za číslo ' , db_column = ' body ' )
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 : %s b ( %s ) " % ( self . resitel . plne_jmeno ( ) , self . body , str ( self . cislo ) ) )
@ -589,7 +618,8 @@ class VysledkyKCislu(VysledkyBase):
abstract = False
managed = False
body_celkem = models . IntegerField ( u ' body celkem do čísla ' , db_column = ' body_celkem ' )
body_celkem = models . DecimalField ( max_digits = 8 , decimal_places = 1 , db_column = ' body_celkem ' ,
verbose_name = u ' body celkem do čísla ' )
def __str__ ( self ) :
# NOTE: DB HOG (ale nepouzivany)
@ -616,3 +646,88 @@ class Nastaveni(SingletonModel):
def verejne ( self ) :
return False
@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 )
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 '
@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 ( ' Studuje ' , max_length = 256 ,
null = True , blank = True )
strucny_popis_organizatora = models . TextField ( ' Stručný popis organizátora ' ,
null = True , blank = True )
foto = models . ImageField ( ' Fotografie organizátora ' ,
upload_to = ' image_organizatori/velke/ % Y/ ' , null = True , blank = True ,
help_text = ' Vlož fotografii organizátora o libovoné velikosti ' )
foto_male = models . ImageField ( upload_to = ' image_organizatori/male/ % Y/ ' ,
null = True , blank = True , editable = False )
def __str__ ( self ) :
return str ( self . user )
class Meta :
verbose_name = ' Organizátor '
verbose_name_plural = ' Organizátoři '
def save ( self ) :
if self . foto :
original = Image . open ( self . foto )
jmeno = os . path . basename ( self . foto . file . name )
Organizator . _vyrobMiniaturu ( original , jmeno , 500 , self . foto )
Organizator . _vyrobMiniaturu ( original , jmeno , 200 , self . foto_male )
super ( Organizator , self ) . save ( )
@staticmethod
def _vyrobMiniaturu ( original , jmeno , maximum , field ) :
zmensenina = Organizator . _zmensiObrazek ( original , maximum )
f = StringIO ( )
try :
zmensenina . save ( f , format = original . format )
data = ContentFile ( f . getvalue ( ) )
finally :
f . close ( )
field . save ( jmeno , data , save = False )
@staticmethod
def _zmensiObrazek ( original , maximum ) :
""" Preskaluje obrazek tak, aby byl zachovan pomer stran
a zadny rozmer nepresahoval maxRozmer . Pokud zadny rozmer
nepresahuje maxRozmer , tak vrati puvodni obrazek
( tj . nedojde ke zvetseni obrazku ) . """
novaVelikost = Organizator . _zmensiVelikost ( original . size , maximum )
return original . resize ( novaVelikost , Image . ANTIALIAS )
@staticmethod
def _zmensiVelikost ( velikost , maximum ) :
maximum = float ( maximum )
w , h = velikost
soucasneMaximum = max ( w , h )
if soucasneMaximum < = maximum :
return velikost
pomer = maximum / soucasneMaximum
return ( int ( w * pomer ) , int ( h * pomer ) )