From 658f2a53c63a58880ea947716a6252c62208ef27 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Tue, 19 Jan 2021 19:25:39 +0100 Subject: [PATCH] =?UTF-8?q?WIP:=20odevzd=C3=A1v=C3=A1tkov=C3=A9=20formsety?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/forms.py | 10 +++++++ .../seminar/odevzdavatko/detail.html | 4 +++ seminar/urls.py | 5 ++-- seminar/utils.py | 28 +++++++++++++++++++ seminar/views/odevzdavatko.py | 28 +++++++++++++++++-- 5 files changed, 69 insertions(+), 6 deletions(-) diff --git a/seminar/forms.py b/seminar/forms.py index a7e0e404..0886f87d 100644 --- a/seminar/forms.py +++ b/seminar/forms.py @@ -301,3 +301,13 @@ class NahrajObrazekKTreeNoduForm(forms.ModelForm): model = m.Obrazek fields = ('na_web',) + +OhodnoceniReseniFormSet = inlineformset_factory(m.Reseni, m.Hodnoceni, + fields = ('problem', 'body', 'cislo_body'), + extra = 1, + widgets = { + 'problem': autocomplete.ModelSelect2( + url='autocomplete_problem_odevzdatelny', # FIXME: Dovolit i starší? + ) + } + ) diff --git a/seminar/templates/seminar/odevzdavatko/detail.html b/seminar/templates/seminar/odevzdavatko/detail.html index 6cee990d..24617dda 100644 --- a/seminar/templates/seminar/odevzdavatko/detail.html +++ b/seminar/templates/seminar/odevzdavatko/detail.html @@ -43,5 +43,9 @@

Ještě nebylo hodnoceno

{% endif %} +
+{% csrf_token %} +{{ form }} +
{% endblock %} diff --git a/seminar/urls.py b/seminar/urls.py index 7fa7b0a6..3d66526b 100644 --- a/seminar/urls.py +++ b/seminar/urls.py @@ -1,7 +1,7 @@ from django.urls import path, include, re_path from django.contrib.auth.decorators import login_required from . import views, export -from .utils import org_required, resitel_required +from .utils import org_required, resitel_required, viewMethodSwitch from django.views.generic.base import RedirectView urlpatterns = [ @@ -174,8 +174,7 @@ urlpatterns = [ path('temp/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'), path('temp/reseni///', org_required(views.ReseniProblemuView.as_view()), name='odevzdavatko_reseni_resitele_k_problemu'), - path('temp/reseni/', org_required(views.DetailReseniView.as_view()), name='odevzdavatko_detail_reseni'), + path('temp/reseni/', org_required(viewMethodSwitch(get=views.DetailReseniView.as_view(), post=views.HodnoceniReseniView.as_view())), name='odevzdavatko_detail_reseni'), path('temp/reseni/all', org_required(views.SeznamReseniView.as_view())), path('temp/reseni/akt', org_required(views.SeznamAktualnichReseniView.as_view())), - ] diff --git a/seminar/utils.py b/seminar/utils.py index bcc67013..39abeae7 100644 --- a/seminar/utils.py +++ b/seminar/utils.py @@ -5,6 +5,7 @@ import datetime from django.contrib.auth import get_user_model from django.contrib.auth.decorators import permission_required from html.parser import HTMLParser +from django import views as DjangoViews from django.contrib.auth.models import AnonymousUser from django.contrib.contenttypes.models import ContentType @@ -191,3 +192,30 @@ def aktivniResitele(cislo, pouze_letosni=False): else: # spojíme querysety s řešiteli loni a letos do daného čísla return (resi_v_rocniku(loni) | resi_v_rocniku(letos, cislo)).distinct() + +def viewMethodSwitch(get, post): + """ + Vrátí view, který zavolá různé jiné views podle toho, kterou metodou je zavolán. + + Inspirováno https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#an-alternative-better-solution, jen jsem to udělal genericky. + + Parametry: + post view pro metodu POST + get view pro metodu GET + + V obou případech se míní už view jakožto funkce, takže u class-based views se už má použít .as_view() + + TODO: Podpora i pro metodu HEAD? A možná i pro FILES? + """ + + theGetView = get + thePostView = post + + class NewView(DjangoViews.View): + def get(self, request, *args, **kwargs): + return theGetView(request, *args, **kwargs) + def post(self, request, *args, **kwargs): + return thePostView(request, *args, **kwargs) + + return NewView.as_view() + diff --git a/seminar/views/odevzdavatko.py b/seminar/views/odevzdavatko.py index de8ceec3..6a593740 100644 --- a/seminar/views/odevzdavatko.py +++ b/seminar/views/odevzdavatko.py @@ -1,10 +1,11 @@ -from django.views.generic import ListView, DetailView -from django.views.generic.base import TemplateView +from django.views.generic import ListView, DetailView, FormView +from django.views.generic.detail import SingleObjectMixin from dataclasses import dataclass import datetime import seminar.models as m +import seminar.forms as f from seminar.utils import aktivniResitele, resi_v_rocniku # Co chceme? @@ -109,10 +110,31 @@ class ReseniProblemuView(ListView): # Kontext automaticky? +## XXX: https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#avoid-anything-more-complex class DetailReseniView(DetailView): model = m.Reseni template_name = 'seminar/odevzdavatko/detail.html' - # To je všechno? Najde se to podle pk... + + def aktualni_hodnoceni(self): + ... + return [] + + def get_context_data(self, **kw): + ctx = super().get_context_data(**kw) + ctx['form'] = f.OhodnoceniReseniFormSet( + initial = self.aktualni_hodnoceni() + ) + return ctx + + +class HodnoceniReseniView(SingleObjectMixin, FormView): + model = m.Reseni + template_name = 'seminar/odevzdavatko/detail.html' + form_class = f.OhodnoceniReseniFormSet + + def form_vaild(self, form): + ... + # Přehled všech řešení kvůli debugování