Web M&M
https://mam.matfyz.cz
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
16 KiB
433 lines
16 KiB
# -*- coding: utf-8 -*-
|
|
|
|
from django.contrib import admin
|
|
from django import forms
|
|
from django.forms import widgets
|
|
import reversion
|
|
from solo.admin import SingletonModelAdmin
|
|
from ckeditor.widgets import CKEditorWidget
|
|
from django.db.models import Count
|
|
from django.db import models
|
|
|
|
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Novinky, Organizator
|
|
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)
|
|
|
|
|
|
### UTILS (pro verbose_name a help_text)
|
|
|
|
def field_labels(model, fieldname):
|
|
f = [i for i in model._meta.fields if i.name == fieldname][0]
|
|
return {'label': f.verbose_name.capitalize(), 'help_text': f.help_text, }
|
|
|
|
def create_modeladmin(modeladmin, model, name = None, verbose_name = None, verbose_name_plural = None):
|
|
|
|
class Meta:
|
|
proxy = True
|
|
app_label = model._meta.app_label
|
|
Meta.verbose_name = verbose_name
|
|
Meta.verbose_name_plural = verbose_name_plural
|
|
|
|
attrs = {'__module__': '', 'Meta': Meta}
|
|
newmodel = type(name, (model,), attrs)
|
|
admin.site.register(newmodel, modeladmin)
|
|
return modeladmin
|
|
|
|
### INLINES
|
|
|
|
class ResitelInline(admin.TabularInline):
|
|
model = Resitel
|
|
fields = ['jmeno', 'prijmeni', 'skola', 'mesto', 'rok_maturity', ]
|
|
readonly_fields = ['jmeno', 'prijmeni', 'skola', 'mesto', 'rok_maturity', ]
|
|
extra = 0
|
|
|
|
def has_add_permission(self, req): return False
|
|
|
|
|
|
class CisloInline(admin.TabularInline):
|
|
model = Cislo
|
|
fields = ['cislo', 'datum_vydani', 'datum_deadline', 'verejne_db', 'poznamka']
|
|
readonly_fields = ['cislo']
|
|
extra = 0
|
|
formfield_overrides = {
|
|
models.TextField: {'widget': forms.TextInput},
|
|
}
|
|
|
|
def has_add_permission(self, req): return False
|
|
|
|
|
|
class PrilohaReseniInline(admin.StackedInline):
|
|
model = PrilohaReseni
|
|
fields = ['timestamp', 'soubor', 'poznamka']
|
|
readonly_fields = ['timestamp']
|
|
formfield_overrides = {
|
|
models.TextField: {'widget': forms.TextInput},
|
|
}
|
|
|
|
extra = 0
|
|
|
|
class ReseniKProblemuInline(admin.TabularInline):
|
|
form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['resitel'], fields=['resitel'])
|
|
model = Reseni
|
|
fields = ['resitel', 'forma', 'body', 'cislo_body', 'timestamp', 'poznamka']
|
|
readonly_fields = ['timestamp']
|
|
extra = 0
|
|
formfield_overrides = {
|
|
models.TextField: {'widget': forms.TextInput},
|
|
}
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ReseniKProblemuInline, self).get_queryset(request)
|
|
return qs.select_related('problem', 'cislo_body', 'resitel')
|
|
|
|
# Potenciální DB HOG (cislo_body se dotazovalo na cisla pri kazdem zobrazeni jejich selectu ...)
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
formfield = super(ReseniKProblemuInline, self).formfield_for_dbfield(db_field, **kwargs)
|
|
if db_field.name == 'cislo_body':
|
|
# dirty trick so queryset is evaluated and cached in .choices
|
|
formfield.choices = formfield.choices
|
|
return formfield
|
|
|
|
|
|
class ReseniKResiteliInline(admin.TabularInline):
|
|
model = Reseni
|
|
fields = ['problem', 'forma', 'body', 'cislo_body', 'timestamp', 'poznamka']
|
|
readonly_fields = ['timestamp', 'problem']
|
|
extra = 0
|
|
formfield_overrides = {
|
|
models.TextField: {'widget': forms.TextInput},
|
|
}
|
|
|
|
def has_add_permission(self, req): return False
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ReseniKResiteliInline, self).get_queryset(request)
|
|
return qs.select_related('problem', 'cislo_body', 'resitel')
|
|
|
|
# Potenciální DB HOG (cislo_body se dotazovalo na cisla pri kazdem zobrazeni jejich selectu ...)
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
formfield = super(ReseniKResiteliInline, self).formfield_for_dbfield(db_field, **kwargs)
|
|
if db_field.name == 'cislo_body':
|
|
# dirty trick so queryset is evaluated and cached in .choices
|
|
formfield.choices = formfield.choices
|
|
return formfield
|
|
|
|
|
|
class Soustredeni_UcastniciInline(admin.TabularInline):
|
|
form = autocomplete_light.modelform_factory(Soustredeni_Ucastnici, autocomplete_fields=['resitel'], fields=['resitel'])
|
|
model = Soustredeni_Ucastnici
|
|
fields = ['resitel', 'poznamka', ]
|
|
extra = 0
|
|
formfield_overrides = {
|
|
models.TextField: {'widget': forms.TextInput},
|
|
}
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(Soustredeni_UcastniciInline, self).get_queryset(request)
|
|
return qs.select_related('resitel', 'soustredeni')
|
|
|
|
### Resitel
|
|
|
|
class ResitelAdmin(reversion.VersionAdmin):
|
|
form = autocomplete_light.modelform_factory(Resitel, autocomplete_fields=['skola'], fields=['skola'])
|
|
fieldsets = [
|
|
(None, {'fields': ['jmeno', 'prijmeni', 'user']}),
|
|
(u'Škola', {'fields': ['skola', 'rok_maturity']}),
|
|
(u'Seminář', {'fields': ['datum_souhlasu_udaje', 'datum_souhlasu_zasilani', 'datum_prihlaseni', 'zasilat']}),
|
|
(u'Osobní údaje', {'fields': ['pohlavi_muz', 'datum_narozeni', 'email', 'telefon']}),
|
|
(u'Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
|
|
]
|
|
list_display = ['jmeno', 'prijmeni', 'user', 'pohlavi_muz', 'skola', 'rok_maturity', 'pocet_reseni']
|
|
list_filter = ['pohlavi_muz', 'rok_maturity', 'zasilat']
|
|
search_fields = ['jmeno', 'prijmeni', 'ulice', 'mesto', 'email']
|
|
inlines = [ReseniKResiteliInline]
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ResitelAdmin, self).get_queryset(request)
|
|
return qs.select_related('skola', 'user').annotate(pocet_reseni=Count('reseni'))
|
|
|
|
def pocet_reseni(self, obj):
|
|
return obj.pocet_reseni
|
|
|
|
|
|
admin.site.register(Resitel, ResitelAdmin)
|
|
|
|
|
|
### Skola
|
|
|
|
class SkolaAdmin(reversion.VersionAdmin):
|
|
fieldsets = [
|
|
(None, {'fields': ['nazev', 'kratky_nazev', 'je_zs', 'je_ss']}),
|
|
(u'Interní ID', {'fields': ['aesop_id', 'izo'], 'classes': ['collapse']}),
|
|
(u'Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
|
|
(None, {'fields': ['poznamka']}),
|
|
]
|
|
list_display = ['nazev', 'aesop_id', 'mesto', 'ulice', 'stat', 'je_zs', 'je_ss']
|
|
list_filter = ['stat', 'je_zs', 'je_ss']
|
|
search_fields = ['nazev', 'mesto', 'ulice']
|
|
inlines = [ResitelInline]
|
|
|
|
admin.site.register(Skola, SkolaAdmin)
|
|
|
|
|
|
### Cislo
|
|
|
|
class CisloAdmin(reversion.VersionAdmin):
|
|
fieldsets = [
|
|
(None, {'fields': ['cislo', 'rocnik', 'verejne_db', 'verejna_vysledkovka', 'poznamka', 'pdf']}),
|
|
(u'Data', {'fields': ['datum_vydani', 'datum_deadline']}),
|
|
]
|
|
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')
|
|
|
|
admin.site.register(Cislo, CisloAdmin)
|
|
|
|
### Rocnik
|
|
|
|
class RocnikAdmin(reversion.VersionAdmin):
|
|
fieldsets = [
|
|
(None, {'fields': ['rocnik', 'prvni_rok', 'exportovat']}),
|
|
]
|
|
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)
|
|
|
|
|
|
### PrilohaReseni
|
|
# NOTE: Nemá pravděpodobně smysl používat
|
|
# class PrilohaReseniAdmin(reversion.VersionAdmin):
|
|
# readonly_fields = ['timestamp', 'reseni']
|
|
# fieldsets = [
|
|
# (None, {'fields': ['reseni', 'soubor', 'timestamp']}),
|
|
# (u'Poznámky', {'fields': ['poznamka']}),
|
|
# ]
|
|
# list_display = ['reseni', 'soubor', 'timestamp']
|
|
# list_filter = ['reseni', 'timestamp']
|
|
# search_fields = []
|
|
#
|
|
# admin.site.register(PrilohaReseni, PrilohaReseniAdmin)
|
|
|
|
|
|
### Reseni
|
|
|
|
class ReseniAdmin(reversion.VersionAdmin):
|
|
form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['problem', 'resitel'], fields=['problem', 'resitel'])
|
|
fieldsets = [
|
|
(None, {'fields': ['problem', 'resitel', 'forma', 'body', 'cislo_body', 'timestamp']}),
|
|
(u'Poznámky', {'fields': ['poznamka']}),
|
|
]
|
|
readonly_fields = ['timestamp']
|
|
list_display = ['problem', 'resitel', 'forma', 'body', 'timestamp', 'cislo_body']
|
|
list_filter = ['body', 'timestamp', 'forma']
|
|
search_fields = []
|
|
inlines = [PrilohaReseniInline]
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ReseniAdmin, self).get_queryset(request)
|
|
return qs.select_related('resitel', 'problem', 'cislo_body')
|
|
|
|
admin.site.register(Reseni, ReseniAdmin)
|
|
|
|
|
|
### Problem
|
|
|
|
from autocomplete_light.contrib.taggit_field import TaggitField, TaggitWidget
|
|
|
|
#TODO: Autocomplete autor/opravovatel
|
|
|
|
class ProblemAdminForm(forms.ModelForm):
|
|
text_zadani = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Problem, 'text_zadani'))
|
|
text_reseni = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Problem, 'text_reseni'))
|
|
text_org = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Problem, 'text_org'))
|
|
zamereni = TaggitField(widget=TaggitWidget('TagAutocomplete'), required=False)
|
|
class Meta:
|
|
model = Problem
|
|
exclude = []
|
|
|
|
class ProblemAdmin(reversion.VersionAdmin):
|
|
form = ProblemAdminForm
|
|
fieldsets = [
|
|
(None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp', 'import_dakos_id']}),
|
|
(u'Vydání', {'fields': ['cislo_zadani', 'kod', 'cislo_reseni', 'opravovatel',]}),
|
|
(None, {'fields': ['text_zadani', 'text_reseni', 'text_org',]}),
|
|
]
|
|
readonly_fields = ['timestamp', 'import_dakos_id']
|
|
list_select_related = True
|
|
search_fields = ['nazev', 'text_zadani', 'text_reseni', 'text_org']
|
|
view_on_site = Problem.verejne_url
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ProblemAdmin, self).get_queryset(request)
|
|
return qs.select_related('autor', 'opravovatel', 'cislo_zadani', 'cislo_reseni')
|
|
|
|
def pocet_reseni(self, obj):
|
|
return obj.pocet_reseni
|
|
|
|
class ProblemNavrhAdmin(ProblemAdmin):
|
|
list_display = ['nazev', 'typ', 'zamereni', 'stav', 'autor', 'timestamp']
|
|
list_filter = ['typ', 'zamereni', 'timestamp', 'stav']
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ProblemNavrhAdmin, self).get_queryset(request)
|
|
return qs.filter(stav__in=[Problem.STAV_NAVRH, Problem.STAV_SMAZANY])
|
|
|
|
create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name=u'Problém (návrh)', verbose_name_plural=u'Problémy (návrhy)')
|
|
|
|
class ProblemZadanyAdmin(ProblemAdmin):
|
|
list_display = ['nazev', 'typ', 'autor', 'opravovatel', 'kod', 'cislo_zadani', 'pocet_reseni', 'verejne']
|
|
list_filter = ['typ', 'cislo_zadani__cislo', 'cislo_zadani__rocnik']
|
|
inlines = [ReseniKProblemuInline]
|
|
|
|
def get_queryset(self, request):
|
|
qs = super(ProblemZadanyAdmin, self).get_queryset(request)
|
|
return qs.filter(stav=Problem.STAV_ZADANY).annotate(pocet_reseni=Count('reseni'))
|
|
|
|
create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'Problém (zadaný)', verbose_name_plural=u'Problémy (zadané)')
|
|
|
|
#admin.site.register(Problem, ProblemAdmin)
|
|
|
|
### Soustredeni
|
|
|
|
class SoustredeniAdminForm(forms.ModelForm):
|
|
text = forms.CharField(widget=CKEditorWidget(), required=False, **field_labels(Soustredeni, 'text'))
|
|
class Meta:
|
|
model = Soustredeni
|
|
exclude = []
|
|
|
|
class SoustredeniAdmin(reversion.VersionAdmin):
|
|
form = SoustredeniAdminForm
|
|
fieldsets = [
|
|
(None, {'fields': ['rocnik', 'misto', 'typ', 'verejne_db', 'exportovat', 'text']}),
|
|
(u'Data', {'fields': ['datum_zacatku', 'datum_konce']}),
|
|
]
|
|
list_display = ['rocnik', 'misto', 'datum_zacatku', 'typ', 'exportovat', 'verejne']
|
|
inlines = [Soustredeni_UcastniciInline]
|
|
list_filter = ['typ', 'rocnik']
|
|
view_on_site = Soustredeni.verejne_url
|
|
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)
|
|
|
|
### Novinky
|
|
|
|
class NovinkyAdminForm(forms.ModelForm):
|
|
text = forms.CharField(widget=CKEditorWidget(), required=False,
|
|
**field_labels(Novinky, 'text'))
|
|
class Meta:
|
|
model = Novinky
|
|
exclude = []
|
|
|
|
def zverejnit_novinky(modeladmin, request, queryset):
|
|
''' zverejni vybrane novinky '''
|
|
for novinka in queryset:
|
|
novinka.zverejneno = True
|
|
novinka.save()
|
|
zverejnit_novinky.short_description = 'Zveřejnit vybané novinky'
|
|
|
|
def zneverejnit_novinky(modeladmin, request, queryset):
|
|
''' zneverejni vybrane novinky'''
|
|
for novinka in queryset:
|
|
novinka.zverejneno = False
|
|
novinka.save()
|
|
zneverejnit_novinky.short_description = 'Zneveřejnit vybrané novinky'
|
|
|
|
|
|
class NovinkyAdmin(admin.ModelAdmin):
|
|
form = NovinkyAdminForm
|
|
list_display = ['datum', 'autor', 'text', 'zverejneno', 'obrazek']
|
|
actions = [zverejnit_novinky, zneverejnit_novinky]
|
|
|
|
# předvyplnění přihlášeného uživatele jako autora novinky
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
if db_field.name == 'autor':
|
|
kwargs['initial'] = request.user.id
|
|
return super(NovinkyAdmin, self).formfield_for_foreignkey(
|
|
db_field, request, **kwargs
|
|
)
|
|
|
|
|
|
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,]
|
|
|
|
|