Browse Source

Merge branch 'master' into stable

remotes/origin/posli-mail-autorovi-korektury v1.7
Bc. Petr Pecha 9 years ago
parent
commit
1d78128ecb
  1. 15
      Makefile
  2. 2
      korektury/admin.py
  3. 4
      korektury/models.py
  4. 2
      korektury/static/korektury/opraf.js
  5. 2
      korektury/templates/korektury/opraf.html
  6. 4
      korektury/views.py
  7. 9
      mamweb/settings_common.py
  8. 14
      mamweb/static/css/mamweb.css
  9. 60
      seminar/admin.py
  10. 29
      seminar/migrations/0037_prispevek.py
  11. 18
      seminar/migrations/0038_change_meta_prispevek.py
  12. 34
      seminar/migrations/0039_pohadka.py
  13. 20
      seminar/migrations/0040_pohadka_nepovinny_autor.py
  14. 70
      seminar/migrations/0041_konfery.py
  15. 214
      seminar/models.py
  16. 22
      seminar/templates/seminar/archiv/cislo.html
  17. 24
      seminar/templates/seminar/archiv/prispevek.html
  18. 4
      seminar/templates/seminar/archiv/problem.html
  19. 6
      seminar/templates/seminar/archiv/problem_clanek.html
  20. 8
      seminar/templates/seminar/archiv/problem_uloha_tema.html
  21. 10
      seminar/templates/seminar/archiv/rocnik.html
  22. 6
      seminar/templates/seminar/archiv/temata.html
  23. 6
      seminar/templates/seminar/clanky/resitelske_clanky.html
  24. 4
      seminar/templates/seminar/cojemam/organizatori.html
  25. 3
      seminar/templates/seminar/novinky.html
  26. 4
      seminar/templates/seminar/pracuje_se.html
  27. 12
      seminar/templates/seminar/soustredeni/seznam_soustredeni.html
  28. 4
      seminar/templates/seminar/stare_novinky.html
  29. 10
      seminar/templates/seminar/stav_databaze.html
  30. 8
      seminar/templates/seminar/titulnistrana.html
  31. 6
      seminar/templates/seminar/zadani/AktualniVysledkovka.html
  32. 8
      seminar/templates/seminar/zadani/AktualniZadani.html
  33. 31
      seminar/templates/seminar/zadani/Temata.html
  34. 20
      seminar/urls.py
  35. 250
      seminar/views.py

15
Makefile

@ -44,7 +44,7 @@ clean_virtualenv:
rm -rf virtualenv-*.tar.gz
run:
./manage.py runserver_plus
./manage.py runserver
test:
./manage.py test -v2 seminar mamweb
@ -93,3 +93,16 @@ deploy_prod:
touch mamweb/wsgi.py
@echo Done.
# Sync media directory with atrey. Useful for local development with production database
# Does not sync Galerie and CACHE (too huge).
sync_media:
rsync -ave ssh --exclude Galerie --exclude CACHE\
atrey.karlin.mff.cuni.cz:/akce/MaM/WWW/mamweb-prod/media/ ./media/
# Downloads and restores production database to local database. PostgreSQL only.
sync_db:
scp atrey.karlin.mff.cuni.cz:`ssh atrey.karlin.mff.cuni.cz 'ls -v /akce/MaM/WWW/backups/mam-prod-*\.pgdump | tail -n 1'` \
./last.pgdump
pg_restore -c -d mam -U mam last.pgdump
# Sync database and media. See above lines
sync: sync_media sync_db

2
korektury/admin.py

@ -9,7 +9,7 @@ class KorekturovanePDFAdmin(VersionAdmin):
(None, {'fields': ['pdf', 'cas', 'stran', 'nazev', 'komentar']}),
# (u'PDF', {'fields': ['pdf']}),
]
list_display = ['pdf', 'cas', 'stran']
list_display = ['nazev', 'cas', 'stran']
list_filter = []
search_fields = []

4
korektury/models.py

@ -78,7 +78,9 @@ class KorekturovanePDF(models.Model):
"-density","180x180",
"-geometry"," 1024x1448",
self.pdf.path+"[%d]"%self.stran,
os.path.join(settings.KOREKTURY_IMG_DIR, "%s-%d.png"%(filename,self.stran))])
os.path.join(settings.BASE_DIR, "media",
settings.KOREKTURY_IMG_DIR,
"%s-%d.png"%(filename,self.stran))])
if res==1:
break
self.stran +=1

2
korektury/static/korektury/opraf.js

@ -126,7 +126,7 @@ function img_click(element, ev) {
function toggle_visibility(button){
var divbox = button.parentNode.parentNode.parentNode;
var id = divbox.id;
var text = document.getElementById(id+'-text');
var text = document.getElementById(id+'-body');
if (text.style.display == 'none'){
text.style.display = 'block';
}else {

2
korektury/templates/korektury/opraf.html

@ -150,6 +150,7 @@
</div>
</div>
<div class='corr-body' id='op{{o.id}}-body'>
<div id='op{{o.id}}-text'>{{o.text}}</div>
{% for k in o.komentare %}
@ -179,6 +180,7 @@
</div>
{% endfor %}
</div>
</div>
{% endfor %}
<script>

4
korektury/views.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.shortcuts import get_object_or_404, render
from django.views import generic
from django.utils.translation import ugettext as _
from django.conf import settings
@ -114,7 +114,7 @@ class KorekturyView(generic.TemplateView):
def get_context_data(self, **kwargs):
context = super(KorekturyView,self).get_context_data(**kwargs)
pdf = KorekturovanePDF.objects.get(id=self.kwargs['pdf'])
pdf = get_object_or_404(KorekturovanePDF, id=self.kwargs['pdf'])
context['pdf'] = pdf
context['img_name'] = os.path.split(pdf.pdf.path)[1].split('.')[0]
context['img_path'] = settings.KOREKTURY_IMG_DIR

9
mamweb/settings_common.py

@ -240,7 +240,8 @@ LOGGING = {
# MaM specific
SEMINAR_RESENI_DIR = os.path.join(BASE_DIR, 'media', 'reseni')
SEMINAR_KONFERY_DIR = os.path.join(BASE_DIR, 'media', 'konfery')
KOREKTURY_PDF_DIR = os.path.join(BASE_DIR, 'media', 'korektury','pdf')
KOREKTURY_IMG_DIR = os.path.join(BASE_DIR, 'media', 'korektury','img')
SEMINAR_RESENI_DIR = os.path.join('reseni')
SEMINAR_KONFERY_DIR = os.path.join('konfery')
KOREKTURY_PDF_DIR = os.path.join('korektury','pdf')
KOREKTURY_IMG_DIR = os.path.join('korektury','img')
CISLO_IMG_DIR = os.path.join('cislo','img')

14
mamweb/static/css/mamweb.css

@ -52,7 +52,7 @@ div.content {
padding: 15px 30px;
}
h2 {
h1 {
margin-top: 0px;
}
@ -92,6 +92,7 @@ h2 {
top: 40px;
left: 55px;
}
/*
#header h1 {
font-size: 130%;
position: absolute;
@ -99,6 +100,7 @@ h2 {
left: 30px;
height: 110px;
}
*/
#header img.header {
margin: -25px 20px 0px 0px;
height: 145px;
@ -160,7 +162,7 @@ div.menu li.selected a {
z-index: 15px;
}
h2 a:hover {
h1 a:hover {
text-decoration: none;
}
@ -263,7 +265,7 @@ div.zadani_azad_termin {
text-align: center;
}
#seznam_orgu h2 {
#seznam_orgu h1 {
text-align: center;
}
@ -495,7 +497,7 @@ div.zadani_azad_termin {
margin: 20px auto 0 auto;
}
.galerie h2 {
.galerie h1 {
text-align: center;
}
@ -679,3 +681,7 @@ div.zadani_azad_termin {
div.novinka_obrazek {
width: 100%;
}
div.org-text {
font-style: italic;
}

60
seminar/admin.py

@ -11,7 +11,7 @@ from django.db import models
from django.contrib.auth.models import User
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Novinky, Organizator
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Novinky, Organizator, Prispevek, Pohadka
from autocomplete_light import shortcuts as autocomplete_light
@ -296,6 +296,39 @@ class ReseniAdmin(VersionAdmin):
admin.site.register(Reseni, ReseniAdmin)
### Pohádka
class PohadkaAdminForm(forms.ModelForm):
class Meta:
model = Pohadka
exclude = []
autor = UserModelChoiceField(User.objects.filter(is_staff=True))
uloha = forms.ModelChoiceField(Problem.objects.filter(typ=Problem.TYP_ULOHA))
class PohadkaAdmin(VersionAdmin):
form = PohadkaAdminForm
def get_kod_ulohy(self, obj):
return obj.uloha.kod_v_rocniku()
get_kod_ulohy.short_description = u'Kód úlohy'
def get_rocnik(self, obj):
return obj.uloha.cislo_zadani.rocnik.rocnik
get_rocnik.short_description = u'Ročník'
list_display = ['__str__', 'get_rocnik', 'get_kod_ulohy', 'uloha', 'autor', 'timestamp']
get_form = get_form_predvypln_autora
class PohadkaKProblemuInline(admin.TabularInline):
form = PohadkaAdminForm
model = Pohadka
exclude = []
extra = 0
admin.site.register(Pohadka, PohadkaAdmin)
### Problem
from autocomplete_light.contrib.taggit_field import TaggitField, TaggitWidget
@ -348,8 +381,15 @@ 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', 'zamereni', 'cislo_zadani__cislo', 'cislo_zadani__rocnik']
def get_inline_instances(self, request, obj=None):
if obj and obj.typ == Problem.TYP_ULOHA:
inlines = [ReseniKProblemuInline, PohadkaKProblemuInline]
else:
inlines = [ReseniKProblemuInline]
return [inline(self.model, self.admin_site) for inline in inlines]
def get_queryset(self, request):
qs = super(ProblemZadanyAdmin, self).get_queryset(request)
return qs.filter(stav=Problem.STAV_ZADANY).annotate(pocet_reseni=Count('reseni'))
@ -360,6 +400,24 @@ create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'P
#admin.site.register(Problem, ProblemAdmin)
### Prispevek (k tematkum)
class PrispevekAdminForm(forms.ModelForm):
text_org = forms.CharField(widget=CKEditorWidget(), required=False,
**field_labels(Prispevek, 'text_org'))
text_resitel = forms.CharField(widget=CKEditorWidget(), required=False,
**field_labels(Prispevek, 'text_resitel'))
class Meta:
model = Prispevek
exclude = []
class PrispevekAdmin(VersionAdmin):
form = PrispevekAdminForm
list_display = ['nazev', 'problem', 'reseni', 'zverejnit']
admin.site.register(Prispevek, PrispevekAdmin)
### Soustredeni
class SoustredeniAdminForm(forms.ModelForm):

29
seminar/migrations/0037_prispevek.py

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('seminar', '0036_add_org_to_soustredeni'),
]
operations = [
migrations.CreateModel(
name='Prispevek',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('nazev', models.CharField(max_length=200, verbose_name=b'N\xc3\xa1zev')),
('text_org', models.TextField(null=True, verbose_name=b'Orgovsk\xc3\xbd text', blank=True)),
('text_resitel', models.TextField(null=True, verbose_name=b'\xc5\x98e\xc5\xa1itelsk\xc3\xbd text', blank=True)),
('zverejnit', models.BooleanField(verbose_name=b'Zve\xc5\x99ejnit?')),
('problem', models.ForeignKey(verbose_name=b'Probl\xc3\xa9m', to='seminar.Problem')),
('reseni', models.OneToOneField(null=True, blank=True, to='seminar.Reseni', verbose_name=b'\xc5\x98e\xc5\xa1en\xc3\xad')),
],
options={
'abstract': False,
},
),
]

18
seminar/migrations/0038_change_meta_prispevek.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('seminar', '0037_prispevek'),
]
operations = [
migrations.AlterModelOptions(
name='prispevek',
options={'verbose_name': 'P\u0159\xedsp\u011bvek k probl\xe9mu', 'verbose_name_plural': 'P\u0159\xedsp\u011bvky k probl\xe9m\u016fm'},
),
]

34
seminar/migrations/0039_pohadka.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('seminar', '0038_change_meta_prispevek'),
]
operations = [
migrations.CreateModel(
name='Pohadka',
fields=[
('id', models.AutoField(serialize=False, primary_key=True)),
('text', models.TextField(verbose_name='Text poh\xe1dky')),
('pred', models.BooleanField(default=True, verbose_name='P\u0159ed \xfalohou')),
('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Vytvo\u0159eno', editable=False, blank=True)),
('autor', models.ForeignKey(verbose_name=b'Autor poh\xc3\xa1dky', to=settings.AUTH_USER_MODEL)),
('uloha', models.ForeignKey(related_name='pohadky', verbose_name='\xdaloha', to='seminar.Problem')),
],
options={
'ordering': ['uloha__cislo_zadani', 'uloha__kod', '-pred'],
'db_table': 'seminar_pohadky',
'verbose_name': 'Poh\xe1dka',
'verbose_name_plural': 'Poh\xe1dky',
},
),
]

20
seminar/migrations/0040_pohadka_nepovinny_autor.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('seminar', '0039_pohadka'),
]
operations = [
migrations.AlterField(
model_name='pohadka',
name='autor',
field=models.ForeignKey(verbose_name=b'Autor poh\xc3\xa1dky', to=settings.AUTH_USER_MODEL, null=True),
),
]

70
seminar/migrations/0041_konfery.py

@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import seminar.models
class Migration(migrations.Migration):
dependencies = [
('seminar', '0040_pohadka_nepovinny_autor'),
]
operations = [
migrations.CreateModel(
name='Konfera',
fields=[
('id', models.AutoField(serialize=False, primary_key=True)),
('nazev', models.CharField(help_text='N\xe1zev konfery', max_length=40, verbose_name='n\xe1zev konfery')),
('popis', models.TextField(help_text='Popis konfery k zobrazen\xed na webu', verbose_name='popis konfery', blank=True)),
('abstrakt', models.TextField(help_text='Abstrakt konfery tak, jak byl uveden ve sborn\xedku', verbose_name='abstrakt', blank=True)),
('org_poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka ke konfe\u0159e(plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
('typ_prezentace', models.CharField(default=b'veletrh', max_length=16, verbose_name='typ prezentace', choices=[(b'veletrh', 'Veletrh (postery)'), (b'prezentace', 'Prezentace (p\u0159edn\xe1\u0161ka)')])),
('prezentace', models.FileField(help_text='Prezentace nebo fotka posteru', upload_to=seminar.models.generate_filename_konfera, verbose_name='prezentace')),
('materialy', models.FileField(help_text='Dal\u0161\xed materi\xe1ly ke konfe\u0159e zabalen\xe9 do jednoho souboru', upload_to=seminar.models.generate_filename_konfera, verbose_name='materialy')),
('organizator', models.ForeignKey(related_name='konfery', on_delete=django.db.models.deletion.SET_NULL, verbose_name='organiz\xe1tor', to='seminar.Organizator', null=True)),
],
options={
'db_table': 'seminar_konfera',
'verbose_name': 'Konfera',
'verbose_name_plural': 'Konfery',
},
),
migrations.CreateModel(
name='Konfery_Ucastnici',
fields=[
('id', models.AutoField(serialize=False, primary_key=True)),
('poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k \xfa\u010dasti (plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
('konfera', models.ForeignKey(verbose_name='konfera', to='seminar.Konfera')),
('resitel', models.ForeignKey(verbose_name='\u0159e\u0161itel', to='seminar.Resitel')),
],
options={
'ordering': ['konfera', 'resitel'],
'db_table': 'seminar_konfery_ucastnici',
'verbose_name': '\xda\u010dast na konfe\u0159e',
'verbose_name_plural': '\xda\u010dasti na konfe\u0159e',
},
),
migrations.AlterField(
model_name='problem',
name='typ',
field=models.CharField(default=b'uloha', max_length=32, verbose_name='typ probl\xe9mu', choices=[(b'uloha', '\xdaloha'), (b'tema', 'T\xe9ma'), (b'serial', 'Seri\xe1l'), (b'konfera', 'Konfera'), (b'org-clanek', 'Organiz\xe1torsk\xfd \u010dl\xe1nek'), (b'res-clanek', '\u0158e\u0161itelsk\xfd \u010dl\xe1nek')]),
),
migrations.AddField(
model_name='konfera',
name='prispevek',
field=models.ForeignKey(related_name='konfery', on_delete=django.db.models.deletion.SET_NULL, verbose_name='p\u0159\xedsp\u011bvek do \u010d\xedsla', to='seminar.Problem', help_text='\xda\u010dastnick\xfd p\u0159\xedp\u011bvek o konfe\u0159e', null=True),
),
migrations.AddField(
model_name='konfera',
name='soustredeni',
field=models.ForeignKey(related_name='konfery', on_delete=django.db.models.deletion.SET_NULL, verbose_name='soust\u0159ed\u011bn\xed', to='seminar.Soustredeni', null=True),
),
migrations.AddField(
model_name='konfera',
name='ucastnici',
field=models.ManyToManyField(help_text='Seznam \xfa\u010dastn\xedk\u016f konfery', to='seminar.Resitel', verbose_name='\xfa\u010dastn\xedci konfery', through='seminar.Konfery_Ucastnici'),
),
]

214
seminar/models.py

@ -16,7 +16,7 @@ from imagekit.processors import ResizeToFit, Transpose
from PIL import Image
import os
from functools import partial
#from functools import partial
from cStringIO import StringIO
from django.core.files.base import ContentFile
@ -402,12 +402,14 @@ class Problem(SeminarModelBase):
TYP_ULOHA = 'uloha'
TYP_TEMA = 'tema'
TYP_SERIAL = 'serial'
TYP_KONFERA = 'konfera'
TYP_ORG_CLANEK = 'org-clanek'
TYP_RES_CLANEK = 'res-clanek'
TYP_CHOICES = [
(TYP_ULOHA, u'Úloha'),
(TYP_TEMA, u'Téma'),
(TYP_SERIAL, u'Seriál'),
(TYP_KONFERA, u'Konfera'),
(TYP_ORG_CLANEK, u'Organizátorský článek'),
(TYP_RES_CLANEK, u'Řešitelský článek'),
]
@ -545,6 +547,10 @@ class Reseni(SeminarModelBase):
# PrilohaReseni method
# TODO vyresit partial, tak aby slo migrovat
#def generate_filename(self, filename, directory):
# Django 1.9 podporuje partial
def generate_filename(self, filename):
clean = filename.replace('/','-').replace('\0', '')
datedir = timezone.now().strftime('%Y-%m')
@ -553,6 +559,16 @@ def generate_filename(self, filename):
clean)
return os.path.join(settings.SEMINAR_RESENI_DIR, datedir, fname)
def generate_filename_konfera(self, filename):
clean = filename.replace('/','-').replace('\0', '')
datedir = timezone.now().strftime('%Y-%m')
fname = "%s_%s" % (
timezone.now().strftime('%Y-%m-%d-%H:%M'),
clean)
return os.path.join(settings.SEMINAR_KONFERY_DIR, datedir, fname)
# TODO vyresit partial tak, aby slo migrovat
# return os.path.join(directory, datedir, fname)
@reversion.register(ignore_duplicate_revisions=True)
@python_2_unicode_compatible
@ -580,6 +596,75 @@ class PrilohaReseni(SeminarModelBase):
return force_unicode(self.soubor)
@python_2_unicode_compatible
class Pohadka(SeminarModelBase):
u"""Kus pohádky před/za úlohou v čísle"""
class Meta:
db_table = 'seminar_pohadky'
verbose_name = u'Pohádka'
verbose_name_plural = u'Pohádky'
ordering = ['uloha__cislo_zadani', 'uloha__kod', '-pred']
# Interní ID
id = models.AutoField(primary_key=True)
text = models.TextField(u'Text pohádky')
uloha = models.ForeignKey(
Problem,
verbose_name=u'Úloha',
related_name='pohadky'
)
# Kusů pohádky je v čísle obvykle o 1 více, než úloh. Jeden bude za úlohou
# místo před ní.
pred = models.BooleanField(u'Před úlohou', default=True)
autor = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name="Autor pohádky",
# Při nahrávání z TeXu není vyplnění vyžadováno, v adminu je
null=True,
blank=False
)
timestamp = models.DateTimeField(
u'Vytvořeno',
default=timezone.now,
blank=True,
editable=False
)
def __str__(self):
uryvek = self.text if len(self.text) < (50-3) else self.text[:50]+"..."
return force_unicode(uryvek)
@reversion.register(ignore_duplicate_revisions=True)
class Prispevek(SeminarModelBase):
problem = models.ForeignKey(Problem, verbose_name='Problém') # TODO autokompleet
nazev = models.CharField('Název', max_length=200)
reseni = models.OneToOneField(Reseni, verbose_name='Řešení',
blank = True, null = True)
text_org = models.TextField('Orgovský text', blank = True, null = True)
text_resitel = models.TextField('Řešitelský text', blank = True, null = True)
zverejnit = models.BooleanField('Zveřejnit?')
class Meta:
verbose_name = 'Příspěvek k problému'
verbose_name_plural = 'Příspěvky k problémům'
def __unicode__(self):
if self.reseni:
return force_unicode(self.nazev) + ' (' + \
force_unicode(self.reseni.resitel) + ') <Problem: ' + \
force_unicode(self.problem) + '>'
else:
return force_unicode(self.nazev) + ' <Problem: ' + \
force_unicode(self.problem) + '>'
@reversion.register(ignore_duplicate_revisions=True)
@python_2_unicode_compatible
class Organizator(models.Model):
@ -736,69 +821,70 @@ class Soustredeni_Organizatori(models.Model):
#@reversion.register(ignore_duplicate_revisions=True)
#@python_2_unicode_compatible
#class Konfera(models.Model):
# class Meta:
# db_table = 'seminar_konfera'
# verbose_name = u'Konfera'
# verbose_name_plural = u'Konfery'
# # Interní ID
# id = models.AutoField(primary_key = True)
# nazev = models.CharField(u'název konfery', max_length=40, help_text = u'Název konfery')
# popis = models.TextField(u'popis konfery', blank=True,
# help_text=u'Popis konfery k zobrazení na webu')
# abstrakt = models.TextField(u'abstrakt', blank=True,
# help_text=u'Abstrakt konfery tak, jak byl uveden ve sborníku')
# organizator = models.ForeignKey(Organizator, verbose_name=u'organizátor', related_name='konfery',
# on_delete = models.SET_NULL, null=True)
# ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci konfery',
# help_text=u'Seznam účastníků konfery', through='Konfery_Ucastnici')
# soustredeni = models.ForeignKey(Soustredeni, verbose_name=u'soustředění', related_name='konfery',
# on_delete = models.SET_NULL, null=True)
# org_poznamka = models.TextField(u'neveřejná poznámka', blank=True,
# help_text=u'Neveřejná poznámka ke konfeře(plain text)')
# #prispevek #TODO
# TYP_VELETRH = 'veletrh'
# TYP_PREZENTACE = 'prezentace'
# TYP_CHOICES = [
# (TYP_VELETRH, u'Veletrh (postery)'),
# (TYP_PREZENTACE, u'Prezentace (přednáška)'),
# ]
# typ_prezentace = models.CharField(u'typ prezentace', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_VELETRH)
# prezentace = models.FileField(u'prezentace',help_text = u'Prezentace nebo fotka posteru',
# upload_to = partial(generate_filename,directory=settings.SEMINAR_KONFERY_DIR))
# materialy = models.FileField(u'materialy',help_text = u'Další materiály ke konfeře zabalené do jednoho souboru',
# upload_to = partial(generate_filename,directory=settings.SEMINAR_KONFERY_DIR))
#
# def __str__(self):
# return force_unicode(u"%s: (%s)" % (self.nazev, self.soustredeni))
#
#
#
#@reversion.register(ignore_duplicate_revisions=True)
#@python_2_unicode_compatible
#class Konfery_Ucastnici(models.Model):
#
# class Meta:
# db_table = 'seminar_konfery_ucastnici'
# verbose_name = u'Účast na konfeře'
# verbose_name_plural = u'Účasti na konfeře'
# ordering = ['konfera', 'resitel']
#
# # Interní ID
# id = models.AutoField(primary_key = True)
#
# resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel')
#
# konfera = models.ForeignKey(Konfera, verbose_name=u'konfera')
#
# poznamka = models.TextField(u'neveřejná poznámka', blank=True,
# help_text=u'Neveřejná poznámka k účasti (plain text)')
#
# def __str__(self):
# return force_unicode(u'%s na %s' % (self.resitel, self.konfera, ))
# # NOTE: Poteciální DB HOG bez select_related
@reversion.register(ignore_duplicate_revisions=True)
@python_2_unicode_compatible
class Konfera(models.Model):
class Meta:
db_table = 'seminar_konfera'
verbose_name = u'Konfera'
verbose_name_plural = u'Konfery'
# Interní ID
id = models.AutoField(primary_key = True)
nazev = models.CharField(u'název konfery', max_length=40, help_text = u'Název konfery')
popis = models.TextField(u'popis konfery', blank=True,
help_text=u'Popis konfery k zobrazení na webu')
abstrakt = models.TextField(u'abstrakt', blank=True,
help_text=u'Abstrakt konfery tak, jak byl uveden ve sborníku')
organizator = models.ForeignKey(Organizator, verbose_name=u'organizátor', related_name='konfery',
on_delete = models.SET_NULL, null=True)
ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci konfery',
help_text=u'Seznam účastníků konfery', through='Konfery_Ucastnici')
soustredeni = models.ForeignKey(Soustredeni, verbose_name=u'soustředění', related_name='konfery',
on_delete = models.SET_NULL, null=True)
org_poznamka = models.TextField(u'neveřejná poznámka', blank=True,
help_text=u'Neveřejná poznámka ke konfeře(plain text)')
prispevek = models.ForeignKey(Problem, verbose_name=u'příspěvek do čísla', related_name='konfery',
help_text=u'Účastnický přípěvek o konfeře',on_delete = models.SET_NULL, null=True)
TYP_VELETRH = 'veletrh'
TYP_PREZENTACE = 'prezentace'
TYP_CHOICES = [
(TYP_VELETRH, u'Veletrh (postery)'),
(TYP_PREZENTACE, u'Prezentace (přednáška)'),
]
typ_prezentace = models.CharField(u'typ prezentace', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_VELETRH)
prezentace = models.FileField(u'prezentace',help_text = u'Prezentace nebo fotka posteru',
upload_to = generate_filename_konfera)
materialy = models.FileField(u'materialy',help_text = u'Další materiály ke konfeře zabalené do jednoho souboru',
upload_to = generate_filename_konfera)
def __str__(self):
return force_unicode(u"%s: (%s)" % (self.nazev, self.soustredeni))
@reversion.register(ignore_duplicate_revisions=True)
@python_2_unicode_compatible
class Konfery_Ucastnici(models.Model):
class Meta:
db_table = 'seminar_konfery_ucastnici'
verbose_name = u'Účast na konfeře'
verbose_name_plural = u'Účasti na konfeře'
ordering = ['konfera', 'resitel']
# Interní ID
id = models.AutoField(primary_key = True)
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel')
konfera = models.ForeignKey(Konfera, verbose_name=u'konfera')
poznamka = models.TextField(u'neveřejná poznámka', blank=True,
help_text=u'Neveřejná poznámka k účasti (plain text)')
def __str__(self):
return force_unicode(u'%s na %s' % (self.resitel, self.konfera, ))
# NOTE: Poteciální DB HOG bez select_related
@python_2_unicode_compatible

22
seminar/templates/seminar/archiv/cislo.html

@ -2,34 +2,38 @@
{% block content %}
<div>
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Číslo {{ cislo }}
{% endblock %}{% endblock %}
</h2>
</h1>
{% if cislo.pdf %}
<p><a href='{{ cislo.pdf.url }}'>Číslo v pdf</a>
{% endif %}
<p><a href='{{ cislo.rocnik.verejne_url }}'>Ročník {{ cislo.rocnik }}</a>
<h3>Zadané problémy</h3>
<h2>Zadané problémy</h2>
<ul>
{% for p in v_cisle_zadane %}
<li>{# TODO zprovoznit odkazy, až bude na co <a href='{{ p.verejne_url }}'> #}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{# </a> #}
<li>{# TODO zprovoznit odkazy i pro účastníky, až bude na co #}
{% if user.is_staff %}
<a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff %}</a>{% endif %}
{% endfor %}
</ul>
<h3>Řešené problémy</h3>
<h2>Řešené problémy</h2>
<ul>
{% for p in resene_problemy %}
<li>{# TODO zprovoznit odkazy, až bude na co <a href='{{ p.verejne_url }}'> #}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{# </a> #}
<li>{# TODO zprovoznit odkazy i pro účastníky, až bude na co #}
{% if user.is_staff %}
<a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff %}</a>{% endif %}
{% endfor %}
</ul>
{% if user.is_staff %}
<div class="mam-org-only">
<h3> Orgovské odkazy </h3>
<h2> Orgovské odkazy </h2>
<ul>
<li><a href="obalky.pdf">Obálky (PDF)</a></li>
<li><a href="tituly.tex">Tituly (TeX)</a></li>
@ -40,11 +44,11 @@
{% endif %}
{% if cislo.verejna_vysledkovka %}
<h3>Výsledkovka</h3>
<h2>Výsledkovka</h2>
{% else %}
{% if user.is_staff %}
<div class='mam-org-only'>
<h3>Výsledkovka (neveřejná)</h3>
<h2>Výsledkovka (neveřejná)</h2>
{% endif %}
{% endif %}

24
seminar/templates/seminar/archiv/prispevek.html

@ -0,0 +1,24 @@
{% extends "seminar/archiv/base_temata.html" %}
{% block title %}
{{prispevek.nazev}}
{% endblock title %}
{% block content %}
{% if not prispevek.zverejnit %}<div class="mam-org-only">{% endif %}
<h1>{{prispevek.nazev}}</h1>
<h2>{{titul}} {{prispevek.reseni.resitel}}</h2>
<h3>Příspěvek k tématu <a href="..">{{prispevek.problem.nazev}}</a></h3>
{% if prispevek.reseni.body %}
<div class="body">({{prispevek.reseni.body}} b)</div>
{% endif %}
{% if prispevek.text_org %}
<div class="org-text">{% autoescape off %}{{prispevek.text_org}}{% endautoescape %}</div>
{% endif %}
{% if prispevek.text_resitel %}
{% autoescape off %}{{prispevek.text_resitel}}{% endautoescape %}
{% endif %}
{% if not prispevek.zverejnit %}</div>{% endif %}
{% endblock content %}

4
seminar/templates/seminar/archiv/problem.html

@ -10,10 +10,10 @@
{% if user.is_staff %}
<div class='mam-org-only'>
<h3>Text - org</h3>
<h2>Text - org</h2>
{{ problem.text_org |safe }}
<h3>Diskuse - org</h3>
<h2>Diskuse - org</h2>
{% render_comment_list for object %}
{% render_comment_form for object %}

6
seminar/templates/seminar/archiv/problem_clanek.html

@ -3,12 +3,12 @@
{% block problem %}
{% if problem.cislo_zadani %}
<h2>
<h1>
{{ problem.nazev_typu }}:
{% block nadpis1a %}{% block nadpis1b %}
{{ problem.nazev }}
{% endblock %}{% endblock %}
</h2>
</h1>
<div class='problem-autori'>
{% if problem.typ == 'res-clanek' %}
@ -30,7 +30,7 @@
{% else %}
{# TODO ? #}
<h2>Problém {{ problem.nazev }}</h2>
<h1>Problém {{ problem.nazev }}</h1>
{% endif %}
{{ problem.text_zadani |safe }}

8
seminar/templates/seminar/archiv/problem_uloha_tema.html

@ -1,11 +1,11 @@
{% extends "seminar/archiv/problem.html" %}
{% block problem %}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
{{ problem.nazev_typu }} {{ problem.kod_v_rocniku }}: {{ problem.nazev }} {{ problem.body_v_zavorce }}
{% endblock %}{% endblock %}
</h2>
</h1>
{% if problem.cislo_zadani %}
<p>Zadáno v čísle <a href='{{ problem.cislo_zadani.verejne_url }}'>{{ problem.cislo_zadani.kod }}</a>.
{% endif %}
@ -13,10 +13,10 @@
<p>Řešeno v čísle <a href='{{ problem.cislo_reseni.verejne_url }}'>{{ problem.cislo_reseni.kod }}</a>.
{% endif %}
<h3>Zadání</h3>
<h2>Zadání</h2>
{{ problem.text_zadani |safe }}
{% if problem.text_reseni %}
<h3>Řešení</h3>
<h2>Řešení</h2>
{{ problem.text_reseni |safe }}
{% endif %}

10
seminar/templates/seminar/archiv/rocnik.html

@ -2,11 +2,11 @@
{% block content %}
<div>
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Ročník {{ rocnik.roman }}
{% endblock %}{% endblock %}
</h2>
</h1>
<p>Ročník číslo {{ rocnik.rocnik }} ({{ rocnik.prvni_rok }}/{{ rocnik.druhy_rok }})
@ -20,7 +20,7 @@
</ul>
{% if temata_v_rocniku %}
<h3>Témata</h3>
<h2>Témata</h2>
<ul>
{% for tema in temata_v_rocniku %}
<li>{# TODO zprovoznit odkaz až bude na co <a href="{{ tema.verejne_url }}"> #}{{ tema.kod_v_rocniku }}: {{ tema.nazev }}{# TODO </a> #}
@ -29,13 +29,13 @@
{% endif %}
{% if vysledkovka %}
<h3>Výsledková listina</h3>
<h2>Výsledková listina</h2>
{% include "seminar/vysledkovka_rocnik.html" %}
{% endif %}
{% if user.is_staff and vysledkovka_s_neverejnymi %}
<div class='mam-org-only'>
<h3>Výsledková listina včetně neveřejných bodů</h3>
<h2>Výsledková listina včetně neveřejných bodů</h2>
{% with vysledkovka_s_neverejnymi as vysledkovka %}
{% include "seminar/vysledkovka_rocnik.html" %}
{% endwith %}

6
seminar/templates/seminar/archiv/temata.html

@ -1,17 +1,17 @@
{% extends "seminar/archiv/base_temata.html" %}
{% block content %}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Archiv témat
{% endblock %}{% endblock%}
</h2>
</h1>
{% for tema in object_list %}
{% with tema.cislo_zadani.rocnik.rocnik as rocnik %}
{% ifchanged rocnik %}
{% if not forloop.first %}</ul>{% endif %}
<h3>{{ rocnik }}. ročník</h3>
<h2>{{ rocnik }}. ročník</h2>
<ul>
{% endifchanged %}
<li>

6
seminar/templates/seminar/clanky/resitelske_clanky.html

@ -10,17 +10,17 @@
{% block content %}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Řešitelské články
{% endblock %}{% endblock %}
</h2>
</h1>
{% for clanek in object_list %}
{% with clanek.cislo_zadani.rocnik.rocnik as rocnik %}
{% ifchanged rocnik %}
{% if not forloop.first %}</ul>{% endif %}
<h3>{{ rocnik }}. ročník</h3>
<h2>{{ rocnik }}. ročník</h2>
<ul>
{% endifchanged %}
<li>

4
seminar/templates/seminar/cojemam/organizatori.html

@ -24,13 +24,13 @@
<br>
{% endif %}
{% for org in object_list %}
<h2>
<h1>
{{org.user.first_name}}
{% if org.prezdivka %}
&bdquo;{{org.prezdivka}}&ldquo;
{% endif %}
{{org.user.last_name}}
</h2>
</h1>
<table>
<tr>
<td>

3
seminar/templates/seminar/novinky.html

@ -3,6 +3,9 @@
<div>
{% if not novinka.zverejneno and user.is_staff %}
<div class="mam-org-only">
<ul>
<li><a href="/admin/seminar/novinky/{{novinka.pk}}">Upravit novinku</a>
</ul>
{% endif %}
{% if novinka.zverejneno or user.is_staff %}
{# datum #}

4
seminar/templates/seminar/pracuje_se.html

@ -1,11 +1,11 @@
{% load staticfiles %}
{% block content %}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Tady se pracuje
{% endblock %}{% endblock %}
</h2>
</h1>
<p>
Na této stránce velmi intenzivně pracujeme.

12
seminar/templates/seminar/soustredeni/seznam_soustredeni.html

@ -14,10 +14,6 @@
{% endblock %}{% endblock %}
{% block content %}
<em>
Na galeriích ze soustředění a dalších informacích ještě pracujeme.
</em><br><br>
{# Projdi vsechna soustredeni #}
{% for soustredeni in object_list %}
{# Kdyz je verejne -> zobraz #}
@ -27,10 +23,10 @@
<!--Groups of user: {{user.groups.all}} <br>-->
{% endif %}
{# misto soustredeni TODO upravit#}
<h2>
<h1>
{{soustredeni.get_typ_display}}
{{soustredeni.misto}}
</h2>
</h1>
<ul>
<li>
{{soustredeni.datum_zacatku}}&thinsp;&ndash;&thinsp;{{soustredeni.datum_konce}}
@ -62,7 +58,7 @@
{% if user.is_staff %}
<div class="mam-org-only">
{# Účastníci #}
<h3>Soustředění se zúčastnili tito účastníci:</h3>
<h2>Soustředění se zúčastnili tito účastníci:</h2>
<p>
{% for i in soustredeni.soustredeni_ucastnici_set.all %}
{{i.resitel}}{% if forloop.last %}.{% else %},{% endif %}
@ -70,7 +66,7 @@
Nic!
{% endfor %}
</p>
<h3>Soustředění se účastnili tito organizátoři:</h3>
<h2>Soustředění se účastnili tito organizátoři:</h2>
<p>
{% for i in soustredeni.soustredeni_organizatori_set.all %}
{{i.organizator}}{% if forloop.last %}.{% else %},{% endif %}

4
seminar/templates/seminar/stare_novinky.html

@ -2,11 +2,11 @@
{% block content %}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Archiv novinek
{% endblock %}{% endblock %}
</h2>
</h1>
{% include 'seminar/novinky.html' %}

10
seminar/templates/seminar/stav_databaze.html

@ -2,13 +2,13 @@
{% block content %}
<div>
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Stav databáze
{% endblock %}{% endblock %}
</h2>
</h1>
<h3>Řešitelé</h3>
<h2>Řešitelé</h2>
<div>Řešitelů: {{ resitele |length}} ({{ muzi |length}} mužů, {{ zeny |length}} žen)</div>
<div>Křestní jména mužů:</div>
@ -16,9 +16,9 @@
<div>Křestní jména žen:</div>
<p><code>{% for n, c in jmena_zen.items %}{{ n }} ({{ c }}), {% endfor %}</code>
<h3>Nastavení</h3>
<h2>Nastavení</h2>
<h3>Problémy</h3>
<h2>Problémy</h2>
{% for p in problemy %}
<div>{{ p |safe }}</div>
{% endfor %}

8
seminar/templates/seminar/titulnistrana.html

@ -6,11 +6,11 @@
{% block content %}
{# Uvitaci text #}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Vítej!
{% endblock %}{% endblock %}
</h2>
</h1>
<p>
M&amp;M je korespondeční seminář. Několikrát do roka zdarma vydáváme časopis a v něm zajímavé podněty k přemýšlení. Ty na ně můžeš reagovat.<br>
@ -26,7 +26,7 @@ M&amp;M je korespondeční seminář. Několikrát do roka zdarma vydáváme ča
{% endif %}
{# Novinky #}
<h2>Novinky</h2>
<h1>Novinky</h1>
{% include 'seminar/novinky.html' %}
<a href='/stare-novinky/'>Archiv novinek</a>
@ -59,7 +59,7 @@ M&amp;M je korespondeční seminář. Několikrát do roka zdarma vydáváme ča
</map>
<span class="zjistit_vic">
<h3><a href="/co-je-MaM/uvod/">Zjistit víc!</a></h3>
<h2><a href="/co-je-MaM/uvod/">Zjistit víc!</a></h2>
</span>
</div>

6
seminar/templates/seminar/zadani/AktualniVysledkovka.html

@ -10,11 +10,11 @@
{% block content %}
{% with nastaveni.aktualni_rocnik as rocnik %}
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Výsledky
{% endblock %}{% endblock %}
</h2>
</h1>
{% if vysledkovka %}
{% include "seminar/vysledkovka_rocnik.html" %}
@ -24,7 +24,7 @@
{% if user.is_staff and vysledkovka_s_neverejnymi %}
<div class='mam-org-only'>
<h2>Výsledky včetně neveřejných</h2>
<h1>Výsledky včetně neveřejných</h1>
{% with vysledkovka_s_neverejnymi as vysledkovka %}
{% include "seminar/vysledkovka_rocnik.html" %}
{% endwith %}

8
seminar/templates/seminar/zadani/AktualniZadani.html

@ -32,7 +32,7 @@
{% for sada in jednorazove_problemy %}
{# podnadpisy, kdyz neni zakomentuje se nadpis #}
{% if not sada %}<!--{% endif %}
<h3>{% cycle 'Úlohy' 'Seriál' %}</h3>
<h2>{% cycle 'Úlohy' 'Seriál' %}</h2>
{% if not sada %}-->{% endif %}
{# publikace jednotlivych zadani #}
{% for problem in sada %}
@ -41,7 +41,7 @@
{% endfor %}
{# TODO použít {{problem.kod_v_rocniku}} ? vrací 4.u1 místo 4.1 #}
<h4>{{problem.cislo_zadani.cislo}}.{{problem.kod}} {{problem.nazev}} {{ problem.body_v_zavorce }}</h4>
<h3>{{problem.cislo_zadani.cislo}}.{{problem.kod}} {{problem.nazev}} {{ problem.body_v_zavorce }}</h3>
{% autoescape off %}{{problem.text_zadani}}{% endautoescape %}
<hr>
{% endfor %}
@ -51,11 +51,11 @@
{% if user.is_staff and not verejne%}</div>{% endif %}
{% else %}
<h3>Aktuálně nejsou zveřejněny žádné úlohy</h3>
<h2>Aktuálně nejsou zveřejněny žádné úlohy</h2>
{% endif %}
<h3>Témata</h3>
<h2>Témata</h2>
<ul>
{% for problem in temata %}
{# TODO použít {{problem.kod_v_rocniku}} ? vrací t4 místo 4 #}

31
seminar/templates/seminar/zadani/Temata.html

@ -10,11 +10,11 @@
{% block content %}
{% with nastaveni.aktualni_rocnik as ar %}
<div>
<h2>
<h1>
{% block nadpis1a %}{% block nadpis1b %}
Témata
{% endblock %}{% endblock %}
</h2>
</h1>
<p>
Témata jsou hlavním obsahem časopisu M&amp;M. Obvykle představují
@ -30,6 +30,7 @@
Letos jsme pro tebe připravili tato témata:
</p>
{% endif %}
{# seznam temat s odkazy doprostred teto stranky #}
<ul>
{% for problem in temata %}
{# TODO použít {{problem.kod_v_rocniku}} ? vrací t4 místo 4 #}
@ -38,11 +39,35 @@
</li>
{% endfor %}
</ul>
{# nahled kazdeho tematu #}
{% for problem in temata %}
{# TODO použít {{problem.kod_v_rocniku}} ? vrací t4 místo 4 #}
<a name="t{{problem.kod}}"></a>
<a href="{{problem.verejne_url}}"><h3>Téma {{problem.kod}}: {{problem.nazev}}</h3></a>
<h2>Téma {{problem.kod}}: {{problem.nazev}}</h2>
{% autoescape off %}{{problem.text_zadani}}{% endautoescape %}
{# kdyz je reseni pridej odkaz na samostatnou stranku s tematem #}
{% if problem.text_reseni %}
<p><a href="{{problem.verejne_url}}">Více</a></p>
{% else %}
<p><a href="{{problem.verejne_url}}">Stejně</a></p>
{% endif%}
{# prime odkazy na prispevky #}
{% if problem.prispevky %}
<h3> K&nbsp;tématu přišly a zveřejnili jsme následující příspěvky</h3>
<div class="seznam_prispeveku">
<ul>
{% for prispevek in problem.prispevky %}
{% if not prispevek.zverejnit %}<div class=mam-org-only>{% endif %}
<li><a href="{{problem.verejne_url}}{{prispevek.id}}">
{{prispevek.nazev}},
{{prispevek.reseni.resitel}}
({{prispevek.reseni.body}} b)
</a>
{% if not prispevek.zverejnit %}</div>{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
<hr>
{% empty %}
Aktuálně nejsou zadána žádná témata k řešení.

20
seminar/urls.py

@ -4,38 +4,49 @@ from django.contrib.auth.decorators import user_passes_test
from . import views, export
from utils import staff_member_required
from prednasky.views import newPrednaska, Prednaska_hotovo
from django.views.generic.base import RedirectView
staff_member_required = user_passes_test(lambda u: u.is_staff)
urlpatterns = [
# prednasky
url(r'^prednasky/$', newPrednaska),
url(r'^prednasky/hotovo$', Prednaska_hotovo),
#url(r'^prednasky/$', newPrednaska),
#url(r'^prednasky/hotovo$', Prednaska_hotovo),
# REDIRECTy
url(r'^jak-resit/$', RedirectView.as_view(url='/co-je-MaM/jak-resit/')),
# Organizatori
url(r'^co-je-MaM/organizatori/$', views.CojemamOrganizatoriView.as_view(), name='organizatori'),
url(r'^co-je-MaM/organizatori/organizovali/$', views.CojemamOrganizatoriStariView.as_view(), name='stari_organizatori'),
# Archiv
url(r'^archiv/cisla/$', views.CislaView.as_view()),
url(r'^archiv/temata/$', views.ArchivTemataView.as_view()),
url(r'^rocnik/(?P<rocnik>\d+)/$', views.RocnikView.as_view(), name='seminar_rocnik'),
url(r'^cislo/(?P<rocnik>\d+)\.(?P<cislo>[0-9-]+)/$', views.CisloView.as_view(), name='seminar_cislo'),
url(r'^problem/(?P<pk>\d+)/$', views.ProblemView.as_view(), name='seminar_problem'),
url(r'^problem/(?P<pk>\d+)/(?P<prispevek>\d+)/$', views.PrispevekView.as_view(), name='seminar_problem_prispevek'),
# Soustredeni
url(r'^soustredeni/probehlo/$', views.SoustredeniListView.as_view(),
name = 'seminar_seznam_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')),
# Zadani
url(r'^zadani/aktualni/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
url(r'^zadani/temata/$', views.ZadaniTemataView, name='seminar_temata'),
url(r'^zadani/vysledkova-listina/$', views.ZadaniAktualniVysledkovkaView, name='seminar_vysledky'),
url(r'^$', views.TitulniStranaView.as_view(), name='titulni_strana'),
url(r'^stare-novinky/$', views.StareNovinkyView.as_view(), name='stare_novinky'),
# Clanky
url(r'^clanky/resitel/$', views.ClankyResitelView.as_view(), name='clanky_resitel'),
url(r'^clanky/org/$', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'),
# Aesop
url(r'^aesop-export/mam-rocnik-(?P<prvni_rok>\d+)\.csv$', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'),
url(r'^aesop-export/mam-sous-(?P<datum_zacatku>[\d-]+)\.csv$', export.ExportSousView.as_view(), name='seminar_export_sous'),
url(r'^aesop-export/index.csv$', export.ExportIndexView.as_view(), name='seminar_export_index'),
@ -52,6 +63,11 @@ urlpatterns = [
staff_member_required(views.StavDatabazeView), name='stav_databaze'),
url(r'^cislo/(?P<rocnik>\d+).(?P<cislo>[0-9-]+)/obalkovani$',
staff_member_required(views.obalkovaniView), name='seminar_cislo_resitel_obalkovani'),
url(r'^cislo/(?P<rocnik>\d+).(?P<cislo>[0-9-]+)/tex-download.json$',
staff_member_required(views.texDownloadView), name='seminar_tex_download'),
url(r'^soustredeni/(?P<soustredeni>\d+)/obalky.pdf',
staff_member_required(views.soustredeniObalkyView), name='seminar_soustredeni_obalky'),
url(r'^tex-upload/login/$', views.LoginView, name='seminar_login'),
url(r'^tex-upload/$', staff_member_required(views.texUploadView), name='seminar_tex_upload'),
]

250
seminar/views.py

@ -1,15 +1,17 @@
# coding:utf-8
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse
from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.views import generic
from django.utils.translation import ugettext as _
from django.http import Http404
from django.db.models import Q
from django.views.decorators.csrf import ensure_csrf_cookie
from django.contrib.auth import authenticate, login
from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici
from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Prispevek
from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from . import utils
@ -21,6 +23,10 @@ import shutil
import os
from django.conf import settings
import unicodedata
import json
import traceback
import sys
def verejna_temata(rocnik):
"""Vrací queryset zveřejněných témat v daném ročníku.
@ -45,9 +51,15 @@ def AktualniZadaniView(request):
def ZadaniTemataView(request):
nastaveni = get_object_or_404(Nastaveni)
temata = verejna_temata(nastaveni.aktualni_rocnik)
for t in temata:
if request.user.is_staff:
t.prispevky = t.prispevek_set.filter(problem=t)
else:
t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True)
return render(request, 'seminar/zadani/Temata.html',
{
'temata': verejna_temata(nastaveni.aktualni_rocnik)
'temata': temata,
}
)
@ -241,6 +253,45 @@ class ProblemView(generic.DetailView):
context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni')
return context
class PrispevekView(generic.DetailView):
model = Prispevek
template_name = 'seminar/archiv/prispevek.html'
# Vlastni ziskavani objektu z databaze podle prispevku
# pokud je prispevek neverejny zobrazi se jenom orgum
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
problem_arg = self.kwargs.get('pk')
prispevek_arg = self.kwargs.get('prispevek')
queryset = queryset.filter(pk=prispevek_arg)
try:
obj = queryset.get()
except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
if self.request.user.is_staff or obj.zverejnit:
return obj
else:
raise Http404()
def get_context_data(self, **kwargs):
context = super(PrispevekView, self).get_context_data(**kwargs)
# snaho o ziskani titulu
titul = ''
try:
resitel = context['prispevek'].reseni.resitel
cislo = context['prispevek'].reseni.cislo_body
body = VysledkyKCisluOdjakziva.objects.get(resitel=resitel,
cislo=cislo).body
titul = resitel.get_titul(body)
except:
pass
context['titul'] = titul
return context
class RadekVysledkovky(object):
@ -408,11 +459,22 @@ def obalkovaniView(request, rocnik, cislo):
rocnik = Rocnik.objects.get(rocnik=rocnik)
cislo = Cislo.objects.get(rocnik=rocnik, cislo=cislo)
reseni = Reseni.objects.filter(cislo_body=cislo)
serazena_reseni = sorted(reseni, key=lambda r: (r.resitel.prijmeni, r.resitel.jmeno, r.problem.typ, r.problem.kod))
reseni = (
Reseni.objects.filter(cislo_body=cislo)
.order_by(
'resitel__prijmeni',
'resitel__jmeno',
'problem__typ',
'problem__kod'
)
)
problemy = sorted(set(r.problem for r in reseni), key=lambda p: (p.typ, p.kod))
return render(request, 'seminar/archiv/cislo_obalkovani.html', {'cislo': cislo, 'problemy': problemy, 'reseni': serazena_reseni})
return render(
request,
'seminar/archiv/cislo_obalkovani.html',
{'cislo': cislo, 'problemy': problemy, 'reseni': reseni}
)
### Tituly
@ -438,7 +500,7 @@ def TitulyView(request, rocnik, cislo):
else:
broken = True
return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele,'broken':broken})
return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele,'broken':broken},content_type="text/plain")
### Soustredeni
@ -487,3 +549,177 @@ def StavDatabazeView(request):
'jmena_muzu': utils.histogram([r.jmeno for r in muzi]),
'jmena_zen': utils.histogram([r.jmeno for r in zeny]),
})
@ensure_csrf_cookie
def LoginView(request):
"""Pro přihlášení při nahrávání z texu"""
q = request.POST
# nastavení cookie csrftoken
if not q:
return JsonResponse({"ok": 1})
if "username" in q:
username = q["username"]
password = q["password"]
user = authenticate(username=username, password=password)
if user is not None and user.is_staff:
login(request, user)
return JsonResponse({"ok": 1})
else:
return JsonResponse({"error": "Neplatné uživatelské jméno nebo heslo"})
@ensure_csrf_cookie
def texUploadView(request):
def uloz_soubory(files, rocnik, cislo):
for filename, f in files:
path = os.path.join(
settings.MEDIA_ROOT,
settings.CISLO_IMG_DIR,
rocnik,
cislo,
filename
)
adresar = os.path.dirname(path)
if not os.path.exists(adresar):
os.makedirs(adresar)
with open(path, "wb+") as fout:
for chunk in f.chunks():
fout.write(chunk)
q = request.POST
# nastavení cookie csrftoken
if not q:
return JsonResponse({"ok": 1})
# Odchytíme všechny výjimky a traceback pošleme v odpovědi
try:
meta = json.loads(q["meta"])
html = q["html"]
if meta["typ"] in ["uloha", "serial", "reseni"]:
# Uložíme soubory
if meta["typ"] != "reseni":
c = meta["cislo"]
else:
# Řešení má nastavené číslo svojí úlohy, ale obrázky jsou
# ukládány do čísla, kde řešení vyšlo
c = meta["cislo_reseni"]
uloz_soubory(request.FILES.items(), meta["rocnik"], c)
# Zjistíme typ ukládaného problému
typy = {
"uloha": Problem.TYP_ULOHA,
"serial": Problem.TYP_SERIAL,
"reseni": Problem.TYP_ULOHA,
}
problem_typ = typy[meta["typ"]]
# Pokud už problém existuje, vytáhneme jej z db a upravíme
# Pokud ročník/číslo ještě neexistuje, vyhodí to výjimku ->
# číslo/ročník se musí založit ručně v adminu
rocnik = Rocnik.objects.get(rocnik=meta["rocnik"])
cislo = Cislo.objects.get(rocnik=rocnik, cislo=meta["cislo"])
existujici = Problem.objects.filter(
typ=problem_typ,
stav=Problem.STAV_ZADANY,
cislo_zadani=cislo,
kod=meta["kod"]
)
problem = None
if existujici:
problem = existujici[0]
# Jinak vytvoříme nový
else:
problem = Problem(
typ=problem_typ,
stav=Problem.STAV_ZADANY,
kod=meta["kod"],
cislo_zadani=cislo
)
if meta["typ"] == "reseni":
problem.text_reseni = html
#při nahrávání řešení už původní zadání atd. neměníme
else:
problem.text_zadani = html
problem.nazev = meta["nazev"]
problem.body = meta["body"]
problem.save()
# Vrátíme id dané úlohy, aby se k ní dala případně připojit pohádka
return JsonResponse({"db_id": problem.id})
elif meta["typ"] == "pohadka":
uloha = Problem.objects.get(typ=Problem.TYP_ULOHA, pk=meta["uloha"])
# Pokud už příslušná pohádka existuje, jen ji upravíme
existujici = Pohadka.objects.filter(uloha=uloha, pred=meta["pred"])
pohadka = None
if existujici:
pohadka = existujici[0]
else:
pohadka = Pohadka(uloha=uloha, pred=meta["pred"])
pohadka.text = q["html"]
pohadka.save()
return JsonResponse({"db_id": pohadka.id})
except Exception, e:
# Pošleme zpátky traceback, ať uživatel ví, v čem je problém
tb = "".join(traceback.format_exception(type(e), e, sys.exc_info()[2]))
return JsonResponse({"error": tb})
def texDownloadView(request, rocnik, cislo):
"""View posílající JSON se zadanými a řešenými problémy pro založení čísla
"""
cislo = Cislo.objects.get(rocnik__rocnik=rocnik, cislo=cislo)
zadane = Problem.objects.filter(
cislo_zadani=cislo,
stav=Problem.STAV_ZADANY
)
resene = Problem.objects.filter(
cislo_reseni=cislo,
stav=Problem.STAV_ZADANY,
typ=Problem.TYP_ULOHA
)
pred_pohadky = Pohadka.objects.filter(uloha__cislo_zadani=cislo, pred=True)
po_pohadky = Pohadka.objects.filter(uloha__cislo_zadani=cislo, pred=False)
response = {
"zadane": [
{
"nazev": p.nazev,
"typ": p.typ,
"kod": p.kod,
"body": p.body,
"zadani": p.text_zadani,
"pred_pohadky": [x.text for x in pred_pohadky.filter(uloha=p)],
"po_pohadky": [x.text for x in po_pohadky.filter(uloha=p)],
} for p in zadane
],
"resene": [
{
"nazev": p.nazev,
"typ": p.typ,
"kod": p.kod,
"body": p.body,
"zadani": p.text_zadani,
"reseni": p.text_reseni,
"cislo_zadani": p.cislo_zadani.cislo,
} for p in resene
],
}
return JsonResponse(response)

Loading…
Cancel
Save