# coding:utf-8 from django.shortcuts import get_object_or_404, render from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied, ObjectDoesNotExist from django.views import generic from django.utils.translation import ugettext as _ from django.http import Http404,HttpResponseBadRequest from django.db.models import Q from django.views.decorators.csrf import ensure_csrf_cookie from django.contrib.auth import authenticate, login from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Prispevek from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva from . import utils from .unicodecsv import UnicodeWriter from datetime import timedelta, date, datetime from itertools import groupby import tempfile import subprocess import shutil import os import os.path as op from django.conf import settings import unicodedata import json import traceback import sys import csv def verejna_temata(rocnik): """Vrací queryset zveřejněných témat v daném ročníku. """ return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod') def AktualniZadaniView(request): nastaveni = get_object_or_404(Nastaveni) verejne = nastaveni.aktualni_cislo.verejne() problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany') ulohy = problemy.filter(typ = 'uloha').order_by('kod') serialy = problemy.filter(typ = 'serial').order_by('kod') jednorazove_problemy = [ulohy, serialy] return render(request, 'seminar/zadani/AktualniZadani.html', {'nastaveni': nastaveni, 'jednorazove_problemy': jednorazove_problemy, 'temata': verejna_temata(nastaveni.aktualni_rocnik), 'verejne': verejne, }, ) def ZadaniTemataView(request): nastaveni = get_object_or_404(Nastaveni) temata = verejna_temata(nastaveni.aktualni_rocnik) for t in temata: if request.user.is_staff: t.prispevky = t.prispevek_set.filter(problem=t) else: t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True) return render(request, 'seminar/zadani/Temata.html', { 'temata': temata, } ) def ZadaniAktualniVysledkovkaView(request): nastaveni = get_object_or_404(Nastaveni) # Aktualni verejna vysledkovka vysledkovka = vysledkovka_rocniku(nastaveni.aktualni_rocnik) # kdyz neni verejna vysledkovka, tak zobraz starou if not vysledkovka: try: minuly_rocnik = Rocnik.objects.get( prvni_rok=(nastaveni.aktualni_rocnik.prvni_rok-1)) vysledkovka = vysledkovka_rocniku(minuly_rocnik) except ObjectDoesNotExist: pass # vysledkovka s neverejnyma vysledkama vysledkovka_s_neverejnymi = vysledkovka_rocniku(nastaveni.aktualni_rocnik, jen_verejne=False) return render( request, 'seminar/zadani/AktualniVysledkovka.html', { 'nastaveni': nastaveni, 'vysledkovka': vysledkovka, 'vysledkovka_s_neverejnymi': vysledkovka_s_neverejnymi, } ) ### Titulni strana class TitulniStranaView(generic.ListView): model = Novinky template_name='seminar/titulnistrana.html' queryset = Novinky.objects.order_by('-datum')[:5] def get_context_data(self, **kwargs): context = super(TitulniStranaView, self).get_context_data(**kwargs) nastaveni = get_object_or_404(Nastaveni) # zjisteni spravneho terminu if nastaveni.aktualni_cislo.datum_deadline_soustredeni: cas_deadline_soustredeni = nastaveni.aktualni_cislo.\ datum_deadline_soustredeni if (datetime.now().date() <= cas_deadline_soustredeni): cas_deadline = cas_deadline_soustredeni deadline_soustredeni = True else: cas_deadline = nastaveni.aktualni_cislo.datum_deadline deadline_soustredeni = False else: cas_deadline = nastaveni.aktualni_cislo.datum_deadline deadline_soustredeni = False # Pokud neni zverejnene cislo nezverejnuj odpocet if nastaveni.aktualni_cislo.verejne(): # pokus se zjistit termin odeslani a pokud neni zadany, # nezverejnuj odpocet context['deadline_soustredeni'] = deadline_soustredeni try: context['dead'] = datetime.combine(cas_deadline, datetime.max.time()) context['ted'] = datetime.now() except: context['dead'] = None else: context['dead'] = None context['deadline_soustredeni'] = deadline_soustredeni return context class StareNovinkyView(generic.ListView): model = Novinky template_name = 'seminar/stare_novinky.html' queryset = Novinky.objects.filter(zverejneno=True).order_by('-datum') ### Co je M&M # Organizatori def aktivniOrganizatori(rok=date.today().year): return Organizator.objects.exclude( organizuje_do_roku__isnull=False, organizuje_do_roku__lt=rok ).order_by('user__first_name') class CojemamOrganizatoriView(generic.ListView): model = Organizator template_name = 'seminar/cojemam/organizatori.html' queryset = aktivniOrganizatori() def get_context_data(self, **kwargs): context = super(CojemamOrganizatoriView, self).get_context_data(**kwargs) context['aktivni'] = True return context class CojemamOrganizatoriStariView(generic.ListView): model = Organizator template_name = 'seminar/cojemam/organizatori.html' queryset = Organizator.objects.exclude( id__in=aktivniOrganizatori()).order_by('-organizuje_do_roku') ### Archiv class ArchivView(generic.ListView): model = Rocnik template_name='seminar/archiv/cisla.html' def get_context_data(self, **kwargs): context = super(ArchivView, self).get_context_data(**kwargs) vyska = 297 # px sirka = 210 # px sirka_paddingu = 3 # px cisla = Cislo.objects.filter(verejne_db=True)[:10] png_dir = op.join(settings.MEDIA_ROOT, "cislo", "png") if not op.isdir(png_dir): os.makedirs(png_dir) # seznam [(url obrázku, číslo)] urls = [] for i, c in enumerate(cisla): if not c.pdf: continue filename = os.path.split(c.pdf.file.name)[1].split(".")[0] png_filename = "{}-{}px.png".format(filename, vyska) def vytvor_obrazek_titulky(strana, pdf_path, png_path, rotace=0): subprocess.call([ "convert", "-density", "180x180", "-geometry", "{}x{}".format(strana, strana), "-background", "white", "-flatten", "-rotate", str(rotace), "{}[0]".format(pdf_path), # titulní strana png_path ]) # Pokud obrázek neexistuje nebo není aktuální, vytvoř jej png_path = op.join(png_dir, png_filename) if not op.exists(png_path) or \ op.getmtime(png_path) < op.getmtime(c.pdf.path): vytvor_obrazek_titulky( vyska - sirka_paddingu, c.pdf.path, png_path, rotace=i * 90 ) urls.append( (op.join(settings.MEDIA_URL, "cislo", "png", png_filename), c) ) vyska, sirka = sirka, vyska / 2 tags = [] def spirala(urls, tags, idx): """Rekurzivně prochází urls a generuje strom elementů do tags""" if idx >= len(urls): return img_url, cislo = urls[idx] tags.append( "
" .format( 50 if idx % 4 == 2 else 0, 50 if idx % 4 == 1 else 0, 50 if idx % 2 == 1 else 100, 50 if idx > 0 and idx % 2 == 0 else 100 ) ) tags.append("".format( cislo.verejne_url(), cislo.kod() )) tags.append( "" .format( img_url, sirka_paddingu, 50 if idx % 4 == 3 else 0, 50 if idx % 4 == 2 else 0, 50 if idx % 2 == 0 else 100, 50 if idx % 2 == 1 else 100 ) ) tags.append("") spirala(urls, tags, idx + 1) tags.append("
") spirala(urls, tags, 0) # náhledy v řádcích cisla = Cislo.objects.all().select_related("rocnik__rocnik")\ .order_by("-rocnik__rocnik", "cislo") for c in cisla: if not c.pdf: continue png_filename_radek = "{}-{}.png".format(c.rocnik.rocnik, c.cislo) www_png_dir = op.join(settings.MEDIA_URL, "cislo", "png") png_path_radek = op.join(png_dir, png_filename_radek) if not op.exists(png_path_radek) or \ op.getmtime(png_path_radek) < op.getmtime(c.pdf.path): vytvor_obrazek_titulky( 297 // 4, c.pdf.path, png_path_radek ) context["nahledy"] = "\n".join(tags) context["cisla"] = cisla context["www_png_dir"] = www_png_dir return context def sloupec_s_poradim(vysledky): # počet řešitelů ve výsledkovce nad aktuálním lepsich_resitelu = 0 poradi_l = [] # projdeme skupiny řešitelů se stejným počtem bodů for skupina in (list(x) for _, x in groupby(vysledky, lambda x: x.body)): # připravíme si obsahy buněk ve sloupci pořadí pro skupinu if len(skupina) == 1: poradi_l += ["{}.".format(lepsich_resitelu + 1)] # je-li účastníků se stejným počtem bodů víc, pořadí (rozsah X.-Y.) je jen u prvního else: poradi_l += [u"{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1) lepsich_resitelu += len(skupina) #pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu return poradi_l def vysledkovka_rocniku(rocnik, jen_verejne=True): """Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html" """ #vyberu vsechny vysledky z rocniku cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__rocnik=rocnik).order_by('cislo') if jen_verejne: cisla_v_rocniku = cisla_v_rocniku.filter(cislo__verejna_vysledkovka=True) #pokud žádné nejsou, výsledkovka se nezobrazí if not cisla_v_rocniku: return None #vybere vsechny vysledky z posledniho (verejneho) cisla a setridi sestupne dle bodu vysledky = list(cisla_v_rocniku.filter(cislo = cisla_v_rocniku[0].cislo).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno').select_related('resitel')) class Vysledkovka: def __init__(self): self.rocnik = rocnik.rocnik self.radky = [] self.cisla = [] vysledkovka = Vysledkovka() vysledkovka.cisla = (rocnik.verejne_vysledkovky_cisla() if jen_verejne else rocnik.cisla.all().order_by('cislo')) # doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky): v.poradi = poradi v.resitel.rocnik = v.resitel.rocnik(rocnik) verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__rocnik=rocnik, cislo=cisla_v_rocniku[0].cislo) if jen_verejne: verejne_vysl_odjakziva = verejne_vysl_odjakziva.filter(cislo__verejna_vysledkovka=True) v.body_odjakziva = verejne_vysl_odjakziva.filter(resitel = v.resitel)[0].body v.titul = v.resitel.get_titul(v.body_odjakziva) v.body_rocnik = v.body v.body_cisla = [] #pokud pro dany rok a cislo nema resitel vysledky, ma defaultne 0 for cis in vysledkovka.cisla: if not jen_verejne or cis.verejna_vysledkovka: #seznam vysledku se spravnym rocnikem a cislem pro resitele #zobrazim jen je-li vysledkovka verejna body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik=rocnik).filter(cislo = cis).filter(resitel = v.resitel) if body_za_cislo: #neprazdne vysledky by mely obsahovat prave jeden vysledek v.body_cisla.append(body_za_cislo[0].body) else: #resitel nema za cislo body v.body_cisla.append(0) vysledkovka.radky.append(v) return vysledkovka class RocnikView(generic.DetailView): model = Rocnik template_name = 'seminar/archiv/rocnik.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') 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 def get_context_data(self, **kwargs): context = super(RocnikView, self).get_context_data(**kwargs) context['vysledkovka'] = vysledkovka_rocniku(context["rocnik"]) context['vysledkovka_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False) context['temata_v_rocniku'] = verejna_temata(context["rocnik"]) return context class ProblemView(generic.DetailView): model = Problem def _je_clanek(self, problem): return problem.typ in [Problem.TYP_ORG_CLANEK, Problem.TYP_RES_CLANEK] def get_template_names(self, **kwargs): context = super(ProblemView, self).get_context_data(**kwargs) return ['seminar/archiv/problem_' + ('clanek.html' if self._je_clanek(context['problem']) else 'uloha_tema.html')] def get_context_data(self, **kwargs): context = super(ProblemView, self).get_context_data(**kwargs) if not context['problem'].verejne() and not self.request.user.is_staff: raise PermissionDenied() if context['problem'].typ == Problem.TYP_RES_CLANEK: context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni') return context 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 class CisloView(generic.DetailView): model = Cislo 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): context = super(CisloView, self).get_context_data(**kwargs) vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno') reseni = Reseni.objects.filter(cislo_body = context['cislo']).select_related("resitel") # typy úloh, které se mají zobrazovat u čísla, tj. těch, které byly v čísle skutečně zadány typy_skutecne_zadanych = [Problem.TYP_ULOHA, Problem.TYP_SERIAL, Problem.TYP_ORG_CLANEK] v_cisle_zadane = Problem.objects.filter(cislo_zadani=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('kod') resene_problemy = Problem.objects.filter(cislo_reseni=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('cislo_zadani__cislo', 'kod') poradi_typu = { Problem.TYP_ULOHA: 1, Problem.TYP_SERIAL: 2, Problem.TYP_ORG_CLANEK: 3, Problem.TYP_TEMA: 4, Problem.TYP_RES_CLANEK: 5 } problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku())) #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 = {} vysledkovka = [] # doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky): v.poradi = poradi v.body_celkem_rocnik = v.body v.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body v.resitel.rocnik = v.resitel.rocnik(v.cislo.rocnik) # je tady '', aby se nezobrazovala 0, pokud se řešitel o řešení úlohy ani nepokusil v.body_ulohy = [''] * len(problemy) v.titul = v.resitel.get_titul(v.body_celkem_odjakziva) body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo']) v.body_cislo = body_cislo_q[0].body if body_cislo_q else 0 vysledkovka.append(v) # připravíme si odkaz na řádek, abychom do něj mohli doplnit body za jednotlivé úlohy vysledky_resitele[v.resitel.id] = v # za každé řešení doplníme k příslušnému řešiteli a úloze body for r in reseni: vysledky_resitele[r.resitel.id].body_ulohy[problem_index[r.problem.id]] = r.body context['vysledkovka'] = vysledkovka context['problemy'] = problemy context['v_cisle_zadane'] = v_cisle_zadane context['resene_problemy'] = resene_problemy return context class ArchivTemataView(generic.ListView): model = Problem template_name = 'seminar/archiv/temata.html' queryset = Problem.objects.filter(typ=Problem.TYP_TEMA, stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') ### Generovani vysledkovky class CisloVysledkovkaView(CisloView): model = Cislo template_name = 'seminar/archiv/cislo_vysledkovka.tex' #content_type = 'application/x-tex; charset=UTF8' #umozni rovnou stahnout TeXovsky dokument content_type = 'text/plain; charset=UTF8' #vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani class RocnikVysledkovkaView(RocnikView): model = Rocnik template_name = 'seminar/archiv/rocnik_vysledkovka.tex' #content_type = 'application/x-tex; charset=UTF8' #umozni rovnou stahnout TeXovsky dokument content_type = 'text/plain; charset=UTF8' #vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani ### Generovani obalek class CisloObalkyStruct: rocnik = None cisla = None # Vraci QuerySet aktualnich resitelu = nekdy neco poslali, ale jeste neodmaturovali def aktualniResitele(rocnik): letos = Rocnik.objects.get(rocnik = rocnik) return Resitel.objects.filter(rok_maturity__gt = letos.prvni_rok) # # ALERT: pokud nekdo nema vypleny rok maturity, tak neni aktualni, protoze Karel Tesar a jini # return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None)) # Vraci QuerySet aktivnich resitelu = # jeste neodmaturovali && # (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali # jinak letos neco poslali) def aktivniResitele(rocnik,cislo): letos = CisloObalkyStruct() loni = CisloObalkyStruct() aktualni_resitele = aktualniResitele(rocnik) letos.rocnik = Rocnik.objects.get(rocnik = rocnik) loni.rocnik = Rocnik.objects.get(rocnik = int(rocnik)-1) letos.cisla = Cislo.objects.filter(rocnik=letos.rocnik,cislo__lte = cislo) loni.cisla = Cislo.objects.filter(rocnik=loni.rocnik) if int(cislo) > 3: problemy = Problem.objects.filter(cislo_zadani = letos.cisla) else: problemy = Problem.objects.filter(Q(cislo_zadani = letos.cisla)|Q(cislo_zadani=loni.cisla)) resitele = aktualni_resitele.filter(reseni = Reseni.objects.filter(problem=problemy)).distinct() return resitele def cisloObalkyView(request,rocnik,cislo): return obalkyView(request,aktivniResitele(rocnik,cislo)) def obalkyView(request,resitele): tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content tempdir = tempfile.mkdtemp() with open(tempdir+"/obalky.tex","w") as texfile: # Pokud TeX chce ISO Latin, tak se da encode nastavit texfile.write(tex.decode("utf-8").encode("iso-8859-2")) shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.eps'),tempdir) subprocess.call(["csplain","obalky.tex"],cwd = tempdir) subprocess.call(["dvipdf","obalky.dvi"],cwd = tempdir) with open(tempdir+"/obalky.pdf","rb") as pdffile: response = HttpResponse(pdffile.read(),content_type='application/pdf') shutil.rmtree(tempdir) return response def obalkovaniView(request, rocnik, cislo): rocnik = Rocnik.objects.get(rocnik=rocnik) cislo = Cislo.objects.get(rocnik=rocnik, cislo=cislo) reseni = ( Reseni.objects.filter(cislo_body=cislo) .order_by( 'resitel__prijmeni', 'resitel__jmeno', 'problem__typ', 'problem__kod' ) ) problemy = sorted(set(r.problem for r in reseni), key=lambda p: (p.typ, p.kod)) return render( request, 'seminar/archiv/cislo_obalkovani.html', {'cislo': cislo, 'problemy': problemy, 'reseni': reseni} ) ### Tituly # TODO udelat neco jako get_objects_or_404 def TitulyView(request, rocnik, cislo): rocnik_obj = Rocnik.objects.get(rocnik = rocnik) resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok) cislo_obj = Cislo.objects.get(rocnik = rocnik_obj, cislo = cislo) asciijmena = [] broken = False for resitel in resitele: try: vys = VysledkyKCisluOdjakziva.objects.get(resitel = resitel, cislo = cislo_obj) body = vys.body except ObjectDoesNotExist: body = 0 resitel.titul = resitel.get_titul(body) resitel.ascii = unicodedata.normalize('NFKD',resitel.jmeno+resitel.prijmeni).encode("ascii","ignore").replace(" ","") if resitel.ascii not in asciijmena: asciijmena.append(resitel.ascii) else: broken = True return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele,'broken':broken},content_type="text/plain") ### 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' def soustredeniObalkyView(request,soustredeni): soustredeni = get_object_or_404(Soustredeni,id = soustredeni) return obalkyView(request,soustredeni.ucastnici.all()) class SoustredeniUcastniciBaseView(generic.ListView): model = Soustredeni_Ucastnici def get_queryset(self): soustredeni = get_object_or_404( Soustredeni, pk=self.kwargs["soustredeni"] ) return Soustredeni_Ucastnici.objects.filter( soustredeni=soustredeni).select_related('resitel') class SoustredeniMailyUcastnikuView(SoustredeniUcastniciBaseView): """Seznam e-mailů řešitelů oddělených čárkami""" model = Soustredeni_Ucastnici template_name = 'seminar/soustredeni/maily_ucastniku.txt' class SoustredeniUcastniciView(SoustredeniUcastniciBaseView): """HTML tabulka účastníků pro tisk""" 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) response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="ucastnici.csv"' writer = UnicodeWriter(response) writer.writerow(["jmeno", "prijmeni", "rok_maturity", "telefon", "email", "ulice", "mesto", "psc","stat"]) for u in ucastnici: writer.writerow([u.jmeno, u.prijmeni, str(u.rok_maturity), u.telefon, u.email, u.ulice, u.mesto, u.psc, u.stat.name]) return response ### Články class ClankyResitelView(generic.ListView): model = Problem template_name = 'seminar/clanky/resitelske_clanky.html' queryset = Problem.objects.filter(typ=Problem.TYP_RES_CLANEK, stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') class ClankyOrganizatorView(generic.ListView): model = Problem template_name = 'seminar/clanky/organizatorske_clanky.html' queryset = Problem.objects.filter(typ=Problem.TYP_ORG_CLANEK, stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') ### Status def StavDatabazeView(request): # nastaveni = Nastaveni.objects.get() problemy = utils.seznam_problemu() muzi = Resitel.objects.filter(pohlavi_muz=True) zeny = Resitel.objects.filter(pohlavi_muz=False) return render(request, 'seminar/stav_databaze.html', { # 'nastaveni': nastaveni, 'problemy': problemy, 'resitele': Resitel.objects.all(), 'muzi': muzi, 'zeny': zeny, 'jmena_muzu': utils.histogram([r.jmeno for r in muzi]), 'jmena_zen': utils.histogram([r.jmeno for r in zeny]), }) @ensure_csrf_cookie def LoginView(request): """Pro přihlášení při nahrávání z texu""" q = request.POST # nastavení cookie csrftoken if not q: return JsonResponse({"ok": 1}) if "username" in q: username = q["username"] password = q["password"] user = authenticate(username=username, password=password) if user is not None and user.is_staff: login(request, user) return JsonResponse({"ok": 1}) else: return JsonResponse({"error": "Neplatné uživatelské jméno nebo heslo"}) @ensure_csrf_cookie def texUploadView(request): def uloz_soubory(files, rocnik, cislo): for filename, f in files: path = os.path.join( settings.MEDIA_ROOT, settings.CISLO_IMG_DIR, rocnik, cislo, filename ) adresar = os.path.dirname(path) if not os.path.exists(adresar): os.makedirs(adresar) with open(path, "wb+") as fout: for chunk in f.chunks(): fout.write(chunk) q = request.POST # nastavení cookie csrftoken if not q: return JsonResponse({"ok": 1}) # Odchytíme všechny výjimky a traceback pošleme v odpovědi try: meta = json.loads(q["meta"]) html = q["html"] if meta["typ"] in ["uloha", "serial", "reseni"]: # Uložíme soubory if meta["typ"] != "reseni": c = meta["cislo"] else: # Řešení má nastavené číslo svojí úlohy, ale obrázky jsou # ukládány do čísla, kde řešení vyšlo c = meta["cislo_reseni"] # Zjistíme typ ukládaného problému typy = { "uloha": Problem.TYP_ULOHA, "serial": Problem.TYP_SERIAL, "reseni": Problem.TYP_ULOHA, } problem_typ = typy[meta["typ"]] # Pokud už problém existuje, vytáhneme jej z db a upravíme # Pokud neexistuje, vytvoříme jej jedině pokud je to vynucené # Pokud ročník/číslo ještě neexistuje, vyhodí to výjimku -> # číslo/ročník se musí založit ručně v adminu rocnik = Rocnik.objects.get(rocnik=meta["rocnik"]) cislo = Cislo.objects.get(rocnik=rocnik, cislo=meta["cislo"]) existujici = Problem.objects.filter( typ=problem_typ, stav=Problem.STAV_ZADANY, cislo_zadani=cislo, kod=meta["kod"] ) problem = None if existujici: problem = existujici[0] elif "vytvor" in q: # vytvoříme nový problem = Problem( typ=problem_typ, stav=Problem.STAV_ZADANY, kod=meta["kod"], cislo_zadani=cislo ) else: return JsonResponse({ "error": "Problém neexistuje: {} {}.{} kód {}".format( meta["typ"], meta["rocnik"], meta["cislo"], meta["kod"] ) }) uloz_soubory(request.FILES.items(), meta["rocnik"], c) if meta["typ"] == "reseni": problem.text_reseni = html problem.cislo_reseni = meta["cislo_reseni"] # při nahrávání řešení už původní zadání atd. neměníme else: problem.text_zadani = html problem.nazev = meta["nazev"] problem.body = meta["body"] problem.save() cislo.faze = cislo.FAZE_NAHRANO cislo.save() # Vrátíme id dané úlohy, aby se k ní dala případně připojit pohádka return JsonResponse({"db_id": problem.id}) elif meta["typ"] == "pohadka": uloha = Problem.objects.get(typ=Problem.TYP_ULOHA, pk=meta["uloha"]) # Pokud už příslušná pohádka existuje, jen ji upravíme existujici = Pohadka.objects.filter(uloha=uloha, pred=meta["pred"]) pohadka = None if existujici: pohadka = existujici[0] else: pohadka = Pohadka(uloha=uloha, pred=meta["pred"]) pohadka.text = q["html"] pohadka.save() return JsonResponse({"db_id": pohadka.id}) except Exception, e: # Pošleme zpátky traceback, ať uživatel ví, v čem je problém tb = "".join(traceback.format_exception(type(e), e, sys.exc_info()[2])) return JsonResponse({"error": tb}) def texDownloadView(request, rocnik, cislo): """View posílající JSON se zadanými a řešenými problémy pro založení čísla """ cislo = Cislo.objects.get(rocnik__rocnik=rocnik, cislo=cislo) if cislo.faze == cislo.FAZE_NAHRANO: # obsah byl nahrán z TeXu na web, už je příliš složitý return JsonResponse( {"error": "Obsah čísla už byl nahrán z TeXu na web."} ) zadane = Problem.objects.filter( cislo_zadani=cislo, stav=Problem.STAV_ZADANY ) resene = Problem.objects.filter( cislo_reseni=cislo, stav=Problem.STAV_ZADANY, typ=Problem.TYP_ULOHA ) pred_pohadky = Pohadka.objects.filter(uloha__cislo_zadani=cislo, pred=True) po_pohadky = Pohadka.objects.filter(uloha__cislo_zadani=cislo, pred=False) response = { "zadane": [ { "nazev": p.nazev, "typ": p.typ, "kod": p.kod, "body": p.body, "zadani": p.text_zadani, "pred_pohadky": [x.text for x in pred_pohadky.filter(uloha=p)], "po_pohadky": [x.text for x in po_pohadky.filter(uloha=p)], } for p in zadane ], "resene": [ { "nazev": p.nazev, "typ": p.typ, "kod": p.kod, "body": p.body, "zadani": p.text_zadani, "reseni": p.text_reseni, "cislo_zadani": p.cislo_zadani.cislo, } for p in resene ], } cislo.faze = Cislo.FAZE_TEX cislo.save() return JsonResponse(response) # Ceka na autocomplete v3 # class OrganizatorAutocomplete(autocomplete.Select2QuerySetView): # def get_queryset(self): # if not self.request.user.is_authenticated(): # return Organizator.objects.none() # # qs = aktivniOrganizatori() # # if self.q: # if self.q[0] == "!": # qs = Organizator.objects.all() # query = self.q[1:] # else: # query = self.q # qs = qs.filter( # Q(prezdivka__isstartswith=query)| # Q(user__first_name__isstartswith=query)| # Q(user__last_name__isstartswith=query)) # # return qs