Merge branch 'master' into stable
This commit is contained in:
		
						commit
						ff7f52c85d
					
				
					 23 changed files with 362 additions and 301 deletions
				
			
		|  | @ -3,6 +3,9 @@ | |||
| from galerie.models import Obrazek, Galerie | ||||
| from django.contrib import admin | ||||
| from django.http import HttpResponseRedirect | ||||
| from django import forms | ||||
| from django.db import models | ||||
| import autocomplete_light | ||||
| 
 | ||||
| # akction | ||||
| 
 | ||||
|  | @ -27,17 +30,25 @@ def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): | |||
|             'Přepnout do režimu úprav (zneveřejní galerii)' | ||||
| 
 | ||||
| class GalerieInline(admin.TabularInline): | ||||
|   model = Obrazek | ||||
|     model = Obrazek | ||||
|     fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag'] | ||||
|     readonly_fields = ['nazev', 'obrazek_maly_tag'] | ||||
|     formfield_overrides = { | ||||
|         models.TextField: {'widget': forms.TextInput}, | ||||
|     } | ||||
| 
 | ||||
| class ObrazekAdmin(admin.ModelAdmin): | ||||
|   list_display = ('obrazek_velky', 'nazev', 'popis') | ||||
|     list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag') | ||||
|    | ||||
| class GalerieAdmin(admin.ModelAdmin):  | ||||
|   model = Galerie | ||||
|   fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni', 'poradi') | ||||
|   list_display = ('nazev', 'pk', 'datum_zmeny', 'zobrazit', 'soustredeni') | ||||
|   inlines = [GalerieInline] | ||||
|   actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu] | ||||
| class GalerieAdmin(admin.ModelAdmin): | ||||
|     form = autocomplete_light.modelform_factory(Galerie, autocomplete_fields=['titulni_obrazek'], fields=['titulni_obrazek']) | ||||
|     model = Galerie | ||||
|     fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni', 'poradi') | ||||
|     list_display = ('nazev', 'pk', 'poradi', 'datum_zmeny', 'zobrazit', 'soustredeni') | ||||
|     inlines = [GalerieInline] | ||||
|     actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu] | ||||
|     save_on_top = True | ||||
|     ordering = ['galerie_up__nazev', 'poradi'] | ||||
| 
 | ||||
| admin.site.register(Obrazek, ObrazekAdmin) | ||||
| admin.site.register(Galerie, GalerieAdmin) | ||||
|  |  | |||
							
								
								
									
										49
									
								
								galerie/autocomplete_light_registry.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								galerie/autocomplete_light_registry.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| import autocomplete_light | ||||
| 
 | ||||
| from models import Obrazek, Galerie | ||||
| from views import cesta_od_korene | ||||
| 
 | ||||
| 
 | ||||
| class ObrazekAutocomplete(autocomplete_light.AutocompleteModelBase): | ||||
| 
 | ||||
|     model = Obrazek | ||||
|     search_fields = ['nazev', 'popis'] | ||||
|     split_words = True | ||||
|     limit_choices = 15 | ||||
|     attrs = { | ||||
|         # This will set the input placeholder attribute: | ||||
|         'placeholder': u'Obrázek', | ||||
|         # This will set the yourlabs.Autocomplete.minimumCharacters | ||||
|         # options, the naming conversion is handled by jQuery | ||||
|         'data-autocomplete-minimum-characters': 1, | ||||
|     } | ||||
| 
 | ||||
|     choice_html_format = ''' | ||||
|         <span class="block" data-value="{}"> | ||||
|             <span class="block"> | ||||
|                 {} | ||||
|                 <span class="block">{}</span> | ||||
|             </span> | ||||
|         </span> | ||||
|     ''' | ||||
| 
 | ||||
|     def choice_label(self, obrazek): | ||||
|         cesta = "/".join(g.nazev for g in cesta_od_korene(obrazek.galerie)) | ||||
|         popis = "{}<br>".format(obrazek.popis) if obrazek.popis else "" | ||||
|         return '{}<br>{}{}'.format(obrazek.nazev, popis, cesta) | ||||
| 
 | ||||
|     def choice_html(self, obrazek): | ||||
|         """Vrátí kus html i s obrázkem, které se pak ukazuje v nabídce""" | ||||
|         return self.choice_html_format.format(self.choice_value(obrazek), | ||||
|             obrazek.obrazek_maly_tag(), self.choice_label(obrazek)) | ||||
| 
 | ||||
|     widget_attrs={ | ||||
|         'data-widget-maximum-values': 15, | ||||
|         'class': 'modern-style', | ||||
|     } | ||||
| 
 | ||||
| autocomplete_light.register(ObrazekAutocomplete) | ||||
							
								
								
									
										22
									
								
								galerie/migrations/0006_django_imagekit.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								galerie/migrations/0006_django_imagekit.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from django.db import models, migrations | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('galerie', '0005_obrazek_ordering_datum'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.RemoveField( | ||||
|             model_name='obrazek', | ||||
|             name='obrazek_maly', | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='obrazek', | ||||
|             name='obrazek_stredni', | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										22
									
								
								galerie/migrations/0007_obrazek_odstranen_datum.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								galerie/migrations/0007_obrazek_odstranen_datum.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from django.db import models, migrations | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('galerie', '0006_django_imagekit'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterModelOptions( | ||||
|             name='obrazek', | ||||
|             options={'ordering': ['nazev'], 'verbose_name': 'Obr\xe1zek', 'verbose_name_plural': 'Obr\xe1zky'}, | ||||
|         ), | ||||
|         migrations.RemoveField( | ||||
|             model_name='obrazek', | ||||
|             name='datum', | ||||
|         ), | ||||
|     ] | ||||
|  | @ -1,17 +1,12 @@ | |||
| # coding: utf-8 | ||||
| 
 | ||||
| from django.db import models | ||||
| import seminar.models | ||||
| from django.db.models import Q | ||||
| from django.utils import timezone | ||||
| #from django.db.models import Q | ||||
| from django.utils.encoding import force_unicode | ||||
| from imagekit.models import ImageSpecField | ||||
| from imagekit.processors import ResizeToFit, Transpose | ||||
| 
 | ||||
| from PIL import Image | ||||
| from PIL.ExifTags import TAGS | ||||
| import os | ||||
| from cStringIO import StringIO | ||||
| from django.core.files.base import ContentFile | ||||
| from datetime import datetime | ||||
| 
 | ||||
| from seminar.models import Soustredeni | ||||
| 
 | ||||
|  | @ -24,120 +19,49 @@ VIDITELNOST = ( | |||
|     (NIKDY, 'Nikdy'), | ||||
| ) | ||||
| 
 | ||||
| def get_exif(fn): | ||||
|     ret = {} | ||||
|     info = fn._getexif() | ||||
|     for tag, value in info.items(): | ||||
|         decoded = TAGS.get(tag, tag) | ||||
|         ret[decoded] = value | ||||
|     return ret | ||||
| 
 | ||||
| def flip_horizontal(im): return im.transpose(Image.FLIP_LEFT_RIGHT) | ||||
| def flip_vertical(im): return im.transpose(Image.FLIP_TOP_BOTTOM) | ||||
| def rotate_180(im): return im.transpose(Image.ROTATE_180) | ||||
| def rotate_90(im): return im.transpose(Image.ROTATE_90) | ||||
| def rotate_270(im): return im.transpose(Image.ROTATE_270) | ||||
| def transpose(im): return rotate_90(flip_horizontal(im)) | ||||
| def transverse(im): return rotate_90(flip_vertical(im)) | ||||
| orientation_funcs = [None, | ||||
|                  lambda x: x, | ||||
|                  flip_horizontal, | ||||
|                  rotate_180, | ||||
|                  flip_vertical, | ||||
|                  transpose, | ||||
|                  rotate_270, | ||||
|                  transverse, | ||||
|                  rotate_90 | ||||
|                 ] | ||||
| 
 | ||||
| # tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují | ||||
| # až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat | ||||
| def obrazek_filename_maly(): | ||||
|     pass | ||||
| def obrazek_filename_stredni(): | ||||
|     pass | ||||
| def obrazek_filename_velky(): | ||||
|     pass | ||||
| 
 | ||||
| def obrazek_filename(self, filename): | ||||
|     return obrazek_filename_obecny(self, filename, "velky") | ||||
| 
 | ||||
| def obrazek_filename_stredni(self, filename): | ||||
|     return obrazek_filename_obecny(self, filename, "stredni") | ||||
| 
 | ||||
| def obrazek_filename_maly(self, filename): | ||||
|     return obrazek_filename_obecny(self, filename, "maly") | ||||
| 
 | ||||
| def obrazek_filename_obecny(self, filename, typ): | ||||
|     gal = self.galerie | ||||
|     cislo_gal = force_unicode(gal.pk) | ||||
|     cesta = "" | ||||
|     while(not gal.soustredeni): | ||||
|         gal = gal.galerie_up | ||||
|     return os.path.join('Galerie', "soustredeni_" + force_unicode(gal.soustredeni.pk), "galerie_" + cislo_gal, typ, force_unicode(self.nazev)) | ||||
|     return os.path.join('Galerie', "soustredeni_" + force_unicode(gal.soustredeni.pk), "galerie_" + cislo_gal, "velky", force_unicode(self.nazev)) | ||||
| 
 | ||||
| class Obrazek(models.Model): | ||||
|   obrazek_velky = models.ImageField(upload_to=obrazek_filename, | ||||
|     help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") | ||||
|   obrazek_stredni = models.ImageField(upload_to=obrazek_filename_stredni, null = True, editable = False) | ||||
|   obrazek_maly = models.ImageField(upload_to=obrazek_filename_maly, null = True, editable = False) | ||||
|   obrazek_stredni = ImageSpecField(source='obrazek_velky', | ||||
|                                 processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], | ||||
|                                 options={'quality': 95}) | ||||
|   obrazek_maly = ImageSpecField(source='obrazek_velky', | ||||
|                                 processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], | ||||
|                                 options={'quality': 95}) | ||||
|   nazev = models.CharField('Název', max_length=50, blank = True, null = True) | ||||
|   popis = models.TextField('Popis', blank = True, null = True) | ||||
|   datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add = True) | ||||
|   datum = models.DateTimeField('Datum pořízení fotografie', blank = True, null = True) | ||||
|   galerie = models.ForeignKey('Galerie', blank=True, null=True) | ||||
|   poradi = models.IntegerField('Pořadí', blank = True, null = True) | ||||
|   def __unicode__(self): | ||||
|     return self.nazev + " -- " + unicode(self.obrazek_velky.name) + " (" + str(self.datum) + ")" | ||||
|     return self.nazev + " -- " + unicode(self.obrazek_velky.name) | ||||
|   class Meta: | ||||
|     verbose_name = 'Obrázek' | ||||
|     verbose_name_plural = 'Obrázky' | ||||
|     ordering = ['datum'] | ||||
|   def save(self): | ||||
|     original = Image.open(self.obrazek_velky) | ||||
|     # vycteni EXIFu | ||||
|     exif = get_exif(original) | ||||
|     # otoceni podle EXIFu | ||||
|     if exif['Orientation']: | ||||
|         f = orientation_funcs[exif['Orientation']] | ||||
|         original_otoceny = f(original) | ||||
|         original_otoceny.format = original.format | ||||
|         original = original_otoceny | ||||
|     # datum podle EXIfu | ||||
|     if exif['DateTimeOriginal']: | ||||
|         datum_string = ":".join(exif['DateTimeOriginal'].split(' ')).split(":") | ||||
|         datum_int = [] | ||||
|         for retezec in datum_string: | ||||
|             datum_int.append(int(retezec)) | ||||
|         self.datum = datetime(datum_int[0], datum_int[1], datum_int[2], | ||||
|                               datum_int[3], datum_int[4], datum_int[5]) | ||||
|     jmeno = os.path.basename(self.obrazek_velky.file.name) | ||||
|     if not self.obrazek_stredni: | ||||
|       Obrazek._vyrobMiniaturu(original, jmeno, 1024, self.obrazek_stredni) | ||||
|     if not self.obrazek_maly: | ||||
|       Obrazek._vyrobMiniaturu(original, jmeno, 200, self.obrazek_maly) | ||||
|     super(Obrazek, self).save() | ||||
|     ordering = ['nazev'] | ||||
| 
 | ||||
|   @staticmethod | ||||
|   def _vyrobMiniaturu(original, jmeno, maximum, field): | ||||
|     zmensenina = Obrazek._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 = Obrazek._zmensiVelikost(original.size, maximum) | ||||
|     return original.resize(novaVelikost, Image.ANTIALIAS) | ||||
|   def obrazek_maly_tag(self): | ||||
|     return u'<img src="{}">'.format(self.obrazek_maly.url) | ||||
|   obrazek_maly_tag.short_description = "Náhled" | ||||
|   obrazek_maly_tag.allow_tags = True | ||||
| 
 | ||||
|   @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)) | ||||
|    | ||||
| 
 | ||||
| class Galerie(models.Model): | ||||
|  |  | |||
|  | @ -6,6 +6,10 @@ Galerie {{galerie.nazev}} | |||
| 
 | ||||
| {% block content %} | ||||
| 
 | ||||
|   {% if galerie.zobrazit > 0 %} | ||||
|     <div class="mam-org-only"> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   <h2> | ||||
|     {% for g in cesta %} | ||||
|       {% if not forloop.last %} | ||||
|  | @ -19,7 +23,7 @@ Galerie {{galerie.nazev}} | |||
|   {% if not obrazky %} | ||||
|    <div class="galerie_hlavicka"> | ||||
|     {% if galerie.titulni_obrazek %} | ||||
|       <img src="{{ galerie.titulni_obrazek.obrazek_stredni.url }}" style="border: 1px solid black;"> | ||||
|       <img src="{{ galerie.titulni_obrazek.obrazek_stredni.url }}" class="titulni_obrazek"> | ||||
|     {% endif %} | ||||
|    </div> | ||||
|   {% endif %} | ||||
|  | @ -45,8 +49,8 @@ Galerie {{galerie.nazev}} | |||
|             {% if galerie.titulni_obrazek %} | ||||
|             {% with galerie.titulni_obrazek.obrazek_maly as obrazek %} | ||||
|             <img src="{{ obrazek.url }}" | ||||
|                 width={% widthratio obrazek.width 200 167 %} | ||||
|                 height={% widthratio obrazek.height 200 167 %} /> | ||||
|                 width="{% widthratio obrazek.width 167 obrazek.width %}" | ||||
|                 height="{% widthratio obrazek.width 167 obrazek.height %}" /> | ||||
|             {% endwith %} | ||||
|             {% endif %} | ||||
|             <div> | ||||
|  | @ -76,8 +80,8 @@ Galerie {{galerie.nazev}} | |||
|     {% for obrazek in obrazky %} | ||||
|         <a title="Zobrazit tuto fotografii" href="./{{obrazek.pk}}#nahoru" class="galerie_nahled"><span class="vystredeno"></span><img | ||||
|             src="{{obrazek.obrazek_maly.url}}" | ||||
|             width={% widthratio obrazek.obrazek_maly.width 200 167 %} | ||||
|             height={% widthratio obrazek.obrazek_maly.height 200 167 %} /> | ||||
|             width="{{ obrazek.obrazek_maly.width }}" | ||||
|             height="{{ obrazek.obrazek_maly.height }}" /> | ||||
|         </a> | ||||
|     {% endfor %} | ||||
|     <br> | ||||
|  | @ -103,4 +107,9 @@ Galerie {{galerie.nazev}} | |||
|       </div> | ||||
|     {% endif %} | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if galerie.zobrazit > 0 %} | ||||
|     </div> {# mam-org-only #} | ||||
|   {% endif %} | ||||
| 
 | ||||
| {% endblock content %} | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ def nahled(request, pk, soustredeni): | |||
|     if not request.user.is_staff: | ||||
|         podgalerie = podgalerie.filter(zobrazit__lt=1) | ||||
| 
 | ||||
|     obrazky = Obrazek.objects.filter(galerie = galerie).order_by('datum') | ||||
|     obrazky = Obrazek.objects.filter(galerie = galerie) | ||||
|     preview = zobrazit(galerie, request) | ||||
| 
 | ||||
|     sourozenci = [] | ||||
|  | @ -82,7 +82,7 @@ def detail(request, pk, fotka, soustredeni): | |||
|   galerie = get_object_or_404(Galerie, pk=pk) | ||||
|   preview = zobrazit(galerie, request) | ||||
|   obrazek = get_object_or_404(Obrazek, pk=fotka) | ||||
|   obrazky = galerie.obrazek_set.all().order_by('datum') | ||||
|   obrazky = galerie.obrazek_set.all() | ||||
| 
 | ||||
|   # vytvoreni a obslouzeni formulare | ||||
|   if request.method == 'POST': | ||||
|  |  | |||
|  | @ -111,6 +111,8 @@ INSTALLED_APPS = ( | |||
|     'django.contrib.flatpages', | ||||
|     'django.contrib.humanize', | ||||
| 
 | ||||
|     'imagekit', | ||||
| 
 | ||||
|     # MaMweb | ||||
|     'mamweb', | ||||
|     'seminar', | ||||
|  | @ -155,6 +157,7 @@ CKEDITOR_IMAGE_BACKEND = 'pillow' | |||
| #CKEDITOR_JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js' | ||||
| CKEDITOR_CONFIGS = { | ||||
|     'default': { | ||||
|         'entities': False, | ||||
|         'toolbar': [ | ||||
|             ['Source', 'ShowBlocks', '-', 'Maximize'], | ||||
|             ['Bold', 'Italic', 'Subscript', 'Superscript', '-', 'RemoveFormat'], | ||||
|  | @ -233,12 +236,3 @@ LOGGING = { | |||
| # MaM specific | ||||
| 
 | ||||
| SEMINAR_RESENI_DIR = os.path.join(BASE_DIR, 'media', 'reseni') | ||||
| 
 | ||||
| 
 | ||||
| CKEDITOR_CONFIGS = { | ||||
|     'default': { | ||||
|         'entities': False | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ ADMINS = [ | |||
|         ('Petr Pecha', 'nejlepsitextovyeditorjevim@gmail.com'), | ||||
|         ('Tomas Gavenciak', 'gavento@gmail.com'), | ||||
|         ('Matěj Kocián', 'matej.kocian@gmail.com'), | ||||
|         ('M&M ERRORs', 'mam-errors@atrey.karlin.mff.cuni.cz'), | ||||
|         ] | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ import os | |||
| SERVER_EMAIL = 'mamweb-test-errors@mam.mff.cuni.cz' | ||||
| ADMINS = [ | ||||
|     ('Petr Pecha', 'nejlepsitextovyeditorjevim@gmail.com'), | ||||
|     ('M&M ERRORs', 'mam-errors@atrey.karlin.mff.cuni.cz'), | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,6 +18,15 @@ body { | |||
|   border: orange 2px dashed; | ||||
| } | ||||
| 
 | ||||
| .mam-org-only .mam-org-only { | ||||
|     border: 0px; | ||||
| } | ||||
| 
 | ||||
| li.mam-org-only { | ||||
|     padding: 3px 0px; | ||||
|     margin: -2px 0px; | ||||
| } | ||||
| 
 | ||||
| table .border-r { | ||||
|   border-right: solid 1px; | ||||
| } | ||||
|  | @ -437,7 +446,7 @@ div.zadani_azad_termin { | |||
|     float: none; | ||||
|     width: 70%; | ||||
|     margin-left: auto; | ||||
|     margin-right: auto | ||||
|     margin-right: auto; | ||||
|      | ||||
|   } | ||||
| } | ||||
|  | @ -446,7 +455,8 @@ div.zadani_azad_termin { | |||
| /* galerie */ | ||||
| 
 | ||||
| /* velká fotka */ | ||||
| .galerie .obrazek { | ||||
| /* zmenšování spolu s oknem prohlížeče */ | ||||
| .galerie .obrazek, .titulni_obrazek { | ||||
|     max-width: 100%; | ||||
|     height: auto; | ||||
|     width: auto\9; /* ie8 */ | ||||
|  | @ -482,7 +492,6 @@ div.zadani_azad_termin { | |||
| .galerie { | ||||
|   position: relative; | ||||
|   text-align: center; | ||||
|   /*width: 100%;*/ | ||||
|   margin: 20px auto 0 auto; | ||||
| } | ||||
| 
 | ||||
|  | @ -503,6 +512,11 @@ div.zadani_azad_termin { | |||
|   text-align: center; | ||||
| } | ||||
| 
 | ||||
| /* titulní obrázek hlavní galerie soustředění */ | ||||
| .titulni_obrazek { | ||||
|     border: 1px solid black; | ||||
| } | ||||
| 
 | ||||
| .galerie_nahledy{ | ||||
|   /*margin: 1em 0;*/ | ||||
|   margin: 0 auto 30px auto; | ||||
|  | @ -649,3 +663,11 @@ div.zadani_azad_termin { | |||
|   float: right; | ||||
|   max-width: 42%; | ||||
| } | ||||
| 
 | ||||
| .novinka_obrazek img { | ||||
|     margin-bottom: 15px; | ||||
| } | ||||
| 
 | ||||
| div.novinka_obrazek { | ||||
|     width: 100%; | ||||
| } | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ django-flat-theme==0.9.3 | |||
| django-taggit==0.17 | ||||
| django-autocomplete-light==2.2.6 | ||||
| django-crispy-forms==1.4.0 | ||||
| django-imagekit==3.2.7 | ||||
| 
 | ||||
| # Comments | ||||
| akismet==0.2.0 | ||||
|  | @ -32,7 +33,7 @@ django-contrib-comments==1.6.1 | |||
| 
 | ||||
| # debug tools/extensions | ||||
| 
 | ||||
| django-debug-toolbar==1.3.2 | ||||
| django-debug-toolbar==1.4 | ||||
| django-extensions==1.5.6 | ||||
| sqlparse==0.1.16 | ||||
| Werkzeug==0.10.4 | ||||
|  |  | |||
|  | @ -334,7 +334,7 @@ create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name=u'Pro | |||
| 
 | ||||
| class ProblemZadanyAdmin(ProblemAdmin): | ||||
|     list_display = ['nazev', 'typ', 'autor', 'opravovatel', 'kod', 'cislo_zadani', 'pocet_reseni', 'verejne'] | ||||
|     list_filter = ['typ', 'cislo_zadani__cislo', 'cislo_zadani__rocnik'] | ||||
|     list_filter = ['typ', 'zamereni', 'cislo_zadani__cislo', 'cislo_zadani__rocnik'] | ||||
|     inlines = [ReseniKProblemuInline] | ||||
| 
 | ||||
|     def get_queryset(self, request): | ||||
|  |  | |||
							
								
								
									
										25
									
								
								seminar/migrations/0035_django_imagekit.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								seminar/migrations/0035_django_imagekit.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from django.db import models, migrations | ||||
| import imagekit.models.fields | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('seminar', '0034_reseni_forma_default_email'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.RemoveField( | ||||
|             model_name='organizator', | ||||
|             name='foto_male', | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='organizator', | ||||
|             name='foto', | ||||
|             field=imagekit.models.fields.ProcessedImageField(help_text=b'Vlo\xc5\xbe fotografii organiz\xc3\xa1tora o libovoln\xc3\xa9 velikosti', upload_to=b'image_organizatori/velke/%Y/', null=True, verbose_name=b'Fotografie organiz\xc3\xa1tora', blank=True), | ||||
|             preserve_default=True, | ||||
|         ), | ||||
|     ] | ||||
|  | @ -11,6 +11,8 @@ 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 | ||||
|  | @ -183,6 +185,9 @@ class Resitel(SeminarModelBase): | |||
|     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()) | ||||
| 
 | ||||
|  | @ -755,6 +760,12 @@ class Novinky(models.Model): | |||
|     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") | ||||
|  | @ -785,11 +796,19 @@ class Organizator(models.Model): | |||
|             "'Přednáší na MFF'") | ||||
|     strucny_popis_organizatora = models.TextField('Stručný popis organizátora', | ||||
|             null = True, blank = True) | ||||
|     foto = models.ImageField('Fotografie organizátora', | ||||
|     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') | ||||
|     foto_male = models.ImageField(upload_to='image_organizatori/male/%Y/', | ||||
|             null = True, blank = True, editable = False) | ||||
|             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): | ||||
|         return str(self.user) | ||||
|  | @ -797,52 +816,3 @@ class Organizator(models.Model): | |||
|     class Meta: | ||||
|         verbose_name = 'Organizátor' | ||||
|         verbose_name_plural = 'Organizátoři' | ||||
| 
 | ||||
|     def save(self): | ||||
|         # v databázi uložený záznam o organizátorovi | ||||
|         puvodni = None | ||||
| 
 | ||||
|         # pokud už organizátor v databázi existuje, nastav puvodni | ||||
|         if self.id is not None: | ||||
|             puvodni = Organizator.objects.get(id=self.id) | ||||
|         # pokud nahráváme fotku | ||||
|         if self.foto: | ||||
|             # a je jiná než ta stará | ||||
|             if not puvodni or puvodni.foto != self.foto: | ||||
|                 # uložíme ji | ||||
|                 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)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,6 +27,16 @@ | |||
|   {% endfor %} | ||||
|   </ul> | ||||
| 
 | ||||
|   {% if user.is_staff %} | ||||
|   	<div class="mam-org-only"> | ||||
| 	<h3> Orgovské odkazy </h3> | ||||
| 	<ul> | ||||
| 		<li><a href="obalky.pdf">Obálky (PDF)</a></li> | ||||
| 		<li><a href="tituly.tex">Tituly (TeX)</a></li> | ||||
| 	</ul> | ||||
| 	</div> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if cislo.verejna_vysledkovka %} | ||||
|   <h3>Výsledkovka</h3> | ||||
|   {% else %} | ||||
|  |  | |||
|  | @ -1,33 +1,9 @@ | |||
| \begin{longtable}{r|l|c|l|c  | ||||
| 		{% for p in problemy %}   | ||||
| 		@\hskip.5em}c {% endfor %}  | ||||
| 		|c|r|r} | ||||
| \hline | ||||
| & & & & \multicolumn{ {{ problemy|length }} }{c|}{\textbf{Úlohy}} & & \\ | ||||
| \textbf{Poř.} & \textbf{Jméno} & \textbf{R.} & \raisebox{0.7mm}{$\sum_{-1}$} &  | ||||
| {% for p in problemy %}  | ||||
| 	{% if p.TYP_ULOHA %}  | ||||
| 		\textbf{ r{{ p.kod }} } &  | ||||
| 	{% else %}  | ||||
| 		\textbf{ t{{ p.kod }} } &  | ||||
| 	{% endif %}  | ||||
| {% endfor %} | ||||
| \raisebox{0.7mm}{$\sum_0$} & | ||||
| \raisebox{0.7mm}{$\sum_1$} \\ | ||||
| \hline | ||||
| \setlength{\tabcolsep}{3pt} | ||||
| \begin{longtable}{|r|l|c|r|{% for p in problemy %}c@{\hskip.5em}{% endfor %}|r|r|}\hline | ||||
| & & & & \multicolumn{ {{ problemy|length}} }{c|}{\textbf{Úlohy}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in problemy %}{% if p.typ == "uloha" %}\textbf{r{{p.kod}}}&{% elif p.typ = "tema" %}\textbf{t{{p.kod}}}&{% else  %}\textbf{ {{p.kod}} }&{% endif %}{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline | ||||
| \endhead | ||||
| \hline | ||||
| \endfoot | ||||
| 
 | ||||
| {% for rv in vysledkovka %} | ||||
|     {{ rv.poradi }} &  | ||||
| {% if rv.resitel.titul %}  | ||||
| 	\titul{ {{ rv.titul }} }  | ||||
| {% endif %}  | ||||
| 	{{ rv.resitel.plne_jmeno }} & {{ rv.resitel.rocnik |default:"" }} & {{ rv.body_minule }}  | ||||
|     {% for b in rv.body %} | ||||
| 		{{ b }} &  | ||||
| 	{% endfor %}  | ||||
| 		{{ rv.body_celkem_rocnik |default:0 }} & {{ rv.body_celkem_minule }} \\ | ||||
| \endfoot  | ||||
| {% for rv in vysledkovka %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.inicial_krestni}}{{rv.resitel.prijmeni}}&{{rv.resitel.rocnik|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_ulohy %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_celkem_rocnik|default:0}}\\ | ||||
| {% endfor %} | ||||
| \end{longtable} | ||||
|  |  | |||
|  | @ -1,21 +1,24 @@ | |||
| {% for novinka in object_list %} | ||||
| {# pripravene div-y na stylovani#} | ||||
| <div> | ||||
|   {% if not novinka.zverejneno and user.is_staff %} | ||||
|   <div class="mam-org-only"> | ||||
|   {% endif %} | ||||
|   {% if novinka.zverejneno or user.is_staff %} | ||||
|   {# datum #} | ||||
|   <div><b>{{novinka.datum}}</b></div> | ||||
|   {# text #} | ||||
|   {{ novinka.text | safe }} | ||||
|   {# obrazek #} | ||||
|   {% if novinka.obrazek %} | ||||
|     <div> | ||||
|       <img src='{{novinka.obrazek.url}}' | ||||
|       height=' | ||||
|       {% if novinka.obrazek.height > 200 %} {# vyska obrazku natvrdo #} | ||||
|         200 | ||||
|     <div class='novinka_obrazek'> | ||||
|       {% if novinka.obrazek.height > novinka.obrazek_maly.height %} | ||||
|         <a href='{{ novinka.obrazek.url }}'> | ||||
|           <img src='{{ novinka.obrazek.url }}' height='{{ novinka.obrazek_maly.height }}'> | ||||
|         </a> | ||||
|       {% else %} | ||||
|         {{novinka.obrazek.height}} | ||||
|           <img src='{{ novinka.obrazek.url }}' height='{{ novinka.obrazek_maly.height }}'> | ||||
|       {% endif%} | ||||
|       '> | ||||
|     </div> | ||||
|   {% endif %} | ||||
|   {# autor #} | ||||
|  | @ -26,6 +29,10 @@ | |||
|     {{novinka.autor.last_name}} | ||||
|       </p> | ||||
|   </div> | ||||
|   {% endif %} | ||||
|   {% if not novinka.zverejneno and user.is_staff %} | ||||
|   </div> | ||||
|   {% endif %} | ||||
| </div> | ||||
| {% endfor%} | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,46 +21,44 @@ | |||
|   {# Projdi vsechna soustredeni #} | ||||
|   {% for soustredeni in object_list %} | ||||
|     {# Kdyz je verejne -> zobraz #} | ||||
|     {% if soustredeni.verejne_db or user.is_authenticated %} | ||||
|       {% if not soustredeni.verejne_db and user.is_authenticated %} | ||||
|         Groups of user: {{user.groups.all}} <br> | ||||
|         <!-- TODO pri prihlasovani ucastniku dodelat prava | ||||
|         jen na group org ve view --> | ||||
|         Toto soustředění není veřejné, vidíte ho jen proto, | ||||
|         že jste přihlášení. <br> | ||||
|     {% if soustredeni.verejne_db or user.is_staff %} | ||||
|       {% if not soustredeni.verejne_db and user.is_staff %} | ||||
|         <div class="mam-org-only"> | ||||
|         <!--Groups of user: {{user.groups.all}} <br>--> | ||||
|       {% endif %} | ||||
|       {# misto soustredeni TODO upravit#} | ||||
|         <h2> | ||||
| 	  {{soustredeni.get_typ_display}}  | ||||
| 	  {{soustredeni.misto}} | ||||
|         </h2> | ||||
| 	<ul> | ||||
| 	<li> | ||||
| 		{{soustredeni.datum_zacatku}} – {{soustredeni.datum_konce}} | ||||
| 	</li> | ||||
|   {# Zobrazeni odkazu na galerie #} | ||||
|   {% if soustredeni.galerie_set.all %} | ||||
|     {% for galerie in soustredeni.galerie_set.all %} | ||||
|       {% if galerie.zobrazit == 0 or user.is_staff %} | ||||
|       <h2> | ||||
| 	    {{soustredeni.get_typ_display}} | ||||
| 	    {{soustredeni.misto}} | ||||
|       </h2> | ||||
|       <ul> | ||||
|         <li> | ||||
|           <a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">Fotogalerie</a> | ||||
|           {# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #} | ||||
|           {{soustredeni.datum_zacatku}} – {{soustredeni.datum_konce}} | ||||
|         </li> | ||||
|       {% endif %} | ||||
|     {% endfor %} | ||||
|   {% endif %} | ||||
| 	</ul> | ||||
|   {% if user.is_staff %} | ||||
|     <div class="mam-org-only"> | ||||
|       <a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a> | ||||
|     </div> | ||||
|   {% endif %} | ||||
| 
 | ||||
| 
 | ||||
|         {# popis soustredeni #} | ||||
|         {% if soustredeni.text %} | ||||
|           {% autoescape off %}{{soustredeni.text}}{% endautoescape %} | ||||
|         {# Zobrazeni odkazu na galerie #} | ||||
|         {% if soustredeni.galerie_set.all %} | ||||
|           {% for galerie in soustredeni.galerie_set.all %} | ||||
|             {% if galerie.zobrazit == 0 or user.is_staff %} | ||||
|               <li {% if galerie.zobrazit > 0 and user.is_staff %}class="mam-org-only"{% endif %}> | ||||
|                 <a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">Fotogalerie</a> | ||||
|                 {# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #} | ||||
|               </li> | ||||
|             {% endif %} | ||||
|           {% endfor %} | ||||
|         {% endif %} | ||||
|       </ul> | ||||
|       {% if user.is_staff %} | ||||
|         <div class="mam-org-only"> | ||||
|           <a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a><br> | ||||
|           <a href="../{{soustredeni.pk}}/obalky.pdf">Vygenerovat obálky pro účastníky</a> | ||||
|         </div> | ||||
|       {% endif %} | ||||
| 
 | ||||
| 
 | ||||
|       {# popis soustredeni #} | ||||
|       {% if soustredeni.text %} | ||||
|         {% autoescape off %}{{soustredeni.text}}{% endautoescape %} | ||||
|       {% endif %} | ||||
|       {% if user.is_authenticated %} | ||||
|         {# Účastníci #} | ||||
|         <h3>Soustředění se zúčastnili tito účastníci:</h3> | ||||
|  | @ -72,9 +70,12 @@ | |||
|         {% endfor %} | ||||
|         </ul> | ||||
|       {% endif %} | ||||
|       {% if not soustredeni.verejne_db and user.is_staff %} | ||||
|         </div> {# class="mam-org-only" #} | ||||
|       {% endif %} | ||||
|     {% endif %} | ||||
|   {% empty %} | ||||
|     Žádná soustředění zatím neproběhla! | ||||
|     {% empty %} | ||||
|       Žádná soustředění zatím neproběhla! | ||||
|   {% endfor %} | ||||
| 
 | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -20,25 +20,11 @@ M&M je korespondeční seminář. Několikrát do roka zdarma vydáváme ča | |||
| <div class="novinky"> | ||||
|   {% if dead %} | ||||
|   <div class="odpocet"> | ||||
|     <p><b>Do konce odeslání řešení zbývá:<br> | ||||
|     <p><b>Do konce <a href="https://mam.mff.cuni.cz/zadani/aktualni/">odeslání řešení</a> zbývá:<br> | ||||
|       <big>{{ted|timesince:dead}}</big></b></p> | ||||
| 
 | ||||
|       | ||||
|     <!--  | ||||
|     {{cas_do_konce_dni}} dní | ||||
|     {% if cas_do_konce_dni < 5 %} | ||||
|       {{cas_do_konce_hodin}} hodin | ||||
|       {% if cas_do_konce_hodin < 5 %} | ||||
|         {{cas_do_konce_minut}} minut | ||||
|         {% if cas_do_konce_minut < 5 %} | ||||
|           {{cas_do_konce_sekund}} | ||||
|         {% endif %} | ||||
|       {% endif %} | ||||
|     {% endif %} | ||||
|     --> | ||||
| 
 | ||||
|   </div> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {# Novinky #} | ||||
|   <h2>Novinky</h2> | ||||
|   {% include 'seminar/novinky.html' %} | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
|   {% if vysledkovka %} | ||||
|     {% include "seminar/vysledkovka_rocnik.html" %} | ||||
|   {% else %} | ||||
|     V tomto ročníku zatím žádné výsledky nejsou | ||||
|     V tomto ročníku zatím žádné výsledky nejsou. | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if user.is_staff and vysledkovka_s_neverejnymi %} | ||||
|  |  | |||
|  | @ -13,7 +13,11 @@ | |||
| {% block content %} | ||||
| <div> | ||||
|    | ||||
|   {% with nastaveni.aktualni_cislo as ac %} | ||||
| {% with nastaveni.aktualni_cislo as ac %} | ||||
|   | ||||
| {# Zobrazovani neverejnych zadani jen organizatorum #} | ||||
| {% if user.is_staff or verejne %} | ||||
| {% if user.is_staff and not verejne %}<div class="mam-org-only">{% endif %} | ||||
| 
 | ||||
|       {% if ac.zadane_problemy.all %} | ||||
| 	<div class="zadani_azad_termin"> | ||||
|  | @ -45,6 +49,12 @@ | |||
|       Aktuálně nejsou zadané žádné úlohy k řešení. | ||||
|     {% endfor %} | ||||
| 
 | ||||
| {% if user.is_staff and not verejne%}</div>{% endif %} | ||||
| {% else %} | ||||
|   <h3>Aktuálně nejsou zveřejněny žádné úlohy</h3> | ||||
| {% endif %} | ||||
| 
 | ||||
| 
 | ||||
|     <h3>Témata</h3> | ||||
|       <ul> | ||||
|       {% for problem in temata %} | ||||
|  | @ -56,7 +66,8 @@ | |||
|         Aktuálně nejsou zadána žádná témata k řešení. | ||||
|       {% endfor %} | ||||
|       </ul> | ||||
|   {% endwith %} | ||||
| 
 | ||||
| {% endwith %} | ||||
| 
 | ||||
| </div> | ||||
| {% endblock content %} | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ from django.core.urlresolvers import reverse | |||
| from django.views import generic | ||||
| from django.utils.translation import ugettext as _ | ||||
| from django.http import Http404 | ||||
| from django.db.models import Q | ||||
| 
 | ||||
| from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici | ||||
| from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva | ||||
|  | @ -29,6 +30,7 @@ def verejna_temata(rocnik): | |||
| 
 | ||||
| def AktualniZadaniView(request): | ||||
|     nastaveni = get_object_or_404(Nastaveni) | ||||
|     verejne = nastaveni.aktualni_cislo.verejne() | ||||
|     problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany') | ||||
|     ulohy = problemy.filter(typ = 'uloha').order_by('kod') | ||||
|     serialy = problemy.filter(typ = 'serial').order_by('kod') | ||||
|  | @ -37,6 +39,7 @@ def AktualniZadaniView(request): | |||
|             {'nastaveni': nastaveni, | ||||
|              'jednorazove_problemy': jednorazove_problemy, | ||||
|              'temata': verejna_temata(nastaveni.aktualni_rocnik), | ||||
|              'verejne': verejne, | ||||
|                 }, | ||||
|             ) | ||||
| 
 | ||||
|  | @ -66,22 +69,22 @@ def ZadaniAktualniVysledkovkaView(request): | |||
| class TitulniStranaView(generic.ListView): | ||||
|     model = Novinky | ||||
|     template_name='seminar/titulnistrana.html' | ||||
|     queryset = Novinky.objects.filter(zverejneno=True).order_by('-datum')[:5] | ||||
|     queryset = Novinky.objects.order_by('-datum')[:5] | ||||
| 
 | ||||
|     def get_context_data(self, **kwargs): | ||||
|         context = super(TitulniStranaView, self).get_context_data(**kwargs) | ||||
|         nastaveni = get_object_or_404(Nastaveni) | ||||
|         cas_deadline = nastaveni.aktualni_cislo.datum_deadline | ||||
|         try: | ||||
|           rozdil_casu =  datetime.combine(cas_deadline, datetime.max.time()) \ | ||||
|                   - datetime.now() | ||||
|           context['cas_do_konce_dni']    = rozdil_casu.days | ||||
|           context['cas_do_konce_hodin']  = rozdil_casu.seconds / 3600 | ||||
|           context['cas_do_konce_minut'] = (rozdil_casu.seconds / 60) % 60 | ||||
|           context['cas_do_konce_sekund'] = rozdil_casu.seconds % 60 | ||||
|           context['dead'] = datetime.combine(cas_deadline, datetime.max.time()) | ||||
|           context['ted'] = datetime.now() | ||||
|         except: | ||||
|         # Pokud neni zverejnene cislo nezverejnuj odpocet | ||||
|         if nastaveni.aktualni_cislo.verejne(): | ||||
|           # pokus se zjistit termin odeslani a pokud neni zadany, | ||||
|           # nezverejnuj odpocet | ||||
|           try: | ||||
|             context['dead'] = datetime.combine(cas_deadline, datetime.max.time()) | ||||
|             context['ted'] = datetime.now() | ||||
|           except: | ||||
|               context['dead'] = None | ||||
|         else: | ||||
|             context['dead'] = None | ||||
|         return context | ||||
| 
 | ||||
|  | @ -128,8 +131,9 @@ def sloupec_s_poradim(vysledky): | |||
|             poradi_l += ["{}.".format(lepsich_resitelu + 1)] | ||||
|         # je-li účastníků se stejným počtem bodů víc, pořadí (rozsah X.-Y.) je jen u prvního | ||||
|         else: | ||||
|             poradi_l += ["{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) | ||||
|             poradi_l += [u"{}. – {}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) | ||||
|         lepsich_resitelu += len(skupina) | ||||
| 	#pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu | ||||
| 
 | ||||
|     return poradi_l | ||||
| 
 | ||||
|  | @ -293,6 +297,7 @@ class CisloView(generic.DetailView): | |||
|             v.poradi = poradi | ||||
|             v.body_celkem_rocnik = v.body | ||||
|             v.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body | ||||
|             v.resitel.rocnik = v.resitel.rocnik(v.cislo.rocnik) | ||||
| 
 | ||||
|             # je tady '', aby se nezobrazovala 0, pokud se řešitel o řešení úlohy ani nepokusil | ||||
|             v.body_ulohy = [''] * len(problemy) | ||||
|  | @ -342,28 +347,42 @@ class RocnikVysledkovkaView(RocnikView): | |||
| 
 | ||||
| ### Generovani obalek | ||||
| class CisloObalkyStruct: | ||||
|     resitele = None | ||||
|     rocnik = None | ||||
|     problemy = None | ||||
|     cisla = None | ||||
| 
 | ||||
| def cisloObalkyView(request,rocnik,cislo): | ||||
| 
 | ||||
| # Vraci QuerySet aktualnich resitelu = nekdy neco poslali, ale jeste neodmaturovali | ||||
| def aktualniResitele(rocnik): | ||||
|     letos = Rocnik.objects.filter(rocnik = rocnik).first() | ||||
|     return Resitel.objects.filter(rok_maturity__gt = letos.prvni_rok) | ||||
| #   # ALERT: pokud nekdo nema vypleny rok maturity, tak neni aktualni, protoze Karel Tesar a jini | ||||
| #    return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None)) | ||||
|      | ||||
| # Vraci QuerySet aktivnich resitelu =  | ||||
| # jeste neodmaturovali &&  | ||||
| # (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali | ||||
| # jinak letos neco poslali) | ||||
| def aktivniResitele(rocnik,cislo): | ||||
|     letos = CisloObalkyStruct() | ||||
|     loni = CisloObalkyStruct() | ||||
| 
 | ||||
|     letos.rocnik = Rocnik.objects.filter(rocnik = rocnik)[0] | ||||
|     loni.rocnik = Rocnik.objects.filter(rocnik = int(rocnik)-1)[0] | ||||
|     letos.problemy = Problem.objects.filter(cislo_zadani = Cislo.objects.filter(rocnik=letos.rocnik,cislo__lte = cislo)) | ||||
|     loni.problemy = Problem.objects.filter(cislo_zadani = Cislo.objects.filter(rocnik=loni.rocnik)) | ||||
|     letos.resitele = Resitel.objects.filter(reseni = Reseni.objects.filter(problem=letos.problemy)).distinct() | ||||
|     loni.resitele = Resitel.objects.filter(reseni = Reseni.objects.filter(problem=loni.problemy)).distinct() | ||||
| 
 | ||||
|     loni.resitele = loni.resitele.filter(rok_maturity__gt =  letos.rocnik.prvni_rok) | ||||
| 
 | ||||
|     aktualni_resitele = aktualniResitele(rocnik) | ||||
|      | ||||
|     letos.rocnik = Rocnik.objects.filter(rocnik = rocnik).first() | ||||
|     loni.rocnik = Rocnik.objects.filter(rocnik = int(rocnik)-1).first() | ||||
|     letos.cisla = Cislo.objects.filter(rocnik=letos.rocnik,cislo__lte = cislo) | ||||
|     loni.cisla = Cislo.objects.filter(rocnik=loni.rocnik)  | ||||
|     if int(cislo) > 3: | ||||
|         resitele = letos.resitele | ||||
|         problemy = Problem.objects.filter(cislo_zadani = letos.cisla) | ||||
|     else: | ||||
|         resitele = list(letos.resitele) + list(loni.resitele) | ||||
|     return obalkyView(request,resitele) | ||||
|         problemy = Problem.objects.filter(Q(cislo_zadani = letos.cisla)|Q(cislo_zadani=loni.cisla)) | ||||
|     resitele = aktualni_resitele.filter(reseni = Reseni.objects.filter(problem=problemy)).distinct() | ||||
| 
 | ||||
|     return resitele | ||||
|      | ||||
| 
 | ||||
| def cisloObalkyView(request,rocnik,cislo): | ||||
|     return obalkyView(request,aktivniResitele(rocnik,cislo)) | ||||
| 
 | ||||
| 
 | ||||
| def obalkyView(request,resitele): | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Bc. Petr Pecha
						Bc. Petr Pecha