diff --git a/mamweb/urls.py b/mamweb/urls.py index 26646528..b60c496a 100644 --- a/mamweb/urls.py +++ b/mamweb/urls.py @@ -1,37 +1,38 @@ -from django.conf.urls import * # NOQA +from django.urls import path, include from django.conf.urls.i18n import i18n_patterns from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin from django.conf import settings from django.views.generic.base import TemplateView from django import views +from django.urls import path # As per docs. urlpatterns = [ # Admin a nastroje - url('admin/', admin.site.urls), # NOQA - url('ckeditor/', include('ckeditor_uploader.urls')), - url('autocomplete/', include('autocomplete_light.urls')), + path('admin/', admin.site.urls), # NOQA + path('ckeditor/', include('ckeditor_uploader.urls')), + path('autocomplete/', include('autocomplete_light.urls')), # Seminarova aplikace (ma vlastni podadresare) - url('', include('seminar.urls')), + path('', include('seminar.urls')), # Korekturovaci aplikace (ma vlastni podadresare) - url('', include('korektury.urls')), + path('', include('korektury.urls')), # Prednaskova aplikace (ma vlastni podadresare) - url('', include('prednasky.urls')), + path('', include('prednasky.urls')), # Comments (interni i verejne) - url('comments_dj/', include('django_comments.urls')), - url('comments_fl/', include('fluent_comments.urls')), + path('comments_dj/', include('django_comments.urls')), + path('comments_fl/', include('fluent_comments.urls')), ] # This is only needed when using runserver. if settings.DEBUG: urlpatterns += [ - url('media/', views.static.serve, # NOQA + path('media/', views.static.serve, # NOQA {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), ] urlpatterns += staticfiles_urlpatterns() diff --git a/seminar/admin.py b/seminar/admin.py index 1ee98f67..d02b4db7 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -1,701 +1,36 @@ -# -*- coding: utf-8 -*- - from django.contrib import admin -from django import forms -from django.forms import widgets -from reversion.admin import VersionAdmin -from solo.admin import SingletonModelAdmin -from ckeditor_uploader.widgets import CKEditorUploadingWidget -from django.db.models import Count -from django.db import models -from django.utils.safestring import mark_safe -from django.urls import reverse - -from django.contrib.auth.models import User - -from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Novinky, Organizator, Pohadka, Konfera, Uloha -from autocomplete_light import shortcuts as autocomplete_light - - -class UserModelChoiceField(forms.ModelChoiceField): - """Vlastní ModelChoiceField pro uživatele. Zobrazí kromě loginu i jméno. - """ - def label_from_instance(self, obj): - return "{} ({})".format(obj.get_full_name(), obj.username) - -def get_form_predvypln_autora(self, request, obj=None, *args, **kwargs): - """get_form fce pro Adminy. Předvyplňí přihlášeného uživatele jako autora. - """ - form = super(self.__class__, self).get_form(request, *args, **kwargs) - form.base_fields['autor'].initial = request.user.id - return form - - -def make_set_action(atribut, hodnota, nazev): - """ - 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 = ['osoba_jmeno', 'osoba_prijmeni', 'skola', 'osoba_mesto', 'rok_maturity', ] - readonly_fields = ['osoba_jmeno', 'osoba_prijmeni', 'skola', 'osoba_mesto', 'rok_maturity', ] - extra = 0 - view_on_site = False - - def osoba_jmeno(self, obj): - return obj.osoba.jmeno - - def osoba_prijmeni(self, obj): - return obj.osoba.prijmeni - - def osoba_mesto(self, obj): - return obj.osoba.mesto - - def has_add_permission(self, req): return False - - -class CisloInline(admin.TabularInline): - model = Cislo - fields = ['cislo', - 'datum_vydani', 'datum_deadline', 'datum_deadline_soustredeni', - 'verejne_db', 'poznamka'] - readonly_fields = ['cislo'] - extra = 0 - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } - view_on_site = Cislo.verejne_url - - def has_add_permission(self, req): return False - - -class PrilohaReseniInline(admin.StackedInline): - model = PrilohaReseni - fields = ['vytvoreno', 'soubor', 'poznamka'] - readonly_fields = ['vytvoreno'] - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } - view_on_site = False - - extra = 0 - - -class ProblemInline(admin.TabularInline): - model = Problem - fields = ['kod', 'nazev', 'autor', 'garant', 'opravovatele', 'stav'] - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } - view_on_site = Problem.verejne_url - - extra = 0 - - -class ReseniKProblemuInline(admin.TabularInline): - form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['resitele'], fields=['resitele']) - model = Reseni - fields = ['resitele', 'forma', 'body', 'cislo_body', 'timestamp', 'poznamka'] - readonly_fields = ['timestamp'] - extra = 0 - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } - view_on_site = False - - def get_queryset(self, request): - qs = super(ReseniKProblemuInline, self).get_queryset(request) - return qs.select_related('problem', 'cislo_body', 'resitele') - - # 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 = ['cas_doruceni', 'problem'] - extra = 0 - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } - view_on_site = False - - 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') - - -class Soustredeni_OrganizatoriInline(admin.TabularInline): - form = autocomplete_light.modelform_factory(Soustredeni_Organizatori, autocomplete_fields=['organizator'], fields=['organizator'],) - model = Soustredeni_Organizatori - fields = ['organizator', 'poznamka', ] - extra = 0 - formfield_overrides = { - models.TextField: {'widget': forms.TextInput}, - } - - def get_queryset(self, request): - qs = super(Soustredeni_OrganizatoriInline, self).get_queryset(request) - return qs.select_related('organizator', 'soustredeni') - -### Resitel - -class ResitelAdmin(VersionAdmin): - form = autocomplete_light.modelform_factory(Resitel, autocomplete_fields=['skola'], fields=['skola']) - fk_name = 'osoba' - fieldsets = [ - (None, {'fields': ['jmeno', 'prijmeni', 'user']}), - ('Škola', {'fields': ['skola', 'rok_maturity']}), - ('Seminář', {'fields': ['datum_souhlasu_udaje', 'datum_souhlasu_zasilani', 'datum_prihlaseni', 'zasilat']}), - ('Osobní údaje', {'fields': ['pohlavi_muz', 'datum_narozeni', 'email', 'telefon']}), - ('Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}), - ] - list_display = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__user', 'osoba__pohlavi_muz', 'skola', 'rok_maturity', 'pocet_reseni'] - list_filter = ['osoba__pohlavi_muz', 'rok_maturity', 'zasilat'] - search_fields = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__ulice', 'osoba__mesto', 'osoba__email'] -# inlines = [ReseniKResiteliInline] # FIXME: - view_on_site = False - - def osoba__jmeno(self, obj): - return obj.osoba.jmeno - - def osoba__prijmeni(self, obj): - return obj.osoba.prijmeni - - def osoba__user(self, obj): - return obj.osoba.user - - def osoba__pohlavi_muz(self, obj): - return obj.osoba.pohlavi_muz - - def osoba__ulice(self, obj): - return obj.osoba.ulice - - def osoba__mesto(self, obj): - return obj.osoba.mesto - - def osoba__email(self, obj): - return obj.osoba.email - - 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(VersionAdmin): - fieldsets = [ - (None, {'fields': ['nazev', 'kratky_nazev', 'je_zs', 'je_ss']}), - ('Interní ID', {'fields': ['aesop_id', 'izo'], 'classes': ['collapse']}), - ('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] - view_on_site = False - -admin.site.register(Skola, SkolaAdmin) - - -### Cislo - -class CisloAdmin(VersionAdmin): - fieldsets = [ - (None, { - 'fields': [ - 'cislo', - 'rocnik', - 'verejne_db', - 'verejna_vysledkovka', - 'faze', - 'poznamka', - 'pdf' - ] - }), - ('Data', {'fields': ['datum_vydani', 'datum_deadline', - 'datum_deadline_soustredeni']}), - ] - 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, 'Zveřejnit číslo'), - make_set_action('verejne_db', False, 'Skrýt (zneveřejnit) číslo'), - make_set_action('verejna_vysledkovka', True, 'Zveřejnit výsledkovku'), - make_set_action('verejna_vysledkovka', False, 'Skrýt (zneveřejnit) výsledkovku'), - ] - #inlines = [ProblemInline] - - 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(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, 'Nastavit pro AESOP export'), - make_set_action('exportovat', False, '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']}), -# ('Poznámky', {'fields': ['poznamka']}), -# ] -# list_display = ['reseni', 'soubor', 'timestamp'] -# list_filter = ['reseni', 'timestamp'] -# search_fields = [] -# -# admin.site.register(PrilohaReseni, PrilohaReseniAdmin) - - -### Reseni - -class ReseniAdmin(VersionAdmin): - #form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['problem', 'resitele'], fields=['problem', 'resitele']) - fieldsets = [ - (None, {'fields': ['problem__set', 'resitele__set', 'forma', 'cas_doruceni']}), - ('Poznámky', {'fields': ['poznamka']}), - ] - readonly_fields = ['cas_doruceni'] - list_display = [ResitelInline, 'forma', 'cas_doruceni'] - list_filter = ['cas_doruceni', 'forma'] - search_fields = [] - inlines = [PrilohaReseniInline] # FIXME: odmazáno ProblemInline,ResitelInline - view_on_site = False - - def get_queryset(self, request): - qs = super(ReseniAdmin, self).get_queryset(request) - return qs.select_related('resitele', 'problem', 'cislo_body') - -admin.site.register(Reseni, ReseniAdmin) - - -### Pohádka - -class PohadkaAdminForm(forms.ModelForm): - class Meta: - model = Pohadka - exclude = [] - autor = UserModelChoiceField(User.objects.filter(is_staff=True)) - uloha = forms.ModelChoiceField( - Uloha.objects.all() - ) - - def __init__(self, *args, **kwargs): - super(PohadkaAdminForm, self).__init__(*args, **kwargs) - instance = getattr(self, 'instance', None) - - # viz ProblemAdminForm.__init__ - if instance and instance.pk: - if instance.uloha and instance.uloha.cislo_zadani: - if instance.uloha.cislo_zadani.faze != 'admin': - self.fields['text'].widget.attrs['readonly'] = True - - -class PohadkaAdmin(VersionAdmin): - form = PohadkaAdminForm - view_on_site = False - - def get_kod_ulohy(self, obj): - return obj.uloha.kod_v_rocniku() - get_kod_ulohy.short_description = 'Kód úlohy' - - def get_rocnik(self, obj): - return obj.uloha.cislo_zadani.rocnik.rocnik - get_rocnik.short_description = 'Ročník' - - list_display = [ - '__str__', - 'get_rocnik', - 'get_kod_ulohy', -# 'uloha', - 'autor' - ] - - get_form = get_form_predvypln_autora - -class PohadkaKProblemuInline(admin.TabularInline): - form = PohadkaAdminForm - model = Pohadka - exclude = [] - extra = 0 - -admin.site.register(Pohadka, PohadkaAdmin) - - -### Problem - -from autocomplete_light.contrib.taggit_field import TaggitField, TaggitWidget - - -class ProblemAdminForm(forms.ModelForm): - #text_zadani = forms.CharField(widget=CKEditorUploadingWidget(), required=False, **field_labels(Problem, 'text_zadani')) - #text_reseni = forms.CharField(widget=CKEditorUploadingWidget(), required=False, **field_labels(Problem, 'text_reseni')) - #text_org = forms.CharField(widget=CKEditorUploadingWidget(), required=False, **field_labels(Problem, 'text_org')) - zamereni = TaggitField(widget=TaggitWidget('TagAutocomplete'), required=False) - autor = UserModelChoiceField(User.objects.filter(is_staff=True)) - opravovatel = UserModelChoiceField(User.objects.filter(is_staff=True), required=False) - class Meta: - model = Problem - exclude = ['nadproblem'] - - def __init__(self, *args, **kwargs): - super(ProblemAdminForm, self).__init__(*args, **kwargs) - instance = getattr(self, 'instance', None) - - # Nedovol měnit název a zadání resp. řešení, pokud je cislo_zadani - # resp. cislo_reseni mimo fázi admin. - # - # Nastavení readonly fields sice vypadá lépe (nevygeneruje input tag), - # ale při ukládání změny vypíše admin nespecifikovanou chybu, která je - # způsobena zřejmě tím, že se neodešle žádná hodnota pro povinné pole - # nazev. Navíc by se smazalo nepovinné pole zadání. - # - # Toto řešení je z http://stackoverflow.com/a/325038/4786205. - # - # TODO Django 1.9: použít field s atributem disabled? - if instance and instance.pk: - if instance.cislo_zadani and instance.cislo_zadani.faze != 'admin': - # CKEditor neumí readonly ... - self.fields['text_zadani'] = forms.CharField( - widget=forms.Textarea, - required=False - ) - for f in ['nazev', 'text_zadani', 'body']: - self.fields[f].widget.attrs['readonly'] = True - if instance.cislo_reseni and instance.cislo_reseni.faze != 'admin': - self.fields['text_reseni'] = forms.CharField( - widget=forms.Textarea, - required=False - ) - self.fields['text_reseni'].widget.attrs['readonly'] = True - - -class ProblemAdmin(VersionAdmin): - form = ProblemAdminForm - fieldsets = [ - (None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp', 'import_dakos_id']}), - ('Vydání', {'fields': ['kod', 'cislo_reseni', 'opravovatel',]}), - (None, {'fields': ['text_zadani', 'text_reseni', 'text_org',]}), - ] - list_select_related = True - search_fields = ['nazev', 'text_zadani', 'text_reseni', 'text_org'] - view_on_site = Problem.verejne_url - ordering = ['-timestamp'] - - readonly_fields = ['timestamp', 'import_dakos_id'] - - def get_queryset(self, request): - qs = super(ProblemAdmin, self).get_queryset(request) - return qs.select_related('autor', 'opravovatel', 'cislo_reseni') - - def pocet_reseni(self, obj): - return obj.pocet_reseni - -class ProblemNavrhAdmin(ProblemAdmin): - list_display = ['nazev', 'typ', '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]) - - get_form = get_form_predvypln_autora - - -#FIXME -#create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name='Problém (návrh)', verbose_name_plural='Problémy (návrhy)') - - -class ProblemZadanyAdmin(ProblemAdmin): - list_display = [ - 'nazev', - 'typ', - 'cislo_zadani_link', - 'cislo_reseni_link', - 'autor', - 'opravovatel', - 'kod', - 'verejne' - ] - list_filter = [ - 'typ', 'zamereni', 'cislo_zadani__cislo', 'cislo_zadani__rocnik' - ] - - def cislo_zadani_link(self, obj): - if not obj.cislo_zadani: - return "" - return mark_safe('{}'.format( - reverse("admin:seminar_cislo_change", args=(obj.cislo_zadani.pk,)), - obj.cislo_zadani - )) - cislo_zadani_link.short_description = 'Číslo zadání' - - # TODO pokud se budou odkazy v adminu více používat, možná by se hodilo je - # nějak zjednodušit, např. tímto? - # https://github.com/gitaarik/django-admin-relation-links - def cislo_reseni_link(self, obj): - if not obj.cislo_reseni: - return "" - return mark_safe('{}'.format( - reverse("admin:seminar_cislo_change", args=(obj.cislo_reseni.pk,)), - obj.cislo_reseni - )) - cislo_reseni_link.short_description = 'Číslo řešení' - - def get_inline_instances(self, request, obj=None): - if obj and obj.typ == Problem.TYP_ULOHA: - inlines = [ReseniKProblemuInline, PohadkaKProblemuInline] - else: - inlines = [ReseniKProblemuInline] - - return [inline(self.model, self.admin_site) for inline in inlines] - - def get_queryset(self, request): - qs = super(ProblemZadanyAdmin, self).get_queryset(request) - return qs.filter(stav=Problem.STAV_ZADANY) - - get_form = get_form_predvypln_autora - -#FIXME -#create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name='Problém (zadaný)', verbose_name_plural='Problémy (zadané)') - -#admin.site.register(Problem, ProblemAdmin) - -### Prispevek (k tematkum) - -#class PrispevekAdminForm(forms.ModelForm): -# text_org = forms.CharField(widget=CKEditorUploadingWidget(), required=False, -# **field_labels(Prispevek, 'text_org')) -# text_resitel = forms.CharField(widget=CKEditorUploadingWidget(), required=False, -# **field_labels(Prispevek, 'text_resitel')) -# -# class Meta: -# model = Prispevek -# exclude = [] -# -#class PrispevekAdmin(VersionAdmin): -# form = PrispevekAdminForm -# list_display = ['nazev', 'problem', 'reseni', 'zverejnit'] -# -#admin.site.register(Prispevek, PrispevekAdmin) - -### Soustredeni - -class SoustredeniAdminForm(forms.ModelForm): - text = forms.CharField(widget=CKEditorUploadingWidget(), required=False, **field_labels(Soustredeni, 'text')) - class Meta: - model = Soustredeni - exclude = [] - -class SoustredeniAdmin(VersionAdmin): - form = SoustredeniAdminForm - fieldsets = [ - (None, {'fields': ['rocnik', 'misto', 'typ', 'verejne_db', 'exportovat', 'text']}), - ('Data', {'fields': ['datum_zacatku', 'datum_konce']}), - ] - list_display = ['rocnik', 'misto', 'datum_zacatku', 'typ', 'exportovat', 'verejne'] - inlines = [Soustredeni_UcastniciInline, Soustredeni_OrganizatoriInline] - list_filter = ['typ', 'rocnik'] - view_on_site = Soustredeni.verejne_url - actions = [ - make_set_action('verejne_db', True, 'Zveřejnit soustředění'), - make_set_action('verejne_db', False, 'Skrýt (zneveřejnit) soustředění'), - make_set_action('exportovat', True, 'Nastavit pro AESOP export'), - make_set_action('exportovat', False, 'Skrýt pro AESOP export'), - ] - -admin.site.register(Soustredeni, SoustredeniAdmin) - -### Konfery -class KonferaAdminForm(forms.ModelForm): - class Meta: - model=Konfera - exclude = [] - -class KonferaAdmin(VersionAdmin): - form = KonferaAdminForm - list_filter = ['soustredeni'] - list_display = ['nazev','soustredeni','organizator','typ_prezentace'] -# inlines = [Konfera_UcastniciInline] - -admin.site.register(Konfera,KonferaAdmin) - -### Novinky - -class NovinkyAdminForm(forms.ModelForm): - text = forms.CharField(widget=CKEditorUploadingWidget(), required=False, - **field_labels(Novinky, 'text')) - autor = UserModelChoiceField(User.objects.filter(is_staff=True)) - - 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(VersionAdmin): - form = NovinkyAdminForm - list_display = ['datum', 'autor', 'text', 'zverejneno', 'obrazek'] - actions = [zverejnit_novinky, zneverejnit_novinky] - - get_form = get_form_predvypln_autora - - -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(VersionAdmin): - list_filter = ['organizuje_do'] - list_display = [jmeno_organizatora, je_organizator_aktivni,] - actions = [zaktivovat_organizatory, deaktivovat_organizatory,] +import seminar.models as m + +admin.site.register(m.Osoba) +admin.site.register(m.Skola) +admin.site.register(m.Prijemce) +admin.site.register(m.Resitel) +admin.site.register(m.Rocnik) +admin.site.register(m.Cislo) +admin.site.register(m.Organizator) +admin.site.register(m.Soustredeni) +admin.site.register(m.Problem) +admin.site.register(m.Tema) +admin.site.register(m.Clanek) +admin.site.register(m.Text) +admin.site.register(m.Uloha) +admin.site.register(m.Reseni) +admin.site.register(m.Hodnoceni) +admin.site.register(m.PrilohaReseni) +admin.site.register(m.Pohadka) +admin.site.register(m.Konfera) +admin.site.register(m.Obrazek) +admin.site.register(m.TreeNode) +admin.site.register(m.RocnikNode) +admin.site.register(m.CisloNode) +admin.site.register(m.MezicisloNode) +admin.site.register(m.TemaVCisleNode) +admin.site.register(m.KonferaNode) +admin.site.register(m.ClanekNode) +admin.site.register(m.UlohaZadaniNode) +admin.site.register(m.PohadkaNode) +admin.site.register(m.UlohaVzorakNode) +admin.site.register(m.TextNode) +admin.site.register(m.Nastaveni) +admin.site.register(m.Novinky) diff --git a/seminar/testutils.py b/seminar/testutils.py index 39156914..01b1cd3d 100644 --- a/seminar/testutils.py +++ b/seminar/testutils.py @@ -7,7 +7,7 @@ import django.contrib.auth from django.db import transaction import unidecode -from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, KonferaNode, RocnikNode +from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, KonferaNode, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode from django.contrib.flatpages.models import FlatPage from django.contrib.sites.models import Site @@ -60,7 +60,7 @@ def gen_osoby(rnd, size): datum_registrace = datetime.date(rnd.randint(2019, 2029), rnd.randint(1, 12), rnd.randint(1, 28)))) #TODO pridat foto male a velke. Jak? - # Pavel tvrdí, že to necháme a přidáme až do adminu + # Pavel tvrdí, že to necháme a přidáme až do adminu return osoby @@ -148,7 +148,7 @@ def gen_ulohy_do_cisla(rnd, cislo, organizatori, resitele, slovnik_cisel, size): "sporné", "nepopsatelně jednoduché", "pokud jste na to nepřišli," "tak jste fakt hloupí"] - if cislo >= 3: + if cislo >= 3: #TODO nagenerovat i nody!!! for pi in range(1, ((size + 1) // 2) + 1): poc_op = rnd.randint(1, 4) # počet opravovatelů poc_oboru = rnd.randint(1, 2) @@ -208,23 +208,23 @@ def gen_ulohy_do_cisla(rnd, cislo, organizatori, resitele, slovnik_cisel, size): return def gen_soustredeni(rnd, resitele, organizatori): - soustredeni = [] - for _ in range(1, 10): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) - datum_zacatku=datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28)) - working_sous = Soustredeni.objects.create( - rocnik=Rocnik.objects.order_by('?').first(), - verejne_db=rnd.choice([True, False]), - misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']), - typ=rnd.choice(['jarni', 'podzimni', 'vikend']), - datum_zacatku=datum_zacatku, - datum_konce=datum_zacatku + datetime.timedelta(days=7)) - for res in rnd.sample(resitele, min(len(resitele), 20)): - Soustredeni_Ucastnici.objects.create(resitel=res, soutredeni=working_sous) - for org in rnd.sample(organizatori, min(len(organizatori), 20)): - Soustredeni_Organizatori.objects.create(organizator=org, soutredeni=working_sous) - working_sous.save() - soustredeni.append(working_sous) - return soustredeni + soustredeni = [] + for _ in range(1, 10): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) + datum_zacatku=datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28)) + working_sous = Soustredeni.objects.create( + rocnik=Rocnik.objects.order_by('?').first(), + verejne_db=rnd.choice([True, False]), + misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']), + typ=rnd.choice(['jarni', 'podzimni', 'vikend']), + datum_zacatku=datum_zacatku, + datum_konce=datum_zacatku + datetime.timedelta(days=7)) + for res in rnd.sample(resitele, min(len(resitele), 20)): + Soustredeni_Ucastnici.objects.create(resitel=res, soutredeni=working_sous) + for org in rnd.sample(organizatori, min(len(organizatori), 20)): + Soustredeni_Organizatori.objects.create(organizator=org, soutredeni=working_sous) + working_sous.save() + soustredeni.append(working_sous) + return soustredeni def gen_rocniky(last_rocnik, size): rocniky = [] @@ -237,24 +237,24 @@ def gen_rocniky(last_rocnik, size): return rocniky def gen_konfery(rnd, reseni, organizatori, ucastnici, soustredeni): - konfery = [] - for _ in range(1, size): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) - konfera = Konfera.objects.create( - nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']), - anotace=lorem.paragraph(), - abstrakt=lorem.paragraph(), - organizator=rnd.choice(organizatori), - soustredeni=rnd.choice(soustredeni), - reseni=rnd.choice(reseni), - typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) - for res in rnd.sample(ucastnici, min(len(ucastnici), rnd.randint(3, 6))): - Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera) - konfery.append(konfera) - konfera.save() - - konferanode = KonferaNode.objects.create(konfera=konfera) - konferanode.save() - return konfery + konfery = [] + for _ in range(1, size): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?) + konfera = Konfera.objects.create( + nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']), + anotace=lorem.paragraph(), + abstrakt=lorem.paragraph(), + organizator=rnd.choice(organizatori), + soustredeni=rnd.choice(soustredeni), + reseni=rnd.choice(reseni), + typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) + for res in rnd.sample(ucastnici, min(len(ucastnici), rnd.randint(3, 6))): + Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera) + konfery.append(konfera) + konfera.save() + + konferanode = KonferaNode.objects.create(konfera=konfera) + konferanode.save() + return konfery def gen_cisla(rocniky): slovnik_rocnik_cisla = {} @@ -368,52 +368,53 @@ def gen_ulohy_k_tematum(rocniky, slovnik_rocnik_cisla, slovnik_rocnik_temata): # for rocnik in rocniky: slovnik_cisel = slovnik_rocnik_cisla[rocnik] slovnik_temat = slovnik_rocnik_temata[rocnik] - for cislo in slovnik_cisel: - syn = cislo.CisloNode.first_child - while syn != None: - tema = syn.tema - for i in range(1, rnd.randint(1, 4)) - poc_op = rnd.randint(1, 4) - poc_oboru = rnd.randint(1, 2) - p = Uloha.objects.create( - nazev=": ".join([tema.nazev, - "úloha {}.".format(i)]), - nadproblem=tema, - stav=Problem.STAV_ZADANY, - zamereni=tema.zamereni, - autor=tema.autor, - garant=tema.garant, - opravovatele=rnd.sample(organizatori, poc_op), - kod=str(i), - cislo_zadani=cislo, - cislo_reseni=slovnik_cisel[cislo.cislo+2], - cislo_deadline=slovnik_cisel[cislo.cislo+2], - max_body = rnd.randint(1, 8) - ) - p.zadani = " ".join([rnd.choice(sloveso), rnd.choice(koho), - rnd.choice(ceho), rnd.choice(jmeno), rnd.choice(kde)]) - - #Tomův pokus o opravu bugu: - text_vzoraku = Text.objects.create( - na_web = rnd.choice(reseni), - do_cisla = rnd.choice(reseni) - ) - vzorak = TextNode.objects.create(text = text_vzoraku) - uloha_vzorak = UlohaVzorakNode.objects.create(uloha=p, first_child = vzorak) - p.UlohaVzorakNode = uloha_vzorak - - #p.vzorak = " - ".join([p.zadani, rnd.choice(reseni)]) - p.save() - - - syn = syn.succ - - - # vytvor text - # vytvor TemaVCisleNode - if (rnd.randint(1, 3) % 3 == 0): - # vytvor mezicislo Node - pass + for cislo in slovnik_cisel: + syn = cislo.CisloNode.first_child + while syn != None: + if type(syn) != TemaVCisleNode + continue + else: + tema = syn.tema + for i in range(1, rnd.randint(1, 4)) + poc_op = rnd.randint(1, 4) + poc_oboru = rnd.randint(1, 2) + p = Uloha.objects.create( + nazev=": ".join([tema.nazev, + "úloha {}.".format(i)]), + nadproblem=tema, + stav=Problem.STAV_ZADANY, + zamereni=tema.zamereni, + autor=tema.autor, + garant=tema.garant, + opravovatele=rnd.sample(organizatori, poc_op), + kod=str(i), + cislo_zadani=cislo, + cislo_reseni=slovnik_cisel[cislo.cislo+2], + cislo_deadline=slovnik_cisel[cislo.cislo+2], + max_body = rnd.randint(1, 8) + ) + p.zadani = " ".join([rnd.choice(sloveso), rnd.choice(koho), + rnd.choice(ceho), rnd.choice(jmeno), rnd.choice(kde)]) + + text_vzoraku = Text.objects.create( + na_web = rnd.choice(reseni), + do_cisla = rnd.choice(reseni) + ) + vzorak = TextNode.objects.create(text = text_vzoraku) + uloha_vzorak = UlohaVzorakNode.objects.create(uloha=p, first_child = vzorak) + p.UlohaVzorakNode = uloha_vzorak + p.save() + + + + syn = syn.succ + + + # vytvor text + # vytvor TemaVCisleNode + if (rnd.randint(1, 3) % 3 == 0): + # vytvor mezicislo Node + pass @transaction.atomic def create_test_data(size = 6, rnd = None): @@ -481,11 +482,6 @@ def create_test_data(size = 6, rnd = None): # generování úloh k tématům ve všech číslech gen_ulohy_k_tematum(rocniky, slovnik_rocnik_cisla, slovnik_rocnik_temata) - - # nagenerovat k tématu úlohy a Nody pro vsechna cisla - - - # FIXME: misto typu ruzne typy objektu a vnoreni do sebe # TODO: vytvorit temata s ruznymi vlakny