Browse Source

Merge remote-tracking branch 'origin/master' into stable

remotes/origin/temata v1.2
Bc. Petr Pecha 9 years ago
parent
commit
8f1c1ac664
  1. 25
      galerie/TODO
  2. 0
      galerie/__init__.py
  3. 43
      galerie/admin.py
  4. 11
      galerie/forms.py
  5. 59
      galerie/migrations/0001_initial.py
  6. 27
      galerie/migrations/0002_auto_20151013_1145.py
  7. 39
      galerie/migrations/0003_add_galerie_poradi.py
  8. 0
      galerie/migrations/__init__.py
  9. 179
      galerie/models.py
  10. 2
      galerie/static/galerie/.gitignore
  11. BIN
      galerie/static/galerie/prvky/dalsi.png
  12. BIN
      galerie/static/galerie/prvky/predchozi.png
  13. 6
      galerie/templates/galerie/Base.html
  14. 65
      galerie/templates/galerie/Galerie.html
  15. 77
      galerie/templates/galerie/GalerieNahled.html
  16. 22
      galerie/templates/galerie/GalerieNew.html
  17. 12
      galerie/urls.py
  18. 169
      galerie/views.py
  19. 1
      mamweb/settings_common.py
  20. 94
      mamweb/static/css/mamweb.css
  21. 2
      requirements.txt
  22. 2
      seminar/admin.py
  23. 7
      seminar/models.py
  24. 24
      seminar/templates/seminar/soustredeni/seznam_soustredeni.html
  25. 69
      seminar/templates/seminar/titulnistrana.html
  26. 4
      seminar/urls.py

25
galerie/TODO

@ -0,0 +1,25 @@
========
| TODO |
|======|
Aktualni
* co s titulni fotkou
* do CSS
* nahledy
* nastylovat tabulku s nahledy
* komentare uz na nahledy?
* detail
* nahledy pred a po
* opravit prechodove sipky
* vyrobit prechodove sipky ve M&M-stylu
Dlouhodobe
* sipky na prechazeni mezi fotkami
* hromadne PRIDANI fotek do jiz existujici galerie
Fylozoficke
* zvolit velikosti velke a male fotky
* je potreba i jine razeni nez automaticky podle casu nebo staci podgalerie?
* napr. dve hry na dvou ruznych mistech ve stejny cas
* fotky od ucastniku ze hry (skupinky se pohybuji ve stejny cas, ale maji sled fotek) -- nestaci to pripadne vrazit do podgalerii?

0
galerie/__init__.py

43
galerie/admin.py

@ -0,0 +1,43 @@
#coding: utf-8
from galerie.models import Obrazek, Galerie
from django.contrib import admin
from django.http import HttpResponseRedirect
# akction
def zverejnit_fotogalerii(modeladmin, request, queryset):
'''zverejni vybranou fotogalerii i jeji vsechny podgalerie'''
for galerie in queryset:
galerie.zobrazit = 0
galerie.save()
zverejnit_fotogalerii(modeladmin, request,
Galerie.objects.filter(galerie_up = galerie))
zverejnit_fotogalerii.short_description = 'Zveřejnit fotogalerie'
def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset):
'''zneverjni vybranou fotogalerii i jeji vsechny podgalerie'''
for galerie in queryset:
galerie.zobrazit = 1
galerie.save()
prepnout_fotogalerii_do_org_rezimu(modeladmin, request,
Galerie.objects.filter(galerie_up = galerie))
prepnout_fotogalerii_do_org_rezimu.short_description = \
'Přepnout do režimu úprav (zneveřejní galerii)'
class GalerieInline(admin.TabularInline):
model = Obrazek
class ObrazekAdmin(admin.ModelAdmin):
list_display = ('obrazek_velky', 'nazev', 'popis')
class GalerieAdmin(admin.ModelAdmin):
model = Galerie
fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni')
list_display = ('nazev', 'pk', 'datum_zmeny', 'zobrazit', 'soustredeni')
inlines = [GalerieInline]
actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu]
admin.site.register(Obrazek, ObrazekAdmin)
admin.site.register(Galerie, GalerieAdmin)

11
galerie/forms.py

@ -0,0 +1,11 @@
#coding: utf-8
from django import forms
from seminar.models import Soustredeni
class KomentarForm(forms.Form):
komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False)
class NewGalerieForm(forms.Form):
nazev = forms.CharField(label = "Název galerie", max_length = 100)
popis = forms.CharField(label = "Popis", required = False, max_length = 2000, widget = forms.Textarea)

59
galerie/migrations/0001_initial.py

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('seminar', '0033_organizator_studuje_popisek'),
]
operations = [
migrations.CreateModel(
name='Galerie',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('nazev', models.CharField(max_length=100, verbose_name=b'N\xc3\xa1zev')),
('datum_vytvoreni', models.DateTimeField(auto_now_add=True, verbose_name=b'Datum vytvo\xc5\x99en\xc3\xad')),
('datum_zmeny', models.DateTimeField(auto_now=True, verbose_name=b'Datum posledn\xc3\xad zm\xc4\x9bny')),
('popis', models.TextField(null=True, verbose_name=b'Popis', blank=True)),
('zobrazit', models.IntegerField(default=1, verbose_name=b'Zobrazit?', choices=[(0, b'V\xc5\xbedy'), (1, b'Organiz\xc3\xa1tor\xc5\xafm'), (2, b'Nikdy')])),
('galerie_up', models.ForeignKey(blank=True, to='galerie.Galerie', null=True)),
('soustredeni', models.ForeignKey(blank=True, to='seminar.Soustredeni', null=True)),
],
options={
'verbose_name': 'Galerie',
'verbose_name_plural': 'Galerie',
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Obrazek',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('obrazek_velky', models.ImageField(help_text=b'Lze vlo\xc5\xbeit libovoln\xc4\x9b velk\xc3\xbd obr\xc3\xa1zek. Ide\xc3\xa1ln\xc3\xad je, aby alespo\xc5\x88 jeden rozm\xc4\x9br m\xc4\x9bl alespo\xc5\x88 500px.', upload_to=b'Galerie/%Y/%m/%d')),
('obrazek_stredni', models.ImageField(upload_to=b'Galerie/%Y/%m/%d/stredni', null=True, editable=False)),
('obrazek_maly', models.ImageField(upload_to=b'Galerie/%Y/%m/%d/male', null=True, editable=False)),
('nazev', models.CharField(max_length=50, null=True, verbose_name=b'N\xc3\xa1zev', blank=True)),
('popis', models.TextField(null=True, verbose_name=b'Popis', blank=True)),
('datum_vlozeni', models.DateTimeField(auto_now_add=True, verbose_name=b'Datum vlo\xc5\xbeen\xc3\xad')),
('datum', models.DateTimeField(verbose_name=b'Datum po\xc5\x99\xc3\xadzen\xc3\xad fotografie')),
('poradi', models.IntegerField(null=True, verbose_name=b'Po\xc5\x99ad\xc3\xad', blank=True)),
('galerie', models.ForeignKey(to='galerie.Galerie')),
],
options={
'verbose_name': 'Obr\xe1zek',
'verbose_name_plural': 'Obr\xe1zky',
},
bases=(models.Model,),
),
migrations.AddField(
model_name='galerie',
name='titulni_obrazek',
field=models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.SET_NULL, to='galerie.Obrazek', null=True),
preserve_default=True,
),
]

27
galerie/migrations/0002_auto_20151013_1145.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('galerie', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='galerie',
name='titulni_obrazek',
field=models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='galerie.Obrazek', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='obrazek',
name='datum',
field=models.DateTimeField(null=True, verbose_name=b'Datum po\xc5\x99\xc3\xadzen\xc3\xad fotografie', blank=True),
preserve_default=True,
),
]

39
galerie/migrations/0003_add_galerie_poradi.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import galerie.models
class Migration(migrations.Migration):
dependencies = [
('galerie', '0002_auto_20151013_1145'),
]
operations = [
migrations.AddField(
model_name='galerie',
name='poradi',
field=models.IntegerField(null=True, verbose_name=b'Po\xc5\x99ad\xc3\xad', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='obrazek',
name='obrazek_maly',
field=models.ImageField(upload_to=galerie.models.obrazek_filename_maly, null=True, editable=False),
preserve_default=True,
),
migrations.AlterField(
model_name='obrazek',
name='obrazek_stredni',
field=models.ImageField(upload_to=galerie.models.obrazek_filename_stredni, null=True, editable=False),
preserve_default=True,
),
migrations.AlterField(
model_name='obrazek',
name='obrazek_velky',
field=models.ImageField(help_text=b'Lze vlo\xc5\xbeit libovoln\xc4\x9b velk\xc3\xbd obr\xc3\xa1zek. Ide\xc3\xa1ln\xc3\xad je, aby alespo\xc5\x88 jeden rozm\xc4\x9br m\xc4\x9bl alespo\xc5\x88 500px.', upload_to=galerie.models.obrazek_filename),
preserve_default=True,
),
]

0
galerie/migrations/__init__.py

179
galerie/models.py

@ -0,0 +1,179 @@
# coding: utf-8
from django.db import models
import seminar.models
from django.db.models import Q
from django.utils import timezone
from django.utils.encoding import force_unicode
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
VZDY=0
ORG=1
NIKDY=2
VIDITELNOST = (
(VZDY, 'Vždy'),
(ORG, 'Organizátorům'),
(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
]
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))
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)
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')
poradi = models.IntegerField('Pořadí', blank = True, null = True)
def __unicode__(self):
return self.nazev + " -- " + unicode(self.obrazek_velky.name) + " (" + str(self.datum) + ")"
class Meta:
verbose_name = 'Obrázek'
verbose_name_plural = 'Obrázky'
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, 500, self.obrazek_stredni)
if not self.obrazek_maly:
Obrazek._vyrobMiniaturu(original, jmeno, 200, self.obrazek_maly)
super(Obrazek, self).save()
@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)
@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):
nazev = models.CharField('Název', max_length=100)
datum_vytvoreni = models.DateTimeField('Datum vytvoření', auto_now_add = True)
datum_zmeny = models.DateTimeField('Datum poslední změny', auto_now = True)
popis = models.TextField('Popis', blank = True, null = True)
titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL)
zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST)
galerie_up = models.ForeignKey('Galerie', blank = True, null = True)
soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True)
poradi = models.IntegerField('Pořadí', blank = True, null = True)
def __unicode__(self):
return self.nazev
class Meta:
verbose_name = 'Galerie'
verbose_name_plural = 'Galerie'
#def link_na_preview(self):
#"""Odkaz na galerii, používá se v admin rozhranní. """
#return '<a href="/fotogalerie/galerie/%s/">Preview</a>' % self.id
#link_na_preview.allow_tags = True
#link_na_preview.short_description = 'Zobrazit galerii'
#
#def je_publikovano(self):
#"""Vraci True, pokud je tato galerie publikovana. """
#if self.zobrazit == VZDY:
#return True
#if self.zobrazit == PODLE_CLANKU:
#for clanek in self.clanek_set.all():
#if clanek.je_publikovano():
#return True
#return False
#
#@staticmethod
#def publikovane_galerie():
#"""Vraci galerie, ktere uz maji byt publikovane."""
#clanky = Blog.models.Clanek.publikovane_clanky()
#return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct()

2
galerie/static/galerie/.gitignore

@ -0,0 +1,2 @@
images
lightbox

BIN
galerie/static/galerie/prvky/dalsi.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
galerie/static/galerie/prvky/predchozi.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

6
galerie/templates/galerie/Base.html

@ -0,0 +1,6 @@
{% extends "base.html" %}
{# TODO predelat pres context processor #}
{% block header %}soustredeni{% endblock %}
{% block menu_soustredeni %}selected{% endblock %}
{% block submenu %}{% include 'seminar/soustredeni/submenu.html' %}{% endblock %}

65
galerie/templates/galerie/Galerie.html

@ -0,0 +1,65 @@
{% extends "galerie/Base.html" %}
{% block title %}{% block nadpis1a %}
{{galerie.nazev}} | Galerie
{% endblock %}{% endblock %}
{% block content %}
<h1><a title="Zpět na náhled fotek" href="../#obsah">{{galerie.nazev}}</a></h1>
{# TODO šipky na přecházeni dodelat ve stylech #}
<div class="galerie">
{% if obrazky_predchozi %}
{% with obrazky_predchozi|last as predchozi_obrazek %}
<div id="popis">
<a title="Předchozí" class="predchozi_obrazek" href="../{{predchozi_obrazek.pk}}#popis"></a>
</div>
{% endwith %}
{% endif%}
<img src={{obrazek.obrazek_stredni.url}}
height="{{vyska}}"
width="{{sirka}}"
alt="{{obrazek.popis}}"
class="obrazek">
{% if obrazky_dalsi %}
{% with obrazky_dalsi|first as dalsi_obrazek %}
<div>
<a title="Další" class="dalsi_obrazek" href="../{{dalsi_obrazek.pk}}#popis"></a>
</div>
{% endwith %}
{% endif%}
</div>
{# Popisek fotky #}
<div class="popis">
{% if preview %}
<form action=".#popis" method="post">
{% csrf_token %}
<table>
<tr><td><label>Aktuální komentář:</label></td><td>{{obrazek.popis}}</td>
{{form.as_table}}
<tr><td></td><td><input name="odeslat" type="submit" value="Změň komentář"></td></tr>
</table>
</form>
{% else %}
{% if obrazek.popis %}
{{obrazek.popis}}
{% endif %}
{% endif %}
</div>
<div class="galerie_nahledy">
{% for obrazek in obrazky_predchozi %}
<a href="../{{obrazek.pk}}#popis"><img src="{{obrazek.obrazek_maly.url}}" height="100"></a>
{% endfor %}
<img src={{obrazek.obrazek_maly.url}}
height="{{obrazek.obrazek_maly.height}}"
width="{{obrazek.obrazek_maly.width}}"
alt="{{obrazek.popis}}"
class="obrazek">
{% for obrazek in obrazky_dalsi %}
<a href="../{{obrazek.pk}}#popis"><img src="{{obrazek.obrazek_maly.url}}" height="100"></a>
{% endfor %}
</div>
{% endblock %}

77
galerie/templates/galerie/GalerieNahled.html

@ -0,0 +1,77 @@
{% extends "galerie/Base.html" %}
{% block title %}{% block nadpis1a %}
{{galerie.nazev}} | Galerie TODO title
{% endblock %}{% endblock %}
{% block content %}
<h2>{{galerie.nazev}}</h2>
{# podgalerie #}
{% if podgalerie or galerie.galerie_up %}
<h3> PODGALERIE </h3>
<ul>
{% if galerie.galerie_up %}
<li><a href="../{{galerie.galerie_up.pk}}">..</a>
{% endif %}
{% for galerie in podgalerie %}
{% if galerie.zobrazit < 1 or user.is_staff %}
<li><a href="../{{galerie.pk}}">{{galerie}}</a>
{% if user.is_staff and galerie.zobrazit > 0 %}
({{galerie.poradi}})
<span class="plus"><a href="plus/{{galerie.pk}}/">+</a></span>
<span class="minus"><a href="minus/{{galerie.pk}}/">-</a></span>
{% endif %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% if user.is_staff and galerie.zobrazit > 0 %}
<ul>
<li><a href="./new">VYTVOŘIT NOVOU PODGALERII </a>
</ul>
{% endif %}
{# obrazky v galerii #}
{% if obrazky %}
<table class="galerie_nahled">
{% for obrazek in obrazky %}
{% if forloop.counter|add:-1|divisibleby:3 %}
<tr>
{% endif %}
<td class="vystredeno">
<a title="Zobrazit tuto fotografii" href="./{{obrazek.pk}}#popis"
class="jednoducha-galerie">
<img
src="{{obrazek.obrazek_maly.url}}"
width={% widthratio obrazek.obrazek_maly.width 200 167 %}
height={% widthratio obrazek.obrazek_maly.height 200 167 %} />
</a>
<!--<a href="{{obrazek.obrazek_velky.url}}"
class="javascript-galerie" data-lightbox="galerie" data-title="{{obrazek.popis}}"
style="display: none;">
<img
src="{{obrazek.obrazek_maly.url}}"
width={% widthratio obrazek.obrazek_maly.width 200 167 %}
height={% widthratio obrazek.obrazek_maly.height 200 167 %} />
</a>-->
</td>
{% if forloop.last %}
{% if not forloop.counter|divisibleby:3 %}
<td></td>
{% endif %}
{% if not forloop.counter|divisibleby:2 %}
<td></td>
{% endif %}
{% endif %}
{% if forloop.counter|divisibleby:3 or forloop.last %}
</tr>
{% endif %}
{% endfor %}
</table>
{% else %}
<div class="zadne-vysledky">
V galerii nejsou žádné fotky.
</div>
{% endif %}
{% endblock content %}

22
galerie/templates/galerie/GalerieNew.html

@ -0,0 +1,22 @@
{% extends "galerie/Base.html" %}
{% block title %}{% block nadpis1a %}
Vytvářím novou galerii
{% endblock %}{% endblock %}
{% block content %}
<h2> Vytváření nové galerie </h2>
<h3> Vytvářím galerii k soustředění {{soustredeni}} jako {{galerie_text}}</h3>
<form enctype="multipart/form-data" action="." method="post">
{% csrf_token %}
<table>{{form.as_table}}
<tr><td><label>Obrázky:</label></td><td><input name="obr" type="file" multiple></td></tr>
<tr><td>&nbsp;</td></tr>
<tr><td></td><td><input name="odeslat" type="submit" value="Vytvoř galerii"></td></tr>
</table>
</form>
{% endblock %}

12
galerie/urls.py

@ -0,0 +1,12 @@
# coding: utf-8
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
(r'^(?P<pk>\d+)/$', 'galerie.views.nahled'),
(r'^(?P<pk>\d+)/(?P<fotka>\d+)/$', 'galerie.views.detail'),
(r'^(?P<galerie>\d+)/new/$', 'galerie.views.new_galerie'),
(r'^(?P<galerie>\d+)/plus/(?P<subgalerie>\d+)/$', 'galerie.views.plus_galerie'),
(r'^(?P<galerie>\d+)/minus/(?P<subgalerie>\d+)/$', 'galerie.views.minus_galerie'),
)

169
galerie/views.py

@ -0,0 +1,169 @@
# coding: utf-8
import random
from django.http import HttpResponse, Http404
from django.shortcuts import render, HttpResponseRedirect, get_object_or_404
from django.template import RequestContext
from datetime import datetime
from galerie.models import Obrazek, Galerie
from seminar.models import Soustredeni
from galerie.forms import KomentarForm, NewGalerieForm
def zobrazit(galerie, request):
preview = False
if galerie.zobrazit >= 1:
if request.user.is_staff:
preview = True;
else:
raise Http404
return preview
def nahled(request, pk, soustredeni):
"""Zobrazeni nahledu vsech fotek ve skupine."""
galerie = get_object_or_404(Galerie, pk=pk)
podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi')
obrazky = Obrazek.objects.filter(galerie = galerie).order_by('datum')
preview = zobrazit(galerie, request)
return render(request, 'galerie/GalerieNahled.html',
{'galerie' : galerie,
'podgalerie' : podgalerie,
'obrazky' : obrazky,
'preview' : preview,
})
def detail(request, pk, fotka, soustredeni):
"""Zobrazeni nahledu fotky s id 'fotka'."""
MAX_VYSKA = 600
MAX_SIRKA = 600
MAX_VYSKA_MALA = 100
MAX_SIRKA_MALA = 200
NAHLEDU = 1
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')
# vytvoreni a obslouzeni formulare
if request.method == 'POST':
form = KomentarForm(request.POST)
if form.is_valid():
obrazek.popis = form.cleaned_data['komentar']
obrazek.save()
else:
form = KomentarForm({'komentar': obrazek.popis})
# Poradi aktualniho obrazku v galerii/stitku.
for i in range(len(obrazky)):
if obrazky[i] == obrazek:
znacka = i
break
else:
# Obrazek neni v galerii/stitku.
raise Http404
# Nacteni okolnich obrazku.
obrazky_dalsi = obrazky[znacka+1:znacka+NAHLEDU+1]
if znacka > NAHLEDU:
obrazky_predchozi = obrazky[znacka-NAHLEDU:znacka]
else:
obrazky_predchozi = obrazky[0:znacka]
# Preskalovani obrazku do vybraneho prostoru.
vyska = obrazek.obrazek_stredni.height
sirka = obrazek.obrazek_stredni.width
if vyska > MAX_VYSKA:
sirka = sirka * MAX_VYSKA / vyska
vyska = MAX_VYSKA
if sirka > MAX_SIRKA:
vyska = vyska * MAX_SIRKA / sirka
sirka = MAX_SIRKA
return render(request, 'galerie/Galerie.html',
{'galerie' : galerie,
'obrazek' : obrazek,
'vyska' : vyska,
'sirka' : sirka,
'obrazky_predchozi' : obrazky_predchozi,
'obrazky_dalsi' : obrazky_dalsi,
'preview' : preview,
'form' : form,
})
def new_galerie(request, galerie, soustredeni):
# zjistime k jakemu soustredeni se vaze nove vytvarena galerie
soustredeni = get_object_or_404(Soustredeni, pk = soustredeni)
# pokud je parametr galerie 0, pak jde o hlavni galerii
# kdyz je nejaky jiny, pak je pk galerie pod kterou tu dalsi vytvarim
if int(galerie) == 0:
galerie_up = False
galerie_text = "Hlavní fotogalerie soustředění"
else:
galerie_up = get_object_or_404(Galerie, pk = int(galerie))
galerie_text = "podgalerii ke galerii " + str(galerie_up)
# obsluha formulare umoznujiciho multiple nahravani fotek
if request.method == 'POST':
form = NewGalerieForm(request.POST, request.FILES)
if form.is_valid():
# vytvoreni nove galerie
gal = Galerie()
gal.nazev = form.cleaned_data['nazev']
gal.popis = form.cleaned_data['popis']
gal.zobrazit = 1 # galerie je v procesu vytvareni
''' pokud je to podgalerie pridej nadrazenou galerii
a nadrazene soustredeni nechej volne,
pokud je to hlavni galerie, tak nadrazena galerie neexistuje,
ale v takovem pripade musi byt nadrazene soustredeni a ne jinak '''
if galerie_up:
gal.galerie_up = galerie_up
else:
gal.soustredeni = soustredeni
if gal.galerie_up:
gal.poradi = int(len(gal.galerie_up.galerie_set.all())) + 1
gal.save()
# zpracovani obrazku v galerii
for obr in request.FILES.getlist('obr'):
o = Obrazek()
o.obrazek_velky = obr
o.nazev = str(obr)
o.galerie = gal
o.save()
# presmerovani na prave vzniklou galerii
return HttpResponseRedirect('../../' + str(gal.pk))
else:
form = NewGalerieForm()
return render(request, 'galerie/GalerieNew.html',
{
'form' : form,
'soustredeni' : soustredeni,
'galerie_text' : galerie_text,
})
def plus_galerie(request, galerie, soustredeni, subgalerie):
galerie = get_object_or_404(Galerie, pk=subgalerie)
if galerie.poradi:
galerie.poradi += 1
else:
galerie.poradi = int(len(galerie.galerie_up.galerie_set.all()))
galerie.save()
return HttpResponseRedirect('../../')
def minus_galerie(request, galerie, soustredeni, subgalerie):
galerie = get_object_or_404(Galerie, pk=subgalerie)
if galerie.poradi:
galerie.poradi -= 1
else:
galerie.poradi = 1
galerie.save()
return HttpResponseRedirect('../../')

1
mamweb/settings_common.py

@ -113,6 +113,7 @@ INSTALLED_APPS = (
# MaMweb # MaMweb
'mamweb', 'mamweb',
'seminar', 'seminar',
'galerie',
# Admin upravy: # Admin upravy:

94
mamweb/static/css/mamweb.css

@ -299,6 +299,21 @@ div.zadani_azad_termin {
padding: 20px 0px 20px 0px; padding: 20px 0px 20px 0px;
float: none; float: none;
} }
div.novinky{
max-width: 100%;
margin-left: auto;
margin-right: auto;
float: none;
}
div.graf{
float: none;
margin-left: auto;
margin-right: auto;
width: 70%;
}
} }
@media (max-width: 767px) { @media (max-width: 767px) {
@ -407,4 +422,83 @@ div.zadani_azad_termin {
padding: 30px 0px 20px 0px; padding: 30px 0px 20px 0px;
float: none; float: none;
} }
div.novinky{
max-width: 100%;
float: none;
}
div.graf{
float: none;
width: 70%;
margin-left: auto;
margin-right: auto
}
}
/* galerie */
.predchozi_obrazek{
position: absolute;
z-index: 1;
width: 33%;
height: 100%;
left: 0;
top: 0;
}
.predchozi_obrazek:hover{
background-image: url("/static/galerie/prvky/predchozi.png");
background-position: left center;
background-repeat: no-repeat;
}
.dalsi_obrazek{
position: absolute;
z-index: 1;
width: 33%;
height: 100%;
left: 67%;
top: 0;
}
.dalsi_obrazek:hover{
background-image: url("/static/galerie/prvky/dalsi.png");
background-position: right center;
background-repeat: no-repeat;
}
.galerie{
position: relative;
}
.galerie_nahledy{
margin: 1em 0;
text-align: center;
}
.galerie_index{
width: 100%;
}
.galerie_index td{
width: 50%;
}
.galerie_nahled{
width: 100%;
}
.galerie_nahled td{
width: 33%;
}
/* titulni stranka */
.zjistit_vic{
text-align: center;
}
.graf{
float: left;
}
.novinky{
float: right;
max-width: 42%;
} }

2
requirements.txt

@ -11,7 +11,7 @@ traitlets==4.0.0
# Django and modules # Django and modules
Django==1.7.10 # Updatable to 1.8 (possibly incompatible) Django==1.7.10 # Updatable to 1.9 (possibly incompatible)
django-bootstrap-sass==0.0.6a0 django-bootstrap-sass==0.0.6a0
django-mptt==0.7.3 django-mptt==0.7.3
django-reversion==1.9.3 django-reversion==1.9.3

2
seminar/admin.py

@ -319,7 +319,7 @@ class ProblemAdmin(reversion.VersionAdmin):
return obj.pocet_reseni return obj.pocet_reseni
class ProblemNavrhAdmin(ProblemAdmin): class ProblemNavrhAdmin(ProblemAdmin):
list_display = ['nazev', 'typ', 'zamereni', 'stav', 'autor', 'timestamp'] list_display = ['nazev', 'typ', 'stav', 'autor', 'timestamp']
list_filter = ['typ', 'zamereni', 'timestamp', 'stav'] list_filter = ['typ', 'zamereni', 'timestamp', 'stav']
def get_queryset(self, request): def get_queryset(self, request):

7
seminar/models.py

@ -795,10 +795,17 @@ class Organizator(models.Model):
verbose_name_plural = 'Organizátoři' verbose_name_plural = 'Organizátoři'
def save(self): 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: if self.id is not None:
puvodni = Organizator.objects.get(id=self.id) puvodni = Organizator.objects.get(id=self.id)
# pokud nahráváme fotku
if self.foto: if self.foto:
# a je jiná než ta stará
if not puvodni or puvodni.foto != self.foto: if not puvodni or puvodni.foto != self.foto:
# uložíme ji
original = Image.open(self.foto) original = Image.open(self.foto)
jmeno = os.path.basename(self.foto.file.name) jmeno = os.path.basename(self.foto.file.name)
Organizator._vyrobMiniaturu(original, jmeno, 500, self.foto) Organizator._vyrobMiniaturu(original, jmeno, 500, self.foto)

24
seminar/templates/seminar/soustredeni/seznam_soustredeni.html

@ -17,8 +17,6 @@
<em> <em>
Na galeriích ze soustředění a dalších informacích ještě pracujeme. Na galeriích ze soustředění a dalších informacích ještě pracujeme.
</em><br><br> </em><br><br>
{#% if user.is_authenticated %#}{# PRACUJE SE STRANKA #}
{# Projdi vsechna soustredeni #} {# Projdi vsechna soustredeni #}
{% for soustredeni in object_list %} {% for soustredeni in object_list %}
@ -40,12 +38,30 @@
<li> <li>
{{soustredeni.datum_zacatku}}&thinsp;&ndash;&thinsp;{{soustredeni.datum_konce}} {{soustredeni.datum_zacatku}}&thinsp;&ndash;&thinsp;{{soustredeni.datum_konce}}
</li> </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 %}
<li>
<a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">FOTOGALERIE: {{galerie}}</a>
{# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #}
</li>
{% endif %}
{% endfor %}
{% endif %}
{% if user.is_staff %}
<li>
<a href="../{{soustredeni.pk}}/fotogalerie/0/new/"> VYTVOŘIT NOVOU FOTOGALERII </a>
</li>
{% endif %}
</ul> </ul>
{% if user.is_authenticated %}
{# popis soustredeni #} {# popis soustredeni #}
{% if soustredeni.text %} {% if soustredeni.text %}
{% autoescape off %}{{soustredeni.text}}{% endautoescape %} {% autoescape off %}{{soustredeni.text}}{% endautoescape %}
{% endif %} {% endif %}
{% if user.is_authenticated %}
{# Účastníci #} {# Účastníci #}
<h3>Soustředění se zúčastnili tito účastníci:</h3> <h3>Soustředění se zúčastnili tito účastníci:</h3>
<ul> <ul>
@ -61,7 +77,5 @@
Žádná soustředění zatím neproběhla! Žádná soustředění zatím neproběhla!
{% endfor %} {% endfor %}
{#% else %}{% include 'seminar/pracuje_se.html' %}{% endif %#}
{% endblock %} {% endblock %}

69
seminar/templates/seminar/titulnistrana.html

@ -17,10 +17,36 @@ M&amp;M je korespondeční seminář. Několikrát do roka zdarma vydáváme ča
M&amp;M je taky soutěž. Můžeš vyhrát knížky, deskovky nebo dokonce dort. Můžeš se dostat na matfyz bez přijímaček. A především s námi můžeš jet na skvělé soustředění. M&amp;M je taky soutěž. Můžeš vyhrát knížky, deskovky nebo dokonce dort. Můžeš se dostat na matfyz bez přijímaček. A především s námi můžeš jet na skvělé soustředění.
</p> </p>
<table> <div class="novinky">
<tr> {% if dead %}
<td> <div class="odpocet">
<p><b>Do konce odeslání řešení 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' %}
<a href='/stare-novinky/'>Archiv novinek</a>
</div>
<div class="graf"> <div class="graf">
<img class="map" src="{% static 'images/graph.png' %}" width="505.0" height="612.0" usemap="#vuemap"> <img class="map" src="{% static 'images/graph.png' %}" width="505.0" height="612.0" usemap="#vuemap">
<map name="vuemap"> <map name="vuemap">
@ -46,43 +72,10 @@ M&amp;M je korespondeční seminář. Několikrát do roka zdarma vydáváme ča
<area href="/media/ilustrace/graf/dort.jpg" id="dort" shape="rect" coords="60,519,121,554"></area> <area href="/media/ilustrace/graf/dort.jpg" id="dort" shape="rect" coords="60,519,121,554"></area>
</map> </map>
</div> <span class="zjistit_vic">
<center>
<h3><a href="/co-je-MaM/uvod/">Zjistit víc!</a></h3> <h3><a href="/co-je-MaM/uvod/">Zjistit víc!</a></h3>
</center></p> </span>
</td>
<td valign="top">
{% if dead %}
<div class="odpocet">
<p><b>Do konce odeslání řešení 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> </div>
{% endif %}
{# Novinky #}
<h2>Novinky</h2>
{% include 'seminar/novinky.html' %}
<a href='/stare-novinky/'>Archiv novinek</a>
</td>
</tr>
</table>

4
seminar/urls.py

@ -1,3 +1,4 @@
from django.conf.urls import * # NOQA
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from . import views, export from . import views, export
@ -15,7 +16,8 @@ urlpatterns = patterns('',
url(r'^soustredeni/probehlo/$', views.SoustredeniListView.as_view(), url(r'^soustredeni/probehlo/$', views.SoustredeniListView.as_view(),
name = 'seminar_seznam_soustredeni'), name = 'seminar_seznam_soustredeni'),
url(r'^soustredeni/(?P<pk>\d+)/$', views.SoustredeniView.as_view(), name='seminar_soustredeni'), url(r'^soustredeni/probehlo/(?P<soustredeni>\d+)/$', views.SoustredeniView.as_view(), name='seminar_soustredeni'),
url(r'^soustredeni/(?P<soustredeni>\d+)/fotogalerie/', include('galerie.urls')),
url(r'^zadani/aktualni/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'), url(r'^zadani/aktualni/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
url(r'^zadani/temata/$', views.ZadaniTemataView, name='seminar_temata'), url(r'^zadani/temata/$', views.ZadaniTemataView, name='seminar_temata'),

Loading…
Cancel
Save