Merge branch 'master' of atrey.karlin.mff.cuni.cz:/akce/MaM/MaMweb/mamweb
This commit is contained in:
commit
bd32ed5d96
9 changed files with 171 additions and 60 deletions
|
@ -33,19 +33,26 @@ DATABASES = {
|
|||
|
||||
import os
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': True,
|
||||
'handlers': {
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
'handlers': ['console'],
|
||||
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
|
||||
},
|
||||
},
|
||||
}
|
||||
SERVER_EMAIL = 'mamweb-prod-errors@mam.mff.cuni.cz'
|
||||
ADMINS = [
|
||||
('Tomas Gavenciak', 'gavento@ucw.cz'),
|
||||
]
|
||||
|
||||
|
||||
# LOGGING = {
|
||||
# 'version': 1,
|
||||
# 'disable_existing_loggers': True,
|
||||
# 'handlers': {
|
||||
# 'console': {
|
||||
# 'class': 'logging.StreamHandler',
|
||||
# },
|
||||
# },
|
||||
# 'loggers': {
|
||||
# 'django': {
|
||||
# 'handlers': ['console'],
|
||||
# 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
|
||||
# },
|
||||
# },
|
||||
# }
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib import admin
|
||||
from django import forms
|
||||
from django.forms import widgets
|
||||
|
@ -12,6 +13,23 @@ from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, Prilo
|
|||
import autocomplete_light
|
||||
|
||||
|
||||
def make_set_action(atribut, hodnota, nazev):
|
||||
u"""
|
||||
Pomocnik pro rychle vytvareni hromadnych admin akci ktere jen nastavuji
|
||||
atribut (dany jako string) na danou hodnotu.
|
||||
nazev je krátký popis akce pro admin rozhraní."""
|
||||
def action_f(modeladmin, request, queryset):
|
||||
for obj in queryset:
|
||||
assert atribut in obj.__dict__
|
||||
obj.__setattr__(atribut, hodnota)
|
||||
obj.save()
|
||||
action_f.short_description = nazev
|
||||
# Trik: je potřeba, aby se funkce různě (ale libovolně) jmenovaly,
|
||||
# jinak je Django v seznamu akcí splácne do jedné
|
||||
action_f.__name__ = 'action_f_%d_%d_%d' % (id(atribut), id(hodnota), id(nazev), )
|
||||
return action_f
|
||||
|
||||
|
||||
### Globální nastavení
|
||||
|
||||
admin.site.register(Nastaveni, SingletonModelAdmin)
|
||||
|
@ -142,7 +160,7 @@ class ResitelAdmin(reversion.VersionAdmin):
|
|||
]
|
||||
list_display = ['jmeno', 'prijmeni', 'user', 'pohlavi_muz', 'skola', 'rok_maturity', 'pocet_reseni']
|
||||
list_filter = ['pohlavi_muz', 'rok_maturity', 'zasilat']
|
||||
search_fields = ['jmeno', 'prijmeni', 'ulice', 'user', 'mesto', 'email']
|
||||
search_fields = ['jmeno', 'prijmeni', 'ulice', 'mesto', 'email']
|
||||
inlines = [ReseniKResiteliInline]
|
||||
|
||||
def get_queryset(self, request):
|
||||
|
@ -180,10 +198,16 @@ class CisloAdmin(reversion.VersionAdmin):
|
|||
(None, {'fields': ['cislo', 'rocnik', 'verejne_db', 'verejna_vysledkovka', 'poznamka']}),
|
||||
(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', 'verejna_vysledkovka']
|
||||
list_display = ['kod', 'rocnik', 'cislo', 'datum_vydani', 'datum_deadline', 'verejne', 'verejna_vysledkovka']
|
||||
list_filter = ['rocnik']
|
||||
view_on_site = Cislo.verejne_url
|
||||
actions = [
|
||||
make_set_action('verejne_db', True, u'Zveřejnit číslo'),
|
||||
make_set_action('verejne_db', False, u'Skrýt (zneveřejnit) číslo'),
|
||||
make_set_action('verejna_vysledkovka', True, u'Zveřejnit výsledkovku'),
|
||||
make_set_action('verejna_vysledkovka', False, u'Skrýt (zneveřejnit) výsledkovku'),
|
||||
]
|
||||
|
||||
def get_queryset(self, request):
|
||||
qs = super(CisloAdmin, self).get_queryset(request)
|
||||
return qs.select_related('rocnik')
|
||||
|
@ -194,11 +218,15 @@ admin.site.register(Cislo, CisloAdmin)
|
|||
|
||||
class RocnikAdmin(reversion.VersionAdmin):
|
||||
fieldsets = [
|
||||
(None, {'fields': ['rocnik', 'prvni_rok']}),
|
||||
(None, {'fields': ['rocnik', 'prvni_rok', 'exportovat']}),
|
||||
]
|
||||
list_display = ['rocnik', 'prvni_rok', 'verejne']
|
||||
list_display = ['rocnik', 'prvni_rok', 'exportovat', 'verejne']
|
||||
inlines = [CisloInline]
|
||||
view_on_site = Rocnik.verejne_url
|
||||
actions = [
|
||||
make_set_action('exportovat', True, u'Nastavit pro AESOP export'),
|
||||
make_set_action('exportovat', False, u'Skrýt pro AESOP export'),
|
||||
]
|
||||
|
||||
admin.site.register(Rocnik, RocnikAdmin)
|
||||
|
||||
|
@ -298,18 +326,6 @@ create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'P
|
|||
|
||||
### 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):
|
||||
text = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Soustredeni, 'text'))
|
||||
class Meta:
|
||||
|
@ -319,14 +335,19 @@ class SoustredeniAdminForm(forms.ModelForm):
|
|||
class SoustredeniAdmin(reversion.VersionAdmin):
|
||||
form = SoustredeniAdminForm
|
||||
fieldsets = [
|
||||
(None, {'fields': ['rocnik', 'misto', 'verejne_db', 'text']}),
|
||||
(None, {'fields': ['rocnik', 'misto', 'typ', 'verejne_db', 'exportovat', 'text']}),
|
||||
(u'Data', {'fields': ['datum_zacatku', 'datum_konce']}),
|
||||
]
|
||||
list_display = ['rocnik', 'misto', 'datum_zacatku', 'verejne']
|
||||
list_display = ['rocnik', 'misto', 'datum_zacatku', 'typ', 'exportovat', 'verejne']
|
||||
inlines = [Soustredeni_UcastniciInline]
|
||||
list_filter = ['rocnik']
|
||||
list_filter = ['typ', 'rocnik']
|
||||
view_on_site = Soustredeni.verejne_url
|
||||
actions = [zverejnit_soustredeni, skryt_soustredeni, ]
|
||||
actions = [
|
||||
make_set_action('verejne_db', True, u'Zveřejnit soustředění'),
|
||||
make_set_action('verejne_db', False, u'Skrýt (zneveřejnit) soustředění'),
|
||||
make_set_action('exportovat', True, u'Nastavit pro AESOP export'),
|
||||
make_set_action('exportovat', False, u'Skrýt pro AESOP export'),
|
||||
]
|
||||
|
||||
admin.site.register(Soustredeni, SoustredeniAdmin)
|
||||
|
||||
|
|
|
@ -12,14 +12,12 @@ class ExportIndexView(generic.View):
|
|||
def get(self, request):
|
||||
|
||||
ls = []
|
||||
for r in Rocnik.objects.all():
|
||||
if r.verejna_cisla():
|
||||
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
||||
ls.append(url.split('/')[-1])
|
||||
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])
|
||||
for r in Rocnik.objects.filter(exportovat = True):
|
||||
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
||||
ls.append(url.split('/')[-1])
|
||||
for s in Soustredeni.objects.filter(exportovat = True):
|
||||
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')
|
||||
|
||||
|
@ -45,9 +43,14 @@ class ExportSousView(generic.View):
|
|||
if dz is None:
|
||||
raise django.http.Http404()
|
||||
|
||||
s = get_object_or_404(Soustredeni, datum_zacatku=dz)
|
||||
s = get_object_or_404(Soustredeni, datum_zacatku=dz, exportovat=True)
|
||||
|
||||
of = default_ovvpfile('MaM.sous', s.rocnik)
|
||||
akce = {Soustredeni.TYP_JARNI: 'MaM.sous.jaro',
|
||||
Soustredeni.TYP_PODZIMNI: 'MaM.sous.podzim',
|
||||
Soustredeni.TYP_VIKEND: 'MaM.vikend',
|
||||
}[s.typ]
|
||||
|
||||
of = default_ovvpfile(akce, 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
|
||||
|
@ -70,8 +73,8 @@ class ExportRocnikView(generic.View):
|
|||
if pr is None:
|
||||
raise django.http.Http404()
|
||||
|
||||
rocnik = get_object_or_404(Rocnik, prvni_rok=pr)
|
||||
cislo = rocnik.posledni_verejne_cislo()
|
||||
rocnik = get_object_or_404(Rocnik, prvni_rok=pr, exportovat=True)
|
||||
cislo = rocnik.posledni_zverejnena_vysledkovka_cislo()
|
||||
vysledky = VysledkyKCislu.objects.filter(cislo = cislo).select_related("resitel").order_by('-body_celkem').all()
|
||||
|
||||
of = default_ovvpfile('MaM.rocnik', rocnik)
|
||||
|
|
|
@ -5,7 +5,6 @@ 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):
|
||||
|
||||
|
|
20
seminar/migrations/0026_soustredeni_typ.py
Normal file
20
seminar/migrations/0026_soustredeni_typ.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', '0025_zmena_cesty_nahravani_obrazku'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='soustredeni',
|
||||
name='typ',
|
||||
field=models.CharField(default=b'podzimni', max_length=16, verbose_name='typ akce', choices=[(b'jarni', 'Jarn\xed soust\u0159ed\u011bn\xed'), (b'podzimni', 'Podzimn\xed soust\u0159ed\u011bn\xed'), (b'sraz', 'Nepravideln\xfd sraz')]),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
32
seminar/migrations/0027_export_flag_a_typ_akce.py
Normal file
32
seminar/migrations/0027_export_flag_a_typ_akce.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', '0026_soustredeni_typ'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='rocnik',
|
||||
name='exportovat',
|
||||
field=models.BooleanField(default=False, help_text='Exportuje se jen podle tohoto flagu (ne ve\u0159ejnosti), a to jen \u010d\xedsla s ve\u0159ejnou v\xfdsledkovkou', verbose_name='export do AESOPa', db_column=b'exportovat'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='soustredeni',
|
||||
name='exportovat',
|
||||
field=models.BooleanField(default=False, help_text='Exportuje se jen podle tohoto flagu (ne ve\u0159ejnosti)', verbose_name='export do AESOPa', db_column=b'exportovat'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='soustredeni',
|
||||
name='typ',
|
||||
field=models.CharField(default=b'podzimni', max_length=16, verbose_name='typ akce', choices=[(b'jarni', 'Jarn\xed soust\u0159ed\u011bn\xed'), (b'podzimni', 'Podzimn\xed soust\u0159ed\u011bn\xed'), (b'vikend', 'V\xedkendov\xfd sraz')]),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -195,7 +195,7 @@ class Resitel(SeminarModelBase):
|
|||
'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,
|
||||
'end-year': self.rok_maturity or '',
|
||||
|
||||
# TODO(gavento): Adresa skoly, kdyz preferuje zasilani tam?
|
||||
'street': self.ulice,
|
||||
|
@ -210,18 +210,21 @@ class Resitel(SeminarModelBase):
|
|||
'school-name': str(self.skola) if self.skola else 'Skola neni znama',
|
||||
}
|
||||
|
||||
def rocnik(self, datum):
|
||||
"Vypise skolni rocnik resitele pro zadane datum typu datetime."
|
||||
rozdil = self.rok_maturity - datum.year
|
||||
if datum.month < 9:
|
||||
return 4 - rozdil
|
||||
else:
|
||||
return 5 - rozdil
|
||||
def rocnik(self, rocnik):
|
||||
"""Vrati skolni rocnik resitele pro zadany Rocnik.
|
||||
Vraci '' pro neznamy rok maturity resitele, Z* pro ekvivalent ZŠ."""
|
||||
if self.rok_maturity is None:
|
||||
return ''
|
||||
rozdil = 5 - (self.rok_maturity - rocnik.prvni_rok)
|
||||
if rozdil >= 1:
|
||||
return str(rozdil)
|
||||
else:
|
||||
return 'Z' + str(rozdil + 9)
|
||||
|
||||
def titul(self, celkove_body):
|
||||
"Vrati titul podle zadaneho poctu bodu."
|
||||
if celkove_body < 10:
|
||||
return None
|
||||
return ''
|
||||
elif celkove_body < 20:
|
||||
return 'Bc.'
|
||||
elif celkove_body < 50:
|
||||
|
@ -254,6 +257,9 @@ class Rocnik(SeminarModelBase):
|
|||
|
||||
rocnik = models.IntegerField(u'číslo ročníku', db_index=True, unique=True)
|
||||
|
||||
exportovat = models.BooleanField(u'export do AESOPa', db_column='exportovat', default=False,
|
||||
help_text=u'Exportuje se jen podle tohoto flagu (ne veřejnosti), a to jen čísla s veřejnou výsledkovkou')
|
||||
|
||||
def __str__(self):
|
||||
return force_unicode(u'%s (%d/%d)' % (self.rocnik, self.prvni_rok, self.prvni_rok+1))
|
||||
|
||||
|
@ -263,6 +269,7 @@ class Rocnik(SeminarModelBase):
|
|||
def verejne(self):
|
||||
return len(self.verejna_cisla()) > 0
|
||||
verejne.boolean = True
|
||||
verejne.short_description = u'Veřejný (jen dle čísel)'
|
||||
|
||||
def verejna_cisla(self):
|
||||
vc = [c for c in self.cisla.all() if c.verejne()]
|
||||
|
@ -273,6 +280,15 @@ class Rocnik(SeminarModelBase):
|
|||
vc = self.verejna_cisla()
|
||||
return vc[-1] if vc else None
|
||||
|
||||
def verejne_vysledkovky_cisla(self):
|
||||
vc = list(self.cisla.filter(verejna_vysledkovka=True))
|
||||
vc.sort(key=lambda c: c.cislo)
|
||||
return vc
|
||||
|
||||
def posledni_zverejnena_vysledkovka_cislo(self):
|
||||
vc = self.verejne_vysledkovky_cisla()
|
||||
return vc[-1] if vc else None
|
||||
|
||||
def druhy_rok(self):
|
||||
return self.prvni_rok + 1
|
||||
|
||||
|
@ -565,6 +581,19 @@ class Soustredeni(SeminarModelBase):
|
|||
|
||||
text = models.TextField(u'text k soustředění (HTML)', blank=True, default='')
|
||||
|
||||
TYP_JARNI = 'jarni'
|
||||
TYP_PODZIMNI = 'podzimni'
|
||||
TYP_VIKEND = 'vikend'
|
||||
TYP_CHOICES = [
|
||||
(TYP_JARNI, u'Jarní soustředění'),
|
||||
(TYP_PODZIMNI, u'Podzimní soustředění'),
|
||||
(TYP_VIKEND, u'Víkendový sraz'),
|
||||
]
|
||||
typ = models.CharField(u'typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI)
|
||||
|
||||
exportovat = models.BooleanField(u'export do AESOPa', db_column='exportovat', default=False,
|
||||
help_text=u'Exportuje se jen podle tohoto flagu (ne veřejnosti)')
|
||||
|
||||
def __str__(self):
|
||||
return force_unicode(u'%s (%s)' % (self.misto, self.datum_zacatku))
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
{% if rv.resitel.titul %}
|
||||
\titul{ {{ rv.resitel.titul }} }
|
||||
{% endif %}
|
||||
{{ rv.resitel.plne_jmeno }} & {{ rv.resitel.rocnik}} & {{ rv.body_minule }}
|
||||
{{ rv.resitel.plne_jmeno }} & {{ rv.resitel.rocnik |default:"" }} & {{ rv.body_minule }}
|
||||
{% for b in rv.body %}
|
||||
{{ b }} &
|
||||
{% endfor %}
|
||||
|
|
|
@ -96,7 +96,7 @@ class CisloView(generic.DetailView):
|
|||
v = vysledky[vi]
|
||||
tv = RadekVysledkovky()
|
||||
tv.resitel = v.resitel
|
||||
tv.rocnik = tv.resitel.rocnik(context['cislo'].datum_vydani)
|
||||
tv.rocnik = tv.resitel.rocnik(context['cislo'].rocnik)
|
||||
tv.resitel.titul = tv.resitel.titul(v.body_celkem)
|
||||
tv.vysledek = v
|
||||
#odkazuje na VysledkyKCislu
|
||||
|
|
Loading…
Reference in a new issue