Hrubá implementace stahování jako ZIP
This commit is contained in:
parent
aa364b3f49
commit
cd914f4524
2 changed files with 48 additions and 0 deletions
|
@ -11,7 +11,9 @@ urlpatterns = [
|
|||
path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='odevzdavatko_resitel_odevzdana_reseni'),
|
||||
|
||||
path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||
path('org/reseni/zip/', org_required(views.OdevzdanaReseniVZipuView.as_view()), name='odevzdavatko_zip'),
|
||||
path('org/reseni/rocnik/<int:rocnik>/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||
path('org/reseni/rocnik/<int:rocnik>/zip/', org_required(views.OdevzdanaReseniVZipuView.as_view()), name='odevzdavatko_zip'),
|
||||
path('org/reseni/<int:problem>/<int:resitel>/', org_required(views.ReseniProblemuView.as_view()), name='odevzdavatko_reseni_resitele_k_problemu'),
|
||||
path('org/reseni/<int:pk>', org_required(viewMethodSwitch(get=views.EditReseniView.as_view(), post=views.hodnoceniReseniView)), name='odevzdavatko_detail_reseni'),
|
||||
path('org/reseni/all', org_required(views.SeznamReseniView.as_view())),
|
||||
|
|
|
@ -10,17 +10,22 @@ from django.shortcuts import redirect, get_object_or_404, render
|
|||
from django.urls import reverse
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponse
|
||||
|
||||
from dataclasses import dataclass
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
from itertools import groupby
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
from . import forms as f
|
||||
from .forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm
|
||||
from .models import Hodnoceni, Reseni
|
||||
|
||||
from odevzdavatko.templatetags.jmena import jmeno_jako_prefix
|
||||
from personalni.models import Resitel, Osoba, Organizator
|
||||
from tvorba.models import Problem, Deadline, Rocnik
|
||||
from tvorba.utils import resi_v_rocniku
|
||||
|
@ -175,6 +180,47 @@ class TabulkaOdevzdanychReseniView(ListView):
|
|||
|
||||
return ctx
|
||||
|
||||
# Intuitivně se mi dědičnost nelíbí, neumím říct přesně proč… (Zhruba:
|
||||
# vykoná/přikládá se spousta kódu, který ale souvisí jen s HTML, tím, že si
|
||||
# píšeme vlastní .get(). Lepší by bylo společné ne-HTML části (e.g.
|
||||
# inicializuj_osy_tabulky) vyrazit ven a v obou Views jen použít…)
|
||||
class OdevzdanaReseniVZipuView(TabulkaOdevzdanychReseniView):
|
||||
def get(self, request, *args, **kwargs):
|
||||
# Inspirováno implementací django.views.generic.list.BaseListView
|
||||
self.object_list = self.get_queryset()
|
||||
# Teď už máme i `self.problemy`.
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
print(f'DBG: {d=}')
|
||||
zfname = f"{d}/reseni.zip"
|
||||
with zipfile.ZipFile(zfname, 'w', compression=zipfile.ZIP_LZMA) as zf: # `zip` is builtin :-/
|
||||
print(f'DBG: .{self.reseni.count()=}')
|
||||
# TODO: data z tabulky
|
||||
for r in self.reseni:
|
||||
if len(r.resitele.all()) < 1:
|
||||
logger.error(f'Řešení {r.id} nemá řešitele??!!')
|
||||
continue
|
||||
# DBG!
|
||||
if len(r.prilohy.all()) < 1: continue
|
||||
# TODO: komentáře jmen souborů
|
||||
# Pro konzistenci imitujeme `data-alt-filename="{{object.resitele.first.osoba | jmeno_jako_prefix }}_{{ object.id }}_{{ priloha.split | last}}"` z templates/odevzdavatko/detail.html.
|
||||
jmeno_slozky = f'{jmeno_jako_prefix(r.resitele.first().osoba)}_{r.id}'
|
||||
zf.mkdir(jmeno_slozky)
|
||||
slozka = zipfile.Path(zf, jmeno_slozky)
|
||||
print(f'DBG: .({jmeno_slozky=}, {r.prilohy.count()=})')
|
||||
for pr in r.prilohy.all():
|
||||
jmeno_souboru = f'{jmeno_slozky}_{pr.split()[-1]}'
|
||||
print(f'DBG: .({os.path.join(jmeno_slozky, jmeno_souboru)=})')
|
||||
zf.write(pr.soubor.path, os.path.join(jmeno_slozky, jmeno_souboru))
|
||||
|
||||
print(f'DBG: Done, sending')
|
||||
# close&open k provedení všech zápisů
|
||||
with open(zfname, 'rb') as zf:
|
||||
print(f'DBG: .')
|
||||
response = HttpResponse(zf.read(), content_type='application/zip')
|
||||
response['Content-Disposition'] = 'attachment; filename="reseni.zip"'
|
||||
print(f'DBG: .')
|
||||
return response
|
||||
|
||||
# Velmi silně inspirováno zdrojáky, FIXME: Nedá se to udělat smysluplněji?
|
||||
class ReseniProblemuView(MultipleObjectTemplateResponseMixin, MultipleObjectMixin, View):
|
||||
"""Rozskok mezi více řešeními téhož problému od téhož řešitele.
|
||||
|
|
Loading…
Reference in a new issue