Merge branch 'master' of atrey.karlin.mff.cuni.cz:/akce/MaM/MaMweb/mamweb
This commit is contained in:
commit
78f97835d1
25 changed files with 702 additions and 127 deletions
2
Makefile
2
Makefile
|
@ -86,7 +86,7 @@ push_test:
|
||||||
(chown -Rf :mam . || true ) && \
|
(chown -Rf :mam . || true ) && \
|
||||||
(chmod -Rf g+w . || true ) && \
|
(chmod -Rf g+w . || true ) && \
|
||||||
echo 'Reloading apache ... (You may have to start it manually on error!)' && \
|
echo 'Reloading apache ... (You may have to start it manually on error!)' && \
|
||||||
~/etc/apache2/apache2ctl -k reload && \
|
~/etc/apache2/apache2ctl -k restart && \
|
||||||
echo Done."
|
echo Done."
|
||||||
@echo "Test pushed to ${TEST_SERVER}:${TEST_DIR} successfully."
|
@echo "Test pushed to ${TEST_SERVER}:${TEST_DIR} successfully."
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -25,7 +25,7 @@ APPEND_SLASH = False
|
||||||
|
|
||||||
LANGUAGE_CODE = 'cs'
|
LANGUAGE_CODE = 'cs'
|
||||||
TIME_ZONE = 'Europe/Prague'
|
TIME_ZONE = 'Europe/Prague'
|
||||||
USE_I18N = False
|
USE_I18N = True
|
||||||
USE_L10N = True
|
USE_L10N = True
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/co-je-MaM/uvod/">Co je M&M</a>
|
<li><a href="/co-je-MaM/uvod/">Co je M&M</a>
|
||||||
<li><a href="/soustredeni/uvod/">Soustředění</a>
|
<li><a href="{% url 'seminar_seznam_soustredeni' %}">Soustředění</a>
|
||||||
<li><a href="/zadani/aktualni/">Zadání</a>
|
<li><a href="/zadani/aktualni/">Zadání</a>
|
||||||
<li><a href="/clanky/uvod/">Články</a>
|
<li><a href="/clanky/uvod/">Články</a>
|
||||||
<li><a href="/archiv/cisla/">Archiv</a>
|
<li><a href="/archiv/cisla/">Archiv</a>
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.contrib import admin
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
|
|
||||||
urlpatterns = i18n_patterns('',
|
urlpatterns = patterns('',
|
||||||
|
|
||||||
# Admin a nastroje
|
# Admin a nastroje
|
||||||
url(r'^admin/', include(admin.site.urls)), # NOQA
|
url(r'^admin/', include(admin.site.urls)), # NOQA
|
||||||
|
|
|
@ -8,7 +8,7 @@ from ckeditor.widgets import CKEditorWidget
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici
|
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Novinky, Organizator
|
||||||
import autocomplete_light
|
import autocomplete_light
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,10 +177,11 @@ admin.site.register(Skola, SkolaAdmin)
|
||||||
|
|
||||||
class CisloAdmin(reversion.VersionAdmin):
|
class CisloAdmin(reversion.VersionAdmin):
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(None, {'fields': ['cislo', 'rocnik', 'verejne_db', 'poznamka']}),
|
(None, {'fields': ['cislo', 'rocnik', 'verejne_db', 'verejna_vysledkovka', 'poznamka']}),
|
||||||
(u'Data', {'fields': ['datum_vydani', 'datum_deadline']}),
|
(u'Data', {'fields': ['datum_vydani', 'datum_deadline']}),
|
||||||
]
|
]
|
||||||
list_display = ['kod', 'rocnik', 'cislo', 'datum_vydani', 'datum_deadline', 'verejne']
|
list_display = ['kod', 'rocnik', 'cislo', 'datum_vydani', 'datum_deadline', 'verejne']
|
||||||
|
list_display = ['kod', 'rocnik', 'cislo', 'datum_vydani', 'datum_deadline', 'verejna_vysledkovka']
|
||||||
list_filter = ['rocnik']
|
list_filter = ['rocnik']
|
||||||
view_on_site = Cislo.verejne_url
|
view_on_site = Cislo.verejne_url
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
|
@ -284,7 +285,7 @@ create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name=u'Pro
|
||||||
|
|
||||||
class ProblemZadanyAdmin(ProblemAdmin):
|
class ProblemZadanyAdmin(ProblemAdmin):
|
||||||
list_display = ['nazev', 'typ', 'autor', 'opravovatel', 'kod', 'cislo_zadani', 'pocet_reseni', 'verejne']
|
list_display = ['nazev', 'typ', 'autor', 'opravovatel', 'kod', 'cislo_zadani', 'pocet_reseni', 'verejne']
|
||||||
list_filter = ['typ', 'cislo_zadani__rocnik']
|
list_filter = ['typ', 'cislo_zadani__cislo', 'cislo_zadani__rocnik']
|
||||||
inlines = [ReseniKProblemuInline]
|
inlines = [ReseniKProblemuInline]
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
|
@ -297,6 +298,18 @@ create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'P
|
||||||
|
|
||||||
### Soustredeni
|
### Soustredeni
|
||||||
|
|
||||||
|
def zverejnit_soustredeni(modeladmin, request, queryset):
|
||||||
|
for soustredeni in queryset:
|
||||||
|
soustredeni.verejne_db = True
|
||||||
|
soustredeni.save()
|
||||||
|
zverejnit_soustredeni.short_description = 'Zveřejnit soustředění'
|
||||||
|
|
||||||
|
def skryt_soustredeni(modeladmin, request, queryset):
|
||||||
|
for soustredeni in queryset:
|
||||||
|
soustredeni.verejne_db = False
|
||||||
|
soustredeni.save()
|
||||||
|
skryt_soustredeni.short_description = 'Skrýt soustředění (Zneveřjnit)'
|
||||||
|
|
||||||
class SoustredeniAdminForm(forms.ModelForm):
|
class SoustredeniAdminForm(forms.ModelForm):
|
||||||
text = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Soustredeni, 'text'))
|
text = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Soustredeni, 'text'))
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -313,6 +326,61 @@ class SoustredeniAdmin(reversion.VersionAdmin):
|
||||||
inlines = [Soustredeni_UcastniciInline]
|
inlines = [Soustredeni_UcastniciInline]
|
||||||
list_filter = ['rocnik']
|
list_filter = ['rocnik']
|
||||||
view_on_site = Soustredeni.verejne_url
|
view_on_site = Soustredeni.verejne_url
|
||||||
|
actions = [zverejnit_soustredeni, skryt_soustredeni, ]
|
||||||
|
|
||||||
admin.site.register(Soustredeni, SoustredeniAdmin)
|
admin.site.register(Soustredeni, SoustredeniAdmin)
|
||||||
|
|
||||||
|
### Novinky
|
||||||
|
|
||||||
|
class NovinkyAdminForm(forms.ModelForm):
|
||||||
|
text = forms.CharField(widget=CKEditorWidget(), required=False,
|
||||||
|
**field_labels(Novinky, 'text'))
|
||||||
|
class Meta:
|
||||||
|
model = Novinky
|
||||||
|
exclude = []
|
||||||
|
|
||||||
|
class NovinkyAdmin(admin.ModelAdmin):
|
||||||
|
form = NovinkyAdminForm
|
||||||
|
|
||||||
|
admin.site.register(Novinky, NovinkyAdmin)
|
||||||
|
|
||||||
|
### Organizator
|
||||||
|
|
||||||
|
def jmeno_organizatora(obj):
|
||||||
|
''' vraci jmeno organizatora '''
|
||||||
|
jmeno = obj.user.first_name
|
||||||
|
if obj.prezdivka:
|
||||||
|
jmeno = jmeno + ' "' + obj.prezdivka + '"'
|
||||||
|
jmeno = jmeno + ' ' + obj.user.last_name
|
||||||
|
if jmeno == ' ': # zobrazeni bezejmennych orgu
|
||||||
|
return 'org'
|
||||||
|
return jmeno
|
||||||
|
jmeno_organizatora.short_description = 'Jméno organizátora'
|
||||||
|
|
||||||
|
def je_organizator_aktivni(obj):
|
||||||
|
''' zjisti, zda-li je organizator aktivni '''
|
||||||
|
return obj.user.is_active
|
||||||
|
je_organizator_aktivni.short_description = 'Aktivní'
|
||||||
|
je_organizator_aktivni.boolean = True
|
||||||
|
|
||||||
|
def zaktivovat_organizatory(modeladmin, request, queryset):
|
||||||
|
''' vybrane organizatory oznaci jako aktivni '''
|
||||||
|
for org in queryset:
|
||||||
|
org.user.is_active = True
|
||||||
|
org.user.save()
|
||||||
|
zaktivovat_organizatory.short_description = 'Zaktivovat organizátory'
|
||||||
|
|
||||||
|
def deaktivovat_organizatory(modeladmin, request, queryset):
|
||||||
|
''' deaktivuje vybrane organizatory '''
|
||||||
|
for org in queryset:
|
||||||
|
org.user.is_active = False
|
||||||
|
org.user.save()
|
||||||
|
deaktivovat_organizatory.short_description = 'Deaktivovat organizátory'
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Organizator)
|
||||||
|
class OrganizatorAdmin(admin.ModelAdmin):
|
||||||
|
list_filter = ['organizuje_do_roku']
|
||||||
|
list_display = [jmeno_organizatora, je_organizator_aktivni,]
|
||||||
|
actions = [zaktivovat_organizatory, deaktivovat_organizatory,]
|
||||||
|
|
||||||
|
|
|
@ -1,80 +1,92 @@
|
||||||
import datetime
|
import datetime, django
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponse
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
class ExportIndexView(generic.base.TemplateView):
|
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik, Soustredeni
|
||||||
template_name = 'seminar/export_index.csv'
|
from .ovvpfile import OvvpFile
|
||||||
content_type = 'text/plain; charset=utf-8'
|
|
||||||
def get_context_data(self, **kwargs):
|
class ExportIndexView(generic.View):
|
||||||
context = super(ExportIndexView, self).get_context_data(**kwargs)
|
def get(self, request):
|
||||||
context['exports'] = []
|
|
||||||
|
ls = []
|
||||||
for r in Rocnik.objects.all():
|
for r in Rocnik.objects.all():
|
||||||
if r.verejna_cisla():
|
if r.verejna_cisla():
|
||||||
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
||||||
context['exports'].append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
return context
|
for s in Soustredeni.objects.all():
|
||||||
|
if s.ucastnici.count() >= 1 and s.verejne:
|
||||||
|
url = reverse('seminar_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
||||||
|
ls.append(url.split('/')[-1])
|
||||||
|
|
||||||
|
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
||||||
|
|
||||||
|
|
||||||
class ExportRocnikView(generic.DetailView):
|
def default_ovvpfile(event, rocnik):
|
||||||
slug_field = 'prvni_rok'
|
of = OvvpFile()
|
||||||
slug_url_kwarg = 'prvni_rok'
|
of.headers['version'] = '1'
|
||||||
model = Rocnik
|
of.headers['event'] = event
|
||||||
template_name = 'seminar/export_rocnik.csv'
|
of.headers['year'] = force_text(rocnik.prvni_rok)
|
||||||
content_type = 'text/plain; charset=utf-8'
|
of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
def get_context_data(self, **kwargs):
|
of.headers['id-scope'] = 'mam'
|
||||||
context = super(ExportRocnikView, self).get_context_data(**kwargs)
|
of.headers['id-generation'] = '1'
|
||||||
|
return of
|
||||||
|
|
||||||
rocnik = context['rocnik']
|
|
||||||
|
class ExportSousView(generic.View):
|
||||||
|
|
||||||
|
def get(self, request, datum_zacatku=None):
|
||||||
|
try:
|
||||||
|
dz = django.utils.dateparse.parse_date(datum_zacatku)
|
||||||
|
except:
|
||||||
|
dz = None
|
||||||
|
if dz is None:
|
||||||
|
raise django.http.Http404()
|
||||||
|
|
||||||
|
s = get_object_or_404(Soustredeni, datum_zacatku=dz)
|
||||||
|
|
||||||
|
of = default_ovvpfile('MaM.sous', s.rocnik)
|
||||||
|
of.headers['x-event-begin'] = s.datum_zacatku.isoformat()
|
||||||
|
of.headers['x-event-end'] = s.datum_konce.isoformat()
|
||||||
|
of.headers['x-event-location'] = s.misto
|
||||||
|
of.headers['comment'] = u'MaM-Web export ucastniku soustredeni v {x-event-location} od {x-event-begin} do {x-event-end}'.format(**of.headers)
|
||||||
|
of.columns = ['id', 'name', 'surname', 'gender', 'email', 'end-year', 'school', 'school-name']
|
||||||
|
|
||||||
|
for u in s.ucastnici.all():
|
||||||
|
of.rows.append(u.export_row())
|
||||||
|
|
||||||
|
return of.to_HttpResponse()
|
||||||
|
|
||||||
|
|
||||||
|
class ExportRocnikView(generic.View):
|
||||||
|
|
||||||
|
def get(self, request, prvni_rok=None):
|
||||||
|
try:
|
||||||
|
pr = int(prvni_rok)
|
||||||
|
except:
|
||||||
|
pr = None
|
||||||
|
if pr is None:
|
||||||
|
raise django.http.Http404()
|
||||||
|
|
||||||
|
rocnik = get_object_or_404(Rocnik, prvni_rok=pr)
|
||||||
cislo = rocnik.posledni_verejne_cislo()
|
cislo = rocnik.posledni_verejne_cislo()
|
||||||
sloupce = ['id', 'name', 'surname',
|
|
||||||
'gender', 'born', 'email', 'end-year',
|
|
||||||
'street', 'town', 'postcode', 'country',
|
|
||||||
'spam-flag', 'spam-date', 'school', 'school-name',
|
|
||||||
'points', 'rank',]
|
|
||||||
radky = []
|
|
||||||
|
|
||||||
vysledky = VysledkyKCislu.objects.filter(cislo = cislo).select_related("resitel").order_by('-body_celkem').all()
|
vysledky = VysledkyKCislu.objects.filter(cislo = cislo).select_related("resitel").order_by('-body_celkem').all()
|
||||||
|
|
||||||
|
of = default_ovvpfile('MaM.rocnik', rocnik)
|
||||||
|
of.headers['comment'] = u'MaM-Web export aktivnich resitelu rocniku {rocnik} do cisla {cislo}'.format(
|
||||||
|
rocnik=rocnik, cislo=cislo)
|
||||||
|
of.columns = ['id', 'name', 'surname', 'gender', 'born', 'email', 'end-year',
|
||||||
|
'street', 'town', 'postcode', 'country', 'spam-flag', 'spam-date',
|
||||||
|
'school', 'school-name', 'points', 'rank',]
|
||||||
|
|
||||||
posledni_body = 100000
|
posledni_body = 100000
|
||||||
posledni_poradi = 0
|
posledni_poradi = 0
|
||||||
for vi in range(len(vysledky)):
|
for vi in range(len(vysledky)):
|
||||||
|
|
||||||
v = vysledky[vi]
|
v = vysledky[vi]
|
||||||
rd = {}
|
rd = v.resitel.export_row()
|
||||||
|
|
||||||
rd['name'] = v.resitel.jmeno
|
|
||||||
rd['surname'] = v.resitel.prijmeni
|
|
||||||
rd['id'] = v.resitel.id
|
|
||||||
|
|
||||||
rd['gender'] = 'M' if v.resitel.pohlavi_muz else 'F'
|
|
||||||
if v.resitel.datum_narozeni:
|
|
||||||
rd['born'] = v.resitel.datum_narozeni.strftime("%Y-%m-%d")
|
|
||||||
else:
|
|
||||||
rd['born'] = ''
|
|
||||||
rd['email'] = v.resitel.email
|
|
||||||
rd['end-year'] = v.resitel.rok_maturity
|
|
||||||
|
|
||||||
# TODO(gavento): Adresa skoly, kdyz preferuje zasilani tam?
|
|
||||||
rd['street'] = v.resitel.ulice
|
|
||||||
rd['town'] = v.resitel.mesto
|
|
||||||
rd['postcode'] = v.resitel.psc
|
|
||||||
rd['country'] = v.resitel.stat
|
|
||||||
|
|
||||||
if v.resitel.datum_souhlasu_zasilani:
|
|
||||||
rd['spam-flag'] = 'Y'
|
|
||||||
rd['spam-date'] = v.resitel.datum_souhlasu_zasilani.strftime("%Y-%m-%d")
|
|
||||||
else:
|
|
||||||
rd['spam-flag'] = ''
|
|
||||||
rd['spam-date'] = ''
|
|
||||||
|
|
||||||
if v.resitel.skola:
|
|
||||||
rd['school'] = v.resitel.skola.aesop_id
|
|
||||||
rd['school-name'] = str(v.resitel.skola)
|
|
||||||
else:
|
|
||||||
rd['school'] = ''
|
|
||||||
rd['school-name'] = 'Skola neni znama'
|
|
||||||
|
|
||||||
if posledni_body > v.body_celkem:
|
if posledni_body > v.body_celkem:
|
||||||
posledni_body = v.body_celkem
|
posledni_body = v.body_celkem
|
||||||
|
@ -82,16 +94,8 @@ class ExportRocnikView(generic.DetailView):
|
||||||
rd['rank'] = posledni_poradi
|
rd['rank'] = posledni_poradi
|
||||||
rd['points'] = v.body_celkem
|
rd['points'] = v.body_celkem
|
||||||
|
|
||||||
r = []
|
of.rows.append(rd)
|
||||||
for c in sloupce:
|
|
||||||
r.append(rd.pop(c))
|
return of.to_HttpResponse()
|
||||||
assert len(rd) == 0
|
|
||||||
radky.append(r)
|
|
||||||
|
|
||||||
context['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
context['cislo'] = cislo
|
|
||||||
context['sloupce'] = sloupce
|
|
||||||
context['radky'] = radky
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
|
|
32
seminar/migrations/0019_rocnik_ciselne.py
Normal file
32
seminar/migrations/0019_rocnik_ciselne.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('seminar', '0018_problemnavrh_problemzadany'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rocnik',
|
||||||
|
name='rocnik_n',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='\u010d\xedslo ro\u010dn\xedku'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.RunSQL(
|
||||||
|
sql="update seminar_rocniky set rocnik_n = cast (rocnik as integer)"
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='rocnik',
|
||||||
|
name='rocnik',
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='rocnik',
|
||||||
|
old_name='rocnik_n',
|
||||||
|
new_name='rocnik',
|
||||||
|
),
|
||||||
|
]
|
44
seminar/migrations/0020_indexy_a_razeni.py
Normal file
44
seminar/migrations/0020_indexy_a_razeni.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('seminar', '0019_rocnik_ciselne'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='cislo',
|
||||||
|
options={'ordering': ['-rocnik__rocnik', '-cislo'], 'verbose_name': '\u010c\xedslo', 'verbose_name_plural': '\u010c\xedsla'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='reseni',
|
||||||
|
options={'ordering': ['problem_id', 'resitel__prijmeni', 'resitel__jmeno'], 'verbose_name': '\u0158e\u0161en\xed', 'verbose_name_plural': '\u0158e\u0161en\xed'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='rocnik',
|
||||||
|
options={'ordering': ['-rocnik'], 'verbose_name': 'Ro\u010dn\xedk', 'verbose_name_plural': 'Ro\u010dn\xedky'},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='cislo',
|
||||||
|
name='cislo',
|
||||||
|
field=models.CharField(help_text='V\u011bt\u0161inou jen "1", vyj\xedme\u010dn\u011b "7-8", lexikograficky ur\u010dije po\u0159ad\xed v ro\u010dn\xedku!', max_length=32, verbose_name='n\xe1zev \u010d\xedsla', db_index=True),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='rocnik',
|
||||||
|
name='prvni_rok',
|
||||||
|
field=models.IntegerField(unique=True, verbose_name='prvn\xed rok', db_index=True),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='rocnik',
|
||||||
|
name='rocnik',
|
||||||
|
field=models.IntegerField(unique=True, verbose_name='\u010d\xedslo ro\u010dn\xedku', db_index=True),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
]
|
20
seminar/migrations/0021_cislo_verejna_vysledkovka.py
Normal file
20
seminar/migrations/0021_cislo_verejna_vysledkovka.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('seminar', '0020_indexy_a_razeni'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='cislo',
|
||||||
|
name='verejna_vysledkovka',
|
||||||
|
field=models.BooleanField(default=False, help_text='Je-li false u ve\u0159ejn\xe9ho \u010d\xedsla, nen\xed v\xfdsledkovka zat\xedm ve\u0159ejn\xe1.', verbose_name='zve\u0159ejn\u011bna v\xfdsledkovka'),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
]
|
30
seminar/migrations/0022_decimal_body.py
Normal file
30
seminar/migrations/0022_decimal_body.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
migration_0022 = importlib.import_module('seminar.migrations.0002_add_body_views')
|
||||||
|
print dir(migration_0022)
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('seminar', '0021_cislo_verejna_vysledkovka'),
|
||||||
|
]
|
||||||
|
operations = [
|
||||||
|
migrations.RunSQL(migration_0022.DROP_VIEWS),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='problem',
|
||||||
|
name='body',
|
||||||
|
field=models.DecimalField(null=True, verbose_name='maximum bod\u016f', max_digits=8, decimal_places=1, blank=True),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='reseni',
|
||||||
|
name='body',
|
||||||
|
field=models.DecimalField(null=True, verbose_name='body', max_digits=8, decimal_places=1, blank=True),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
migrations.RunSQL(migration_0022.CREATE_VIEWS),
|
||||||
|
]
|
32
seminar/migrations/0023_add_novinky.py
Normal file
32
seminar/migrations/0023_add_novinky.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('seminar', '0022_decimal_body'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Novinky',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('datum', models.DateField(auto_now_add=True)),
|
||||||
|
('text', models.TextField(null=True, verbose_name=b'Text novinky', blank=True)),
|
||||||
|
('obrazek', models.ImageField(upload_to=b'image_novinky/%Y/%m/%d/', null=True, verbose_name=b'Obr\xc3\xa1zek', blank=True)),
|
||||||
|
('zverejneno', models.BooleanField(default=b'False', verbose_name=b'Zve\xc5\x99ejn\xc4\x9bno')),
|
||||||
|
('autor', models.ForeignKey(verbose_name=b'Autor novinky', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Novinka',
|
||||||
|
'verbose_name_plural': 'Novinky',
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
]
|
35
seminar/migrations/0024_add_organizator.py
Normal file
35
seminar/migrations/0024_add_organizator.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('seminar', '0023_add_novinky'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Organizator',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('prezdivka', models.CharField(max_length=32, null=True, verbose_name=b'P\xc5\x99ezd\xc3\xadvka', blank=True)),
|
||||||
|
('organizuje_od_roku', models.IntegerField(null=True, verbose_name=b'Organizuje od roku', blank=True)),
|
||||||
|
('organizuje_do_roku', models.IntegerField(null=True, verbose_name=b'Organizuje do roku', blank=True)),
|
||||||
|
('studuje', models.CharField(max_length=256, null=True, verbose_name=b'Studuje', blank=True)),
|
||||||
|
('strucny_popis_organizatora', models.TextField(null=True, verbose_name=b'Stru\xc4\x8dn\xc3\xbd popis organiz\xc3\xa1tora', blank=True)),
|
||||||
|
('foto', models.ImageField(help_text=b'Vlo\xc5\xbe fotografii organiz\xc3\xa1tora o libovon\xc3\xa9 velikosti', upload_to=b'image_organizatori/%Y/', null=True, verbose_name=b'Fotografie organiz\xc3\xa1tora', blank=True)),
|
||||||
|
('foto_male', models.ImageField(upload_to=b'image_organizatori/male/%Y/', null=True, editable=False, blank=True)),
|
||||||
|
('user', models.OneToOneField(verbose_name=b'Osoba', to=settings.AUTH_USER_MODEL, help_text=b'Vyber \xc3\xba\xc4\x8det sp\xc5\x99a\xc5\xbeen\xc3\xbd s organiz\xc3\xa1torem.')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Organiz\xe1tor',
|
||||||
|
'verbose_name_plural': 'Organiz\xe1to\u0159i',
|
||||||
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
|
),
|
||||||
|
]
|
20
seminar/migrations/0025_zmena_cesty_nahravani_obrazku.py
Normal file
20
seminar/migrations/0025_zmena_cesty_nahravani_obrazku.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('seminar', '0024_add_organizator'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='organizator',
|
||||||
|
name='foto',
|
||||||
|
field=models.ImageField(help_text=b'Vlo\xc5\xbe fotografii organiz\xc3\xa1tora o libovon\xc3\xa9 velikosti', upload_to=b'image_organizatori/velke/%Y/', null=True, verbose_name=b'Fotografie organiz\xc3\xa1tora', blank=True),
|
||||||
|
preserve_default=True,
|
||||||
|
),
|
||||||
|
]
|
|
@ -12,6 +12,10 @@ from django.utils.text import slugify
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
import os
|
||||||
|
from cStringIO import StringIO
|
||||||
|
from django.core.files.base import ContentFile
|
||||||
|
|
||||||
from django_countries.fields import CountryField
|
from django_countries.fields import CountryField
|
||||||
from solo.models import SingletonModel
|
from solo.models import SingletonModel
|
||||||
|
@ -29,12 +33,6 @@ class SeminarModelBase(models.Model):
|
||||||
def verejne(self):
|
def verejne(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# def public_url(self):
|
|
||||||
# if self.Meta.url_name:
|
|
||||||
# return reverse(self.Meta.url_name,
|
|
||||||
# kwargs={'id': self.id, 'pk': self.id})
|
|
||||||
# return None
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return self.verejne_url() # TODO "absolute"
|
return self.verejne_url() # TODO "absolute"
|
||||||
|
|
||||||
|
@ -188,6 +186,30 @@ class Resitel(SeminarModelBase):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return force_unicode(self.plne_jmeno())
|
return force_unicode(self.plne_jmeno())
|
||||||
|
|
||||||
|
def export_row(self):
|
||||||
|
"Slovnik pro pouziti v OVVP exportu"
|
||||||
|
return {
|
||||||
|
'id': self.id,
|
||||||
|
'name': self.jmeno,
|
||||||
|
'surname': self.prijmeni,
|
||||||
|
'gender': 'M' if self.pohlavi_muz else 'F',
|
||||||
|
'born': self.datum_narozeni.isoformat() if self.datum_narozeni else '',
|
||||||
|
'email': self.email,
|
||||||
|
'end-year': self.rok_maturity,
|
||||||
|
|
||||||
|
# TODO(gavento): Adresa skoly, kdyz preferuje zasilani tam?
|
||||||
|
'street': self.ulice,
|
||||||
|
'town': self.mesto,
|
||||||
|
'postcode': self.psc,
|
||||||
|
'country': self.stat,
|
||||||
|
|
||||||
|
'spam-flag': 'Y' if self.datum_souhlasu_zasilani else '',
|
||||||
|
'spam-date': self.datum_souhlasu_zasilani.isoformat() if self.datum_souhlasu_zasilani else '',
|
||||||
|
|
||||||
|
'school': self.skola.aesop_id if self.skola else '',
|
||||||
|
'school-name': str(self.skola) if self.skola else 'Skola neni znama',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@reversion.register(ignore_duplicate_revisions=True)
|
@reversion.register(ignore_duplicate_revisions=True)
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
|
@ -202,18 +224,15 @@ class Rocnik(SeminarModelBase):
|
||||||
# Interní ID
|
# Interní ID
|
||||||
id = models.AutoField(primary_key = True)
|
id = models.AutoField(primary_key = True)
|
||||||
|
|
||||||
prvni_rok = models.IntegerField(u'první rok')
|
prvni_rok = models.IntegerField(u'první rok', db_index=True, unique=True)
|
||||||
|
|
||||||
rocnik = models.CharField(u'číslo ročníku', max_length=16)
|
rocnik = models.IntegerField(u'číslo ročníku', db_index=True, unique=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return force_unicode(u'%s (%d/%d)' % (self.rocnik, self.prvni_rok, self.prvni_rok+1))
|
return force_unicode(u'%s (%d/%d)' % (self.rocnik, self.prvni_rok, self.prvni_rok+1))
|
||||||
|
|
||||||
def roman(self):
|
def roman(self):
|
||||||
if self.rocnik.isdigit():
|
return force_unicode(roman(int(self.rocnik)))
|
||||||
return force_unicode(roman(int(self.rocnik)))
|
|
||||||
else:
|
|
||||||
return force_unicode(self.rocnik)
|
|
||||||
|
|
||||||
def verejne(self):
|
def verejne(self):
|
||||||
return len(self.verejna_cisla()) > 0
|
return len(self.verejna_cisla()) > 0
|
||||||
|
@ -232,7 +251,7 @@ class Rocnik(SeminarModelBase):
|
||||||
return self.prvni_rok + 1
|
return self.prvni_rok + 1
|
||||||
|
|
||||||
def verejne_url(self):
|
def verejne_url(self):
|
||||||
return reverse('seminar_rocnik', kwargs={'pk': self.id})
|
return reverse('seminar_rocnik', kwargs={'rocnik': self.rocnik})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cached_rocnik(cls, r_id):
|
def cached_rocnik(cls, r_id):
|
||||||
|
@ -258,9 +277,9 @@ class Cislo(SeminarModelBase):
|
||||||
# Interní ID
|
# Interní ID
|
||||||
id = models.AutoField(primary_key = True)
|
id = models.AutoField(primary_key = True)
|
||||||
|
|
||||||
rocnik = models.ForeignKey(Rocnik, verbose_name=u'ročník', related_name='cisla')
|
rocnik = models.ForeignKey(Rocnik, verbose_name=u'ročník', related_name='cisla', db_index=True)
|
||||||
|
|
||||||
cislo = models.CharField(u'název čísla', max_length=32,
|
cislo = models.CharField(u'název čísla', max_length=32, db_index=True,
|
||||||
help_text=u'Většinou jen "1", vyjímečně "7-8", lexikograficky určije pořadí v ročníku!')
|
help_text=u'Většinou jen "1", vyjímečně "7-8", lexikograficky určije pořadí v ročníku!')
|
||||||
|
|
||||||
datum_vydani = models.DateField(u'datum vydání', blank=True, null=True,
|
datum_vydani = models.DateField(u'datum vydání', blank=True, null=True,
|
||||||
|
@ -271,6 +290,9 @@ class Cislo(SeminarModelBase):
|
||||||
|
|
||||||
verejne_db = models.BooleanField(u'číslo zveřejněno', db_column='verejne', default=False)
|
verejne_db = models.BooleanField(u'číslo zveřejněno', db_column='verejne', default=False)
|
||||||
|
|
||||||
|
verejna_vysledkovka = models.BooleanField(u'zveřejněna výsledkovka', default=False,
|
||||||
|
help_text=u'Je-li false u veřejného čísla, není výsledkovka zatím veřejná.')
|
||||||
|
|
||||||
poznamka = models.TextField(u'neveřejná poznámka', blank=True,
|
poznamka = models.TextField(u'neveřejná poznámka', blank=True,
|
||||||
help_text=u'Neveřejná poznámka k číslu (plain text)')
|
help_text=u'Neveřejná poznámka k číslu (plain text)')
|
||||||
|
|
||||||
|
@ -288,7 +310,7 @@ class Cislo(SeminarModelBase):
|
||||||
verejne.boolean = True
|
verejne.boolean = True
|
||||||
|
|
||||||
def verejne_url(self):
|
def verejne_url(self):
|
||||||
return reverse('seminar_cislo', kwargs={'pk': self.id})
|
return reverse('seminar_cislo', kwargs={'rocnik': self.rocnik.rocnik, 'cislo': self.cislo})
|
||||||
|
|
||||||
def nasledujici(self):
|
def nasledujici(self):
|
||||||
u"Vrací None, pokud je toto poslední"
|
u"Vrací None, pokud je toto poslední"
|
||||||
|
@ -370,7 +392,7 @@ class Problem(SeminarModelBase):
|
||||||
cislo_reseni = models.ForeignKey(Cislo, verbose_name=u'číslo řešení', blank=True, null=True, related_name=u'resene_problemy',
|
cislo_reseni = models.ForeignKey(Cislo, verbose_name=u'číslo řešení', blank=True, null=True, related_name=u'resene_problemy',
|
||||||
help_text=u'Číslo s řešením úlohy, jen pro úlohy')
|
help_text=u'Číslo s řešením úlohy, jen pro úlohy')
|
||||||
|
|
||||||
body = models.IntegerField(u'maximum bodů', blank=True, null=True)
|
body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name=u'maximum bodů', blank=True, null=True)
|
||||||
|
|
||||||
timestamp = models.DateTimeField(u'vytvořeno', default=timezone.now, blank=True, editable=False)
|
timestamp = models.DateTimeField(u'vytvořeno', default=timezone.now, blank=True, editable=False)
|
||||||
|
|
||||||
|
@ -411,7 +433,7 @@ class Reseni(SeminarModelBase):
|
||||||
db_table = 'seminar_reseni'
|
db_table = 'seminar_reseni'
|
||||||
verbose_name = u'Řešení'
|
verbose_name = u'Řešení'
|
||||||
verbose_name_plural = u'Řešení'
|
verbose_name_plural = u'Řešení'
|
||||||
ordering = ['problem_id', 'resitel_id']
|
ordering = ['problem_id', 'resitel__prijmeni', 'resitel__jmeno',]
|
||||||
|
|
||||||
# Interní ID
|
# Interní ID
|
||||||
id = models.AutoField(primary_key = True)
|
id = models.AutoField(primary_key = True)
|
||||||
|
@ -420,7 +442,7 @@ class Reseni(SeminarModelBase):
|
||||||
|
|
||||||
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', related_name='reseni')
|
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', related_name='reseni')
|
||||||
|
|
||||||
body = models.IntegerField(u'body', blank=True, null=True)
|
body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name=u'body', blank=True, null=True)
|
||||||
|
|
||||||
cislo_body = models.ForeignKey(Cislo, verbose_name=u'číslo pro body', related_name='bodovana_reseni', blank=True, null=True)
|
cislo_body = models.ForeignKey(Cislo, verbose_name=u'číslo pro body', related_name='bodovana_reseni', blank=True, null=True)
|
||||||
|
|
||||||
|
@ -443,6 +465,12 @@ class Reseni(SeminarModelBase):
|
||||||
return force_unicode(u"%s: %s (%sb)" % (self.resitel.plne_jmeno(), self.problem.nazev, self.body))
|
return force_unicode(u"%s: %s (%sb)" % (self.resitel.plne_jmeno(), self.problem.nazev, self.body))
|
||||||
# NOTE: Potenciální DB HOG (bez select_related)
|
# NOTE: Potenciální DB HOG (bez select_related)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if ((self.cislo_body is None) and (self.problem.cislo_reseni) and
|
||||||
|
(self.problem.typ == Problem.TYP_ULOHA)):
|
||||||
|
self.cislo_body = self.problem.cislo_reseni
|
||||||
|
super(Reseni, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
# PrilohaReseni method
|
# PrilohaReseni method
|
||||||
def generate_filename(self, filename):
|
def generate_filename(self, filename):
|
||||||
|
@ -562,7 +590,8 @@ class VysledkyBase(SeminarModelBase):
|
||||||
|
|
||||||
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', db_column='resitel_id', on_delete=models.DO_NOTHING)
|
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel', db_column='resitel_id', on_delete=models.DO_NOTHING)
|
||||||
|
|
||||||
body = models.IntegerField(u'body za číslo', db_column='body')
|
body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body',
|
||||||
|
verbose_name=u'body za číslo')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return force_unicode(u"%s: %sb (%s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo)))
|
return force_unicode(u"%s: %sb (%s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo)))
|
||||||
|
@ -589,7 +618,8 @@ class VysledkyKCislu(VysledkyBase):
|
||||||
abstract = False
|
abstract = False
|
||||||
managed = False
|
managed = False
|
||||||
|
|
||||||
body_celkem = models.IntegerField(u'body celkem do čísla', db_column='body_celkem')
|
body_celkem = models.DecimalField(max_digits=8, decimal_places=1, db_column='body_celkem',
|
||||||
|
verbose_name=u'body celkem do čísla')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# NOTE: DB HOG (ale nepouzivany)
|
# NOTE: DB HOG (ale nepouzivany)
|
||||||
|
@ -616,3 +646,88 @@ class Nastaveni(SingletonModel):
|
||||||
|
|
||||||
def verejne(self):
|
def verejne(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class Novinky(models.Model):
|
||||||
|
datum = models.DateField(auto_now_add=True)
|
||||||
|
text = models.TextField('Text novinky', blank=True, null=True)
|
||||||
|
obrazek = models.ImageField('Obrázek', upload_to='image_novinky/%Y/%m/%d/',
|
||||||
|
null=True, blank=True)
|
||||||
|
autor = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='Autor novinky')
|
||||||
|
zverejneno = models.BooleanField('Zveřejněno', default="False")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '[' + str(self.datum) + '] ' + self.text[0:50]
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Novinka'
|
||||||
|
verbose_name_plural = 'Novinky'
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class Organizator(models.Model):
|
||||||
|
user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name='Osoba',
|
||||||
|
help_text = 'Vyber účet spřažený s organizátorem.')
|
||||||
|
prezdivka = models.CharField('Přezdívka', max_length = 32,
|
||||||
|
null = True, blank = True)
|
||||||
|
organizuje_od_roku = models.IntegerField('Organizuje od roku',
|
||||||
|
null = True, blank = True)
|
||||||
|
organizuje_do_roku = models.IntegerField('Organizuje do roku',
|
||||||
|
null = True, blank = True)
|
||||||
|
studuje = models.CharField('Studuje', max_length = 256,
|
||||||
|
null = True, blank = True)
|
||||||
|
strucny_popis_organizatora = models.TextField('Stručný popis organizátora',
|
||||||
|
null = True, blank = True)
|
||||||
|
foto = models.ImageField('Fotografie organizátora',
|
||||||
|
upload_to='image_organizatori/velke/%Y/', null = True, blank = True,
|
||||||
|
help_text = 'Vlož fotografii organizátora o libovoné velikosti')
|
||||||
|
foto_male = models.ImageField(upload_to='image_organizatori/male/%Y/',
|
||||||
|
null = True, blank = True, editable = False)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.user)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Organizátor'
|
||||||
|
verbose_name_plural = 'Organizátoři'
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
if self.foto:
|
||||||
|
original = Image.open(self.foto)
|
||||||
|
jmeno = os.path.basename(self.foto.file.name)
|
||||||
|
Organizator._vyrobMiniaturu(original, jmeno, 500, self.foto)
|
||||||
|
Organizator._vyrobMiniaturu(original, jmeno, 200, self.foto_male)
|
||||||
|
super(Organizator, self).save()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _vyrobMiniaturu(original, jmeno, maximum, field):
|
||||||
|
zmensenina = Organizator._zmensiObrazek(original, maximum)
|
||||||
|
f = StringIO()
|
||||||
|
try:
|
||||||
|
zmensenina.save(f, format=original.format)
|
||||||
|
data = ContentFile(f.getvalue())
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
field.save(jmeno, data, save = False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _zmensiObrazek(original, maximum):
|
||||||
|
"""Preskaluje obrazek tak, aby byl zachovan pomer stran
|
||||||
|
a zadny rozmer nepresahoval maxRozmer. Pokud zadny rozmer
|
||||||
|
nepresahuje maxRozmer, tak vrati puvodni obrazek
|
||||||
|
(tj. nedojde ke zvetseni obrazku)."""
|
||||||
|
novaVelikost = Organizator._zmensiVelikost(original.size, maximum)
|
||||||
|
return original.resize(novaVelikost, Image.ANTIALIAS)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _zmensiVelikost(velikost, maximum):
|
||||||
|
maximum = float(maximum)
|
||||||
|
w, h = velikost
|
||||||
|
soucasneMaximum = max(w, h)
|
||||||
|
if soucasneMaximum <= maximum:
|
||||||
|
return velikost
|
||||||
|
pomer = maximum/soucasneMaximum
|
||||||
|
return (int(w * pomer), int(h * pomer))
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
try:
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
except:
|
||||||
|
force_text = str
|
||||||
|
|
||||||
|
|
||||||
class OvvpFile(object):
|
class OvvpFile(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
# { header: value, ... }
|
||||||
self.headers = {}
|
self.headers = {}
|
||||||
|
# [ 'column-name', ... ]
|
||||||
self.columns = []
|
self.columns = []
|
||||||
|
# [ { column: value, ...}, ...]
|
||||||
self.rows = []
|
self.rows = []
|
||||||
|
|
||||||
def to_lines(self):
|
def to_lines(self):
|
||||||
|
@ -15,11 +25,14 @@ class OvvpFile(object):
|
||||||
yield '\t'.join([c for c in self.columns]) + '\n'
|
yield '\t'.join([c for c in self.columns]) + '\n'
|
||||||
# rows
|
# rows
|
||||||
for r in self.rows:
|
for r in self.rows:
|
||||||
yield '\t'.join([r[c] for c in self.columns]) + '\n'
|
yield '\t'.join([force_text(r[c]) for c in self.columns]) + '\n'
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
return ''.join(self.to_lines())
|
return ''.join(self.to_lines())
|
||||||
|
|
||||||
|
def to_HttpResponse(self):
|
||||||
|
return HttpResponse(self.to_string(), content_type='text/plain; charset=utf-8')
|
||||||
|
|
||||||
def parse_from(self, source, with_headers=True):
|
def parse_from(self, source, with_headers=True):
|
||||||
"Parse data from file, string or line iterator, overwriting self"
|
"Parse data from file, string or line iterator, overwriting self"
|
||||||
if isinstance(source, str) or isinstance(source, unicode):
|
if isinstance(source, str) or isinstance(source, unicode):
|
||||||
|
|
|
@ -20,7 +20,12 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{% if cislo.verejna_vysledkovka %}
|
||||||
<h3>Výsledkovka</h3>
|
<h3>Výsledkovka</h3>
|
||||||
|
{% else %}
|
||||||
|
<div class='mam-org-only'>
|
||||||
|
<h3>Výsledkovka (neveřejná)</h3>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<table class='vysledkovka'>
|
<table class='vysledkovka'>
|
||||||
<tr class='border-b'>
|
<tr class='border-b'>
|
||||||
|
@ -44,6 +49,11 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% if cislo.verejna_vysledkovka %}
|
||||||
|
{% else %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,42 @@
|
||||||
<div>
|
<div>
|
||||||
<h2>Organizátoři</h2>
|
<h2>Organizátoři</h2>
|
||||||
|
|
||||||
|
{% for org in object_list %}
|
||||||
|
{% if org.user.is_active %}
|
||||||
|
<b>Aktivní</b>
|
||||||
|
{% else %}
|
||||||
|
Není aktivní
|
||||||
|
{% endif %}
|
||||||
|
{{org.user.first_name}}
|
||||||
|
{% if org.prezdivka %}
|
||||||
|
"{{org.prezdivka}}"
|
||||||
|
{% endif %}
|
||||||
|
{{org.user.last_name}} <br>
|
||||||
|
<ul>
|
||||||
|
{% if org.organizuje_od_roku %}
|
||||||
|
<li>Organizuje od roku: {{org.organizuje_od_roku}}
|
||||||
|
{% endif %}
|
||||||
|
{% if org.organizuje_do_roku %}
|
||||||
|
<li>Organizuje do roku: {{org.organizuje_do_roku}}
|
||||||
|
{% endif %}
|
||||||
|
{% if org.studuje %}
|
||||||
|
<li>Studuje: {{org.studuje}}
|
||||||
|
{% endif %}
|
||||||
|
{% if org.user.email %}
|
||||||
|
<li>Pošta:
|
||||||
|
{# zobrazeni e-mailu (na jednom radku, aby nevznikali mezery navic) #}
|
||||||
|
{% for znak in org.user.email %}{% if znak == '@' %} <zavináč> {% elif znak == '.' %} <tečka> {% else %}{{znak}}{% endif %}{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% if org.foto %}
|
||||||
|
<div class="foto_org">
|
||||||
|
<img src="{{org.foto.url}}" height="{{org.foto.height}}">
|
||||||
|
<img src="{{org.foto_male.url}}" height="{{org.foto_male.height}}">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<hr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
{% for e in exports %}{{ e }}
|
|
||||||
{% endfor %}
|
|
|
|
@ -1,11 +0,0 @@
|
||||||
version 1
|
|
||||||
event MaM.rocnik
|
|
||||||
year {{ rocnik.prvni_rok }}
|
|
||||||
date {{ date }}
|
|
||||||
id-scope mam
|
|
||||||
id-generation 1
|
|
||||||
comment MaM-Web export aktivnich resitelu rocniku {{ rocnik }} do cisla {{ cislo.kod }}
|
|
||||||
|
|
||||||
{% for c in sloupce %}{{ c }} {% endfor %}
|
|
||||||
{% for r in radky %}{% for c in r %}{{ c }} {% endfor %}
|
|
||||||
{% endfor %}
|
|
Can't render this file because it has a wrong number of fields in line 11.
|
|
@ -0,0 +1,45 @@
|
||||||
|
{% extends "seminar/soustredeni/base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1> Soustředění </h1>
|
||||||
|
|
||||||
|
{# 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>
|
||||||
|
{% endif %}
|
||||||
|
{# misto soustredeni TODO upravit#}
|
||||||
|
{% if soustredeni.misto %}
|
||||||
|
<h2>
|
||||||
|
Soustředění v {{soustredeni.misto}}
|
||||||
|
od {{soustredeni.datum_zacatku}} do {{soustredeni.datum_konce}}
|
||||||
|
při {{soustredeni.rocnik.rocnik}}. ročníku M&M
|
||||||
|
</h2>
|
||||||
|
{% endif %}
|
||||||
|
{# popis soustredeni #}
|
||||||
|
{% if soustredeni.text %}
|
||||||
|
{% autoescape off %}{{soustredeni.text}}{% endautoescape %}
|
||||||
|
{% endif %}
|
||||||
|
{# Účastníci #}
|
||||||
|
<h3>Soustředění se zůčastnili tito účastníci:</h3>
|
||||||
|
<ul>
|
||||||
|
{% for i in soustredeni.soustredeni_ucastnici_set.all %}
|
||||||
|
<li>{{i.resitel}}
|
||||||
|
{% empty %}
|
||||||
|
<li>Nic!
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% empty %}
|
||||||
|
Žádná soustředění zatím neproběhla!
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -29,7 +29,7 @@ class SeminarBasicTests(TestCase):
|
||||||
def test_render_cislo_e2e(self):
|
def test_render_cislo_e2e(self):
|
||||||
cs = Cislo.objects.all()
|
cs = Cislo.objects.all()
|
||||||
for c in cs[:4]:
|
for c in cs[:4]:
|
||||||
url = reverse('seminar_cislo', args=(c.id,))
|
url = c.verejne_url()
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert len(r.content) >= 100
|
assert len(r.content) >= 100
|
||||||
|
@ -38,12 +38,25 @@ class SeminarBasicTests(TestCase):
|
||||||
def test_render_problem_e2e(self):
|
def test_render_problem_e2e(self):
|
||||||
ps = Problem.objects.all()
|
ps = Problem.objects.all()
|
||||||
for p in ps[:4]:
|
for p in ps[:4]:
|
||||||
url = reverse('seminar_problem', args=(p.id,))
|
url = p.verejne_url()
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert len(r.content) >= 100
|
assert len(r.content) >= 100
|
||||||
# TODO: Validate cntent as HTML
|
# TODO: Validate cntent as HTML
|
||||||
|
|
||||||
|
def test_export_e2e(self):
|
||||||
|
i_url = '/aesop-export/index.csv'
|
||||||
|
i_r = self.client.get(i_url)
|
||||||
|
assert i_r.status_code == 200
|
||||||
|
ls = i_r.content.strip().split('\n')
|
||||||
|
|
||||||
|
for u in [ls[0], ls[-1]]:
|
||||||
|
ex_r = self.client.get('/aesop-export/' + u)
|
||||||
|
assert ex_r.status_code == 200
|
||||||
|
assert len(ex_r.content) >= 100
|
||||||
|
o = ovvpfile.parse(ex_r.content)
|
||||||
|
assert o.headers['version'] == '1'
|
||||||
|
|
||||||
def test_admin_url(self):
|
def test_admin_url(self):
|
||||||
for m in [Skola, Resitel, Rocnik, Cislo, Problem, Reseni, Nastaveni]:
|
for m in [Skola, Resitel, Rocnik, Cislo, Problem, Reseni, Nastaveni]:
|
||||||
o = m.objects.first()
|
o = m.objects.first()
|
||||||
|
|
|
@ -5,7 +5,7 @@ import random
|
||||||
import django.contrib.auth
|
import django.contrib.auth
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni
|
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici
|
||||||
|
|
||||||
from django.contrib.flatpages.models import FlatPage
|
from django.contrib.flatpages.models import FlatPage
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
|
@ -70,7 +70,7 @@ def create_test_data(size = 6, rnd = None):
|
||||||
for ci in range(1, cisel + 1):
|
for ci in range(1, cisel + 1):
|
||||||
vydano = datetime.date(r.prvni_rok, ci + 6, 1)
|
vydano = datetime.date(r.prvni_rok, ci + 6, 1)
|
||||||
deadline = datetime.date(r.prvni_rok, ci + 8, 1) if ci + 2 < cisel else None
|
deadline = datetime.date(r.prvni_rok, ci + 8, 1) if ci + 2 < cisel else None
|
||||||
c = Cislo.objects.create(rocnik = r, cislo = str(ci), datum_vydani=vydano, datum_deadline=deadline)
|
c = Cislo.objects.create(rocnik = r, cislo = str(ci), datum_vydani=vydano, datum_deadline=deadline, verejne_db=True)
|
||||||
cs[ci] = c
|
cs[ci] = c
|
||||||
|
|
||||||
# problemy resene v ci
|
# problemy resene v ci
|
||||||
|
@ -91,6 +91,12 @@ def create_test_data(size = 6, rnd = None):
|
||||||
res = Reseni.objects.create(problem = p, resitel = resitel,
|
res = Reseni.objects.create(problem = p, resitel = resitel,
|
||||||
body = rnd.randint(0, p.body), cislo_body = cs[ci])
|
body = rnd.randint(0, p.body), cislo_body = cs[ci])
|
||||||
|
|
||||||
|
sous = Soustredeni.objects.create(rocnik=Rocnik.objects.first(), verejne_db=True, misto=u'Někde',
|
||||||
|
datum_zacatku=datetime.date(2000, 11, 23), datum_konce=datetime.date(2000, 11, 27))
|
||||||
|
for res in rnd.sample(resitele, 6):
|
||||||
|
Soustredeni_Ucastnici.objects.create(resitel=res, soustredeni=sous)
|
||||||
|
sous.save()
|
||||||
|
|
||||||
nastaveni = Nastaveni.objects.create(aktualni_rocnik = Rocnik.objects.last(),
|
nastaveni = Nastaveni.objects.create(aktualni_rocnik = Rocnik.objects.last(),
|
||||||
aktualni_cislo = Cislo.objects.all()[1])
|
aktualni_cislo = Cislo.objects.all()[1])
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,18 @@ urlpatterns = patterns('',
|
||||||
url(r'^co-je-MaM/organizatori/$', views.CojemamOrganizatoriView.as_view()),
|
url(r'^co-je-MaM/organizatori/$', views.CojemamOrganizatoriView.as_view()),
|
||||||
|
|
||||||
url(r'^archiv/cisla/$', views.CislaView.as_view()),
|
url(r'^archiv/cisla/$', views.CislaView.as_view()),
|
||||||
url(r'^archiv/cisla/rocnik/(?P<pk>\d+)/$', views.RocnikView.as_view(), name='seminar_rocnik'),
|
|
||||||
url(r'^archiv/cisla/cislo/(?P<pk>\d+)/$', views.CisloView.as_view(), name='seminar_cislo'),
|
|
||||||
url(r'^archiv/cisla/problem/(?P<pk>\d+)/$', views.ProblemView.as_view(), name='seminar_problem'),
|
|
||||||
|
|
||||||
|
url(r'^rocnik/(?P<rocnik>\d+)/$', views.RocnikView.as_view(), name='seminar_rocnik'),
|
||||||
|
url(r'^cislo/(?P<rocnik>\d+)\.(?P<cislo>\d+)/$', views.CisloView.as_view(), name='seminar_cislo'),
|
||||||
|
url(r'^problem/(?P<pk>\d+)/$', views.ProblemView.as_view(), name='seminar_problem'),
|
||||||
|
|
||||||
|
url(r'^soustredeni/$', views.SoustredeniListView.as_view(),
|
||||||
|
name = 'seminar_seznam_soustredeni'),
|
||||||
url(r'^soustredeni/(?P<pk>\d+)/$', views.SoustredeniView.as_view(), name='seminar_soustredeni'),
|
url(r'^soustredeni/(?P<pk>\d+)/$', views.SoustredeniView.as_view(), name='seminar_soustredeni'),
|
||||||
|
|
||||||
url(r'^zadani/aktualni/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
|
url(r'^zadani/aktualni/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
|
||||||
|
|
||||||
url(r'^aesop-export/mam-rocnik-(?P<prvni_rok>\d+)\.csv$', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'),
|
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'),
|
url(r'^aesop-export/index.csv$', export.ExportIndexView.as_view(), name='seminar_export_index'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,10 @@ from django.shortcuts import get_object_or_404, render
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik, Soustredeni
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.http import Http404
|
||||||
|
|
||||||
|
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik, Soustredeni, Organizator
|
||||||
|
|
||||||
|
|
||||||
def AktualniZadaniView(request):
|
def AktualniZadaniView(request):
|
||||||
|
@ -12,11 +15,14 @@ def AktualniZadaniView(request):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Co je M&M
|
### Co je M&M
|
||||||
|
|
||||||
class CojemamOrganizatoriView(generic.TemplateView):
|
class CojemamOrganizatoriView(generic.ListView):
|
||||||
|
model = Organizator
|
||||||
template_name='seminar/cojemam/organizatori.html'
|
template_name='seminar/cojemam/organizatori.html'
|
||||||
|
|
||||||
|
### Archiv
|
||||||
|
|
||||||
class CislaView(generic.ListView):
|
class CislaView(generic.ListView):
|
||||||
model = Rocnik
|
model = Rocnik
|
||||||
template_name='seminar/archiv/cisla.html'
|
template_name='seminar/archiv/cisla.html'
|
||||||
|
@ -25,9 +31,19 @@ class RocnikView(generic.DetailView):
|
||||||
model = Rocnik
|
model = Rocnik
|
||||||
template_name = 'seminar/archiv/rocnik.html'
|
template_name = 'seminar/archiv/rocnik.html'
|
||||||
|
|
||||||
class SoustredeniView(generic.DetailView):
|
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
||||||
model = Soustredeni
|
def get_object(self, queryset=None):
|
||||||
template_name = 'seminar/archiv/soustredeni.html'
|
if queryset is None:
|
||||||
|
queryset = self.get_queryset()
|
||||||
|
rocnik_arg = self.kwargs.get('rocnik')
|
||||||
|
queryset = queryset.filter(rocnik=rocnik_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})
|
||||||
|
return obj
|
||||||
|
|
||||||
class ProblemView(generic.DetailView):
|
class ProblemView(generic.DetailView):
|
||||||
model = Problem
|
model = Problem
|
||||||
|
@ -39,26 +55,50 @@ class RadekVysledkovky(object):
|
||||||
class CisloView(generic.DetailView):
|
class CisloView(generic.DetailView):
|
||||||
model = Cislo
|
model = Cislo
|
||||||
template_name = 'seminar/archiv/cislo.html'
|
template_name = 'seminar/archiv/cislo.html'
|
||||||
|
|
||||||
|
# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
|
||||||
|
def get_object(self, queryset=None):
|
||||||
|
if queryset is None:
|
||||||
|
queryset = self.get_queryset()
|
||||||
|
rocnik_arg = self.kwargs.get('rocnik')
|
||||||
|
cislo_arg = self.kwargs.get('cislo')
|
||||||
|
queryset = queryset.filter(rocnik__rocnik=rocnik_arg, cislo=cislo_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})
|
||||||
|
return obj
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(CisloView, self).get_context_data(**kwargs)
|
context = super(CisloView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
# Vysledky k cislu: seznam objektu typu (cislo, resitel, body [v tom cisle], body_celkem [od zac. rocniku])
|
||||||
vysledky = VysledkyKCislu.objects.filter(cislo = context['cislo']).order_by('-body_celkem').select_related("resitel")
|
vysledky = VysledkyKCislu.objects.filter(cislo = context['cislo']).order_by('-body_celkem').select_related("resitel")
|
||||||
|
|
||||||
reseni = Reseni.objects.filter(cislo_body = context['cislo']).select_related("resitel")
|
reseni = Reseni.objects.filter(cislo_body = context['cislo']).select_related("resitel")
|
||||||
|
|
||||||
|
# seznam problemu s nejakymi body v tomto cisle
|
||||||
problemy = sorted(list(set([r.problem for r in reseni])), key=lambda x:(0 if x.typ==Problem.TYP_ULOHA else 1,x.kod))
|
problemy = sorted(list(set([r.problem for r in reseni])), key=lambda x:(0 if x.typ==Problem.TYP_ULOHA else 1,x.kod))
|
||||||
|
# cislo sloupecku pro problem (inverzni funkce)
|
||||||
problem_index = {}
|
problem_index = {}
|
||||||
for i in range(len(problemy)):
|
for i in range(len(problemy)):
|
||||||
problem_index[problemy[i].id] = i
|
problem_index[problemy[i].id] = i
|
||||||
|
|
||||||
|
# pomocna mapa Resitel: RadekVysledkovky
|
||||||
vysledky_resitele = {}
|
vysledky_resitele = {}
|
||||||
|
# radky vysledkovky, seznam objektu RadekVysledkovky
|
||||||
vysledkovka = []
|
vysledkovka = []
|
||||||
|
# posledni pocet bodu, pro detekci stejnych mist
|
||||||
posledni_body = 100000
|
posledni_body = 100000
|
||||||
|
|
||||||
for vi in range(len(vysledky)):
|
for vi in range(len(vysledky)):
|
||||||
v = vysledky[vi]
|
v = vysledky[vi]
|
||||||
tv = RadekVysledkovky()
|
tv = RadekVysledkovky()
|
||||||
tv.resitel = v.resitel
|
tv.resitel = v.resitel
|
||||||
tv.vysledek = v
|
tv.vysledek = v
|
||||||
tv.body = ['']*len(problemy)
|
tv.body = ['']*len(problemy) # misto pro body za jednotlive uloy
|
||||||
tv.poradi = ''
|
tv.poradi = ''
|
||||||
if posledni_body > v.body_celkem:
|
if posledni_body > v.body_celkem:
|
||||||
posledni_body = v.body_celkem
|
posledni_body = v.body_celkem
|
||||||
|
@ -66,6 +106,7 @@ class CisloView(generic.DetailView):
|
||||||
vysledky_resitele[v.resitel.id] = tv
|
vysledky_resitele[v.resitel.id] = tv
|
||||||
vysledkovka.append(tv)
|
vysledkovka.append(tv)
|
||||||
|
|
||||||
|
# doplneni bodu za jednotliva reseni lidi do RadekVysledkovky.body
|
||||||
for r in reseni:
|
for r in reseni:
|
||||||
vysledky_resitele[r.resitel.id].body[problem_index[r.problem.id]] = r.body
|
vysledky_resitele[r.resitel.id].body[problem_index[r.problem.id]] = r.body
|
||||||
|
|
||||||
|
@ -73,4 +114,12 @@ class CisloView(generic.DetailView):
|
||||||
context['problemy'] = problemy
|
context['problemy'] = problemy
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
### Soustredeni
|
||||||
|
|
||||||
|
class SoustredeniListView(generic.ListView):
|
||||||
|
model = Soustredeni
|
||||||
|
template_name = 'seminar/soustredeni/seznam_soustredeni.html'
|
||||||
|
|
||||||
|
class SoustredeniView(generic.DetailView):
|
||||||
|
model = Soustredeni
|
||||||
|
template_name = 'seminar/archiv/soustredeni.html'
|
||||||
|
|
Loading…
Reference in a new issue