diff --git a/seminar/admin.py b/seminar/admin.py index 59eab849..28f25314 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -18,13 +18,13 @@ from autocomplete_light import shortcuts as autocomplete_light class UserModelChoiceField(forms.ModelChoiceField): - u"""Vlastní ModelChoiceField pro uživatele. Zobrazí kromě loginu i jméno. + """Vlastní ModelChoiceField pro uživatele. Zobrazí kromě loginu i jméno. """ def label_from_instance(self, obj): - return u"{} ({})".format(obj.get_full_name(), obj.username) + return "{} ({})".format(obj.get_full_name(), obj.username) def get_form_predvypln_autora(self, request, obj=None, *args, **kwargs): - u"""get_form fce pro Adminy. Předvyplňí přihlášeného uživatele jako autora. + """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 @@ -32,7 +32,7 @@ def get_form_predvypln_autora(self, request, obj=None, *args, **kwargs): 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í.""" @@ -214,10 +214,10 @@ class ResitelAdmin(VersionAdmin): fk_name = 'osoba' 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']}), + ('Š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'] @@ -262,8 +262,8 @@ admin.site.register(Resitel, ResitelAdmin) class SkolaAdmin(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']}), + ('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'] @@ -328,8 +328,8 @@ class RocnikAdmin(VersionAdmin): 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'), + make_set_action('exportovat', True, 'Nastavit pro AESOP export'), + make_set_action('exportovat', False, 'Skrýt pro AESOP export'), ] admin.site.register(Rocnik, RocnikAdmin) @@ -341,7 +341,7 @@ admin.site.register(Rocnik, RocnikAdmin) # readonly_fields = ['timestamp', 'reseni'] # fieldsets = [ # (None, {'fields': ['reseni', 'soubor', 'timestamp']}), -# (u'Poznámky', {'fields': ['poznamka']}), +# ('Poznámky', {'fields': ['poznamka']}), # ] # list_display = ['reseni', 'soubor', 'timestamp'] # list_filter = ['reseni', 'timestamp'] @@ -356,7 +356,7 @@ 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']}), - (u'Poznámky', {'fields': ['poznamka']}), + ('Poznámky', {'fields': ['poznamka']}), ] readonly_fields = ['cas_doruceni'] list_display = [ResitelInline, 'forma', 'cas_doruceni'] @@ -400,11 +400,11 @@ class PohadkaAdmin(VersionAdmin): def get_kod_ulohy(self, obj): return obj.uloha.kod_v_rocniku() - get_kod_ulohy.short_description = u'Kód úlohy' + get_kod_ulohy.short_description = 'Kód úlohy' def get_rocnik(self, obj): return obj.uloha.cislo_zadani.rocnik.rocnik - get_rocnik.short_description = u'Ročník' + get_rocnik.short_description = 'Ročník' list_display = [ '__str__', @@ -477,7 +477,7 @@ class ProblemAdmin(VersionAdmin): form = ProblemAdminForm fieldsets = [ (None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp', 'import_dakos_id']}), - (u'Vydání', {'fields': ['kod', 'cislo_reseni', 'opravovatel',]}), + ('Vydání', {'fields': ['kod', 'cislo_reseni', 'opravovatel',]}), (None, {'fields': ['text_zadani', 'text_reseni', 'text_org',]}), ] list_select_related = True @@ -506,7 +506,7 @@ class ProblemNavrhAdmin(ProblemAdmin): #FIXME -#create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name=u'Problém (návrh)', verbose_name_plural=u'Problémy (návrhy)') +#create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name='Problém (návrh)', verbose_name_plural='Problémy (návrhy)') class ProblemZadanyAdmin(ProblemAdmin): @@ -531,7 +531,7 @@ class ProblemZadanyAdmin(ProblemAdmin): reverse("admin:seminar_cislo_change", args=(obj.cislo_zadani.pk,)), obj.cislo_zadani )) - cislo_zadani_link.short_description = u'Číslo zadání' + 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? @@ -543,7 +543,7 @@ class ProblemZadanyAdmin(ProblemAdmin): reverse("admin:seminar_cislo_change", args=(obj.cislo_reseni.pk,)), obj.cislo_reseni )) - cislo_reseni_link.short_description = u'Číslo řešení' + cislo_reseni_link.short_description = 'Číslo řešení' def get_inline_instances(self, request, obj=None): if obj and obj.typ == Problem.TYP_ULOHA: @@ -560,7 +560,7 @@ class ProblemZadanyAdmin(ProblemAdmin): get_form = get_form_predvypln_autora #FIXME -#create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'Problém (zadaný)', verbose_name_plural=u'Problémy (zadané)') +#create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name='Problém (zadaný)', verbose_name_plural='Problémy (zadané)') #admin.site.register(Problem, ProblemAdmin) @@ -601,10 +601,10 @@ class SoustredeniAdmin(VersionAdmin): 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'), + 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) diff --git a/seminar/migrations/0058_problem_to_uloha_tema_clanek.py b/seminar/migrations/0058_problem_to_uloha_tema_clanek.py index 7b43cdc6..333f5453 100644 --- a/seminar/migrations/0058_problem_to_uloha_tema_clanek.py +++ b/seminar/migrations/0058_problem_to_uloha_tema_clanek.py @@ -91,8 +91,7 @@ def clanek_to_Clanek(apps,schema_editor): elif cl.cislo_reseni_old == cl.cislo_zadani_old: cislo = cl.cislo_zadani_old else: - cislo = cl.cislo_zadani_old - #raise ValueError("Různá čísla zadání a řešení u článku!") + raise ValueError("Různá čísla zadání a řešení u článku! (Článek: {})".format(cl.nazev)) clnew = Clanek.objects.create( problem_ptr = cl, @@ -132,7 +131,7 @@ def tema_to_Tema(apps, schema_editor): elif t.cislo_reseni_old.rocnik == t.cislo_zadani_old.rocnik: rocnik = t.cislo_zadani_old.rocnik else: - raise ValueError("Nelze mít téma přes více ročníků!") + raise ValueError("Nelze mít téma přes více ročníků! (Téma: {}".format(t.nazev)) tnew = Tema.objects.create( problem_ptr = t, diff --git a/seminar/models.py b/seminar/models.py index d94d1e3d..760c5c57 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -115,6 +115,11 @@ class Osoba(SeminarModelBase): ], options={'quality': 95}) + # má OneToOneField nejvýše s: + # Resitel + # Prijemce + # Organizator + def plne_jmeno(self): return '{} {}'.format(self.jmeno, self.prijmeni) @@ -314,7 +319,11 @@ class Rocnik(SeminarModelBase): rocnik = models.IntegerField('číslo ročníku', db_index=True, unique=True) exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False, - help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti), a to jen čísla s veřejnou výsledkovkou') + help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti),' + ' a to jen čísla s veřejnou výsledkovkou') + + # má OneToOneField s: + # RocnikNode def __str__(self): return '{} ({}/{})'.format(self.rocnik, self.prvni_rok, self.prvni_rok+1) @@ -409,6 +418,8 @@ class Cislo(SeminarModelBase): pdf = models.FileField('pdf', upload_to=cislo_pdf_filename, null=True, blank=True, help_text='Pdf čísla, které si mohou řešitelé stáhnout') + # má OneToOneField s: + # CisloNode def kod(self): return '%s.%s' % (self.rocnik.rocnik, self.cislo) @@ -560,7 +571,10 @@ class Problem(SeminarModelBase): class Meta: # Není abstraktní, protože se na něj jinak nedají dělat ForeignKeys. - # TODO: Udělat to polymorfní (pomocí django-polymorphic), abychom dostali po těch vazbách přímo tu úlohu/témátko vč. fieldů, které nejsou součástí modelu Problem? + # TODO: Udělat to polymorfní (pomocí django-polymorphic), abychom dostali + # po těch vazbách přímo tu úlohu/témátko vč. fieldů, které nejsou součástí + # modelu Problem? + #abstract = True db_table = 'seminar_problemy' verbose_name = 'Problém' @@ -678,6 +692,10 @@ class Clanek(Problem): verbose_name_plural = 'Články' cislo = models.ForeignKey(Cislo, verbose_name='číslo', blank=True, null=True) + + # má OneToOneField s: + # ClanekNode + def kod_v_rocniku(self): if self.stav == 'zadany': # Nemělo by být potřeba @@ -698,8 +716,12 @@ class Text(SeminarModelBase): do_cisla = models.TextField('text do čísla', blank=True, help_text='Text ke zveřejnění v čísle') + # má OneToOneField s: + # Reseni (je u něj jako reseni_cele) + # obrázky mají návaznost opačným směrem (vazba z druhé strany) + class Uloha(Problem): class Meta: @@ -720,6 +742,10 @@ class Uloha(Problem): max_body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='maximum bodů', blank=True, null=True) + # má OneToOneField s: + # UlohaZadaniNode + # UlohaVzorakNode + def kod_v_rocniku(self): if self.stav == 'zadany': name="{}.u{}".format(self.cislo_zadani.cislo,self.kod) @@ -729,7 +755,6 @@ class Uloha(Problem): return '' - @reversion.register(ignore_duplicates=True) class Reseni(SeminarModelBase): @@ -776,6 +801,9 @@ class Reseni(SeminarModelBase): zverejneno = models.BooleanField('řešení zveřejněno', default=False, help_text='Udává, zda je řešení zveřejněno') + # má OneToOneField s: + # Konfera + def __str__(self): return "{}: {}".format(self.resitel.osoba.plne_jmeno(), self.problem.nazev) # NOTE: Potenciální DB HOG (bez select_related) @@ -897,6 +925,9 @@ class Pohadka(SeminarModelBase): editable=False ) + # má OneToOneField s: + # PohadkaNode + def __str__(self): uryvek = self.text if len(self.text) < 50 else self.text[:(50-3)]+"..." return uryvek @@ -1001,6 +1032,9 @@ class Konfera(models.Model): help_text = 'Další materiály ke konfeře zabalené do jednoho souboru', upload_to = generate_filename_konfera, blank=True) + # má OneToOneField s: + # KonferaNode + def __str__(self): return "{}: ({})".format(self.nazev, self.soustredeni) diff --git a/seminar/old_views.py b/seminar/old_views.py new file mode 100644 index 00000000..f904d137 --- /dev/null +++ b/seminar/old_views.py @@ -0,0 +1,71 @@ +# Tento soubor slouží k odkládání aktuálně nepotřebného kódu, který by +# se však v budoucnu mohl opět hodit. + +################################################################### + +## Prispevek byl zrusen, mozna ale bude podobny nahled na neco jineho. +#class PrispevekView(generic.DetailView): +# model = Prispevek +# template_name = 'seminar/archiv/prispevek.html' +# +# # Vlastni ziskavani objektu z databaze podle prispevku +# # pokud je prispevek neverejny zobrazi se jenom orgum +# def get_object(self, queryset=None): +# if queryset is None: +# queryset = self.get_queryset() +# problem_arg = self.kwargs.get('pk') +# prispevek_arg = self.kwargs.get('prispevek') +# queryset = queryset.filter(pk=prispevek_arg) +# +# try: +# obj = queryset.get() +# except queryset.model.DoesNotExist: +# raise Http404(_("No %(verbose_name)s found matching the query") % +# {'verbose_name': queryset.model._meta.verbose_name}) +# +# if self.request.user.is_staff or obj.zverejnit: +# return obj +# else: +# raise Http404() +# +# def get_context_data(self, **kwargs): +# context = super(PrispevekView, self).get_context_data(**kwargs) +# # snaho o ziskani titulu +# titul = '' +# try: +# resitel = context['prispevek'].reseni.resitel +# cislo = context['prispevek'].reseni.cislo_body +# body = VysledkyKCisluOdjakziva.objects.get(resitel=resitel, +# cislo=cislo).body +# titul = resitel.get_titul(body) +# except: +# pass +# context['titul'] = titul +# return context + +#################################################################### + +## Stvrzenky aktuálně nevydáváme, ale možná časem zase budeme. +#def soustredeniStvrzenkyExportView(request,soustredeni,first_num): +# first_num = int(first_num) +# soustredeni = get_object_or_404(Soustredeni,id = soustredeni) +# ucastnici = Resitel.objects.filter(soustredeni=soustredeni) +# for (idx,u) in enumerate(ucastnici): +# u.cislo_stvrzenky = first_num+idx; +# tex = render(request,'seminar/soustredeni/ucastnici.tex', {'ucastnici': ucastnici, 'datum':soustredeni.datum_zacatku }).content +# +# tempdir = tempfile.mkdtemp() +# with open(tempdir+"/ucastnici.tex","w") as texfile: +# # Pokud TeX chce ISO Latin, tak se da encode nastavit +# texfile.write(tex.decode("utf-8").encode("utf-8")) +# shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenka.sty'),tempdir) +# shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenky.tex'),tempdir) +# subprocess.call(["cslatex","stvrzenky.tex"],cwd = tempdir) +# subprocess.call(["dvipdf","stvrzenky.dvi"],cwd = tempdir) +# +# with open(tempdir+"/stvrzenky.pdf","rb") as pdffile: +# response = HttpResponse(pdffile.read(),content_type='application/pdf') +# shutil.rmtree(tempdir) +# return response + + diff --git a/seminar/urls.py b/seminar/urls.py index aa41c386..962db176 100644 --- a/seminar/urls.py +++ b/seminar/urls.py @@ -45,11 +45,6 @@ urlpatterns = [ staff_member_required(views.SoustredeniMailyUcastnikuView.as_view()), name='maily_ucastniku' ), - url( - r'^soustredeni/(?P\d+)/stvrzenky/(?P\d+)$', - staff_member_required(views.soustredeniStvrzenkyExportView), - name='soustredeni_stvrzenky' - ), url( r'^soustredeni/(?P\d+)/export_ucastniku$', staff_member_required(views.soustredeniUcastniciExportView), diff --git a/seminar/views.py b/seminar/views.py index 3f01376f..aba2b55e 100644 --- a/seminar/views.py +++ b/seminar/views.py @@ -377,47 +377,6 @@ class ProblemView(generic.DetailView): context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni') return context -## Prispevek byl zrusen, mozna ale bude podobny nahled na neco jineho. -#class PrispevekView(generic.DetailView): -# model = Prispevek -# template_name = 'seminar/archiv/prispevek.html' -# -# # Vlastni ziskavani objektu z databaze podle prispevku -# # pokud je prispevek neverejny zobrazi se jenom orgum -# def get_object(self, queryset=None): -# if queryset is None: -# queryset = self.get_queryset() -# problem_arg = self.kwargs.get('pk') -# prispevek_arg = self.kwargs.get('prispevek') -# queryset = queryset.filter(pk=prispevek_arg) -# -# try: -# obj = queryset.get() -# except queryset.model.DoesNotExist: -# raise Http404(_("No %(verbose_name)s found matching the query") % -# {'verbose_name': queryset.model._meta.verbose_name}) -# -# if self.request.user.is_staff or obj.zverejnit: -# return obj -# else: -# raise Http404() -# -# def get_context_data(self, **kwargs): -# context = super(PrispevekView, self).get_context_data(**kwargs) -# # snaho o ziskani titulu -# titul = '' -# try: -# resitel = context['prispevek'].reseni.resitel -# cislo = context['prispevek'].reseni.cislo_body -# body = VysledkyKCisluOdjakziva.objects.get(resitel=resitel, -# cislo=cislo).body -# titul = resitel.get_titul(body) -# except: -# pass -# context['titul'] = titul -# return context - - class RadekVysledkovky(object): pass @@ -465,7 +424,6 @@ class RadekVysledkovky(object): # #setridi problemy podle typu a poradi zadani # problem_index = {} # for i in range(len(problemy)): -# problem_index[problemy[i].id] = i # #umoznuje zjistit index podle id problemu # # vysledky_resitele = {} @@ -665,30 +623,6 @@ class SoustredeniUcastniciView(SoustredeniUcastniciBaseView): model = Soustredeni_Ucastnici template_name = 'seminar/soustredeni/seznam_ucastniku.html' - -def soustredeniStvrzenkyExportView(request,soustredeni,first_num): - first_num = int(first_num) - soustredeni = get_object_or_404(Soustredeni,id = soustredeni) - ucastnici = Resitel.objects.filter(soustredeni=soustredeni) - for (idx,u) in enumerate(ucastnici): - u.cislo_stvrzenky = first_num+idx; - tex = render(request,'seminar/soustredeni/ucastnici.tex', {'ucastnici': ucastnici, 'datum':soustredeni.datum_zacatku }).content - - tempdir = tempfile.mkdtemp() - with open(tempdir+"/ucastnici.tex","w") as texfile: - # Pokud TeX chce ISO Latin, tak se da encode nastavit - texfile.write(tex.decode("utf-8").encode("utf-8")) - shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenka.sty'),tempdir) - shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenky.tex'),tempdir) - subprocess.call(["cslatex","stvrzenky.tex"],cwd = tempdir) - subprocess.call(["dvipdf","stvrzenky.dvi"],cwd = tempdir) - - with open(tempdir+"/stvrzenky.pdf","rb") as pdffile: - response = HttpResponse(pdffile.read(),content_type='application/pdf') - shutil.rmtree(tempdir) - return response - - def soustredeniUcastniciExportView(request,soustredeni): soustredeni = get_object_or_404(Soustredeni,id = soustredeni) ucastnici = Resitel.objects.filter(soustredeni=soustredeni)