From 3439a3f15ebf00041b56b842e7421209dff4ca9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Koci=C3=A1n?= Date: Wed, 17 Feb 2016 16:17:11 +0100 Subject: [PATCH] =?UTF-8?q?P=C5=99=C3=ADprava=20na=20nahr=C3=A1v=C3=A1n?= =?UTF-8?q?=C3=AD=20obsahu=20z=20texu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/urls.py | 3 + seminar/views.py | 154 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 148 insertions(+), 9 deletions(-) diff --git a/seminar/urls.py b/seminar/urls.py index 968e5f02..1e67073b 100644 --- a/seminar/urls.py +++ b/seminar/urls.py @@ -49,4 +49,7 @@ urlpatterns = [ staff_member_required(views.obalkovaniView), name='seminar_cislo_resitel_obalkovani'), url(r'^soustredeni/(?P\d+)/obalky.pdf', staff_member_required(views.soustredeniObalkyView), name='seminar_soustredeni_obalky'), + + url(r'^tex-upload/login/$', views.LoginView, name='seminar_login'), + url(r'^tex-upload/$', staff_member_required(views.TexUploadView), name='seminar_tex_upload'), ] diff --git a/seminar/views.py b/seminar/views.py index 0f4c6e50..0d568cd2 100644 --- a/seminar/views.py +++ b/seminar/views.py @@ -1,15 +1,17 @@ # coding:utf-8 from django.shortcuts import get_object_or_404, render -from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden +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 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 +from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva from . import utils @@ -21,6 +23,10 @@ import shutil import os from django.conf import settings import unicodedata +import json +import traceback +import sys + def verejna_temata(rocnik): """Vrací queryset zveřejněných témat v daném ročníku. @@ -318,7 +324,7 @@ class CisloView(generic.DetailView): # 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 @@ -360,9 +366,9 @@ def aktualniResitele(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 && + +# 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): @@ -370,11 +376,11 @@ def aktivniResitele(rocnik,cislo): 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) + loni.cisla = Cislo.objects.filter(rocnik=loni.rocnik) if int(cislo) > 3: problemy = Problem.objects.filter(cislo_zadani = letos.cisla) else: @@ -382,7 +388,7 @@ def aktivniResitele(rocnik,cislo): resitele = aktualni_resitele.filter(reseni = Reseni.objects.filter(problem=problemy)).distinct() return resitele - + def cisloObalkyView(request,rocnik,cislo): return obalkyView(request,aktivniResitele(rocnik,cislo)) @@ -487,3 +493,133 @@ def StavDatabazeView(request): '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 = "{}/{}/{}/{}".format( + 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"] + uloz_soubory(request.FILES.items(), meta["rocnik"], c) + + # 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 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] + # Jinak vytvoříme nový + else: + problem = Problem( + typ=problem_typ, + stav=Problem.STAV_ZADANY, + kod=meta["kod"], + cislo_zadani=cislo + ) + + if meta["typ"] == "reseni": + problem.text_reseni = html + #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() + + # 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})