WIP: odevzdávátkové formsety
This commit is contained in:
parent
8c64fb5a24
commit
658f2a53c6
5 changed files with 69 additions and 6 deletions
|
@ -301,3 +301,13 @@ class NahrajObrazekKTreeNoduForm(forms.ModelForm):
|
||||||
model = m.Obrazek
|
model = m.Obrazek
|
||||||
fields = ('na_web',)
|
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ší?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
@ -43,5 +43,9 @@
|
||||||
<p>Ještě nebylo hodnoceno</p>
|
<p>Ještě nebylo hodnoceno</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<form method=post><table>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form }}
|
||||||
|
</table><input type=submit></form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.urls import path, include, re_path
|
from django.urls import path, include, re_path
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from . import views, export
|
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
|
from django.views.generic.base import RedirectView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -174,8 +174,7 @@ urlpatterns = [
|
||||||
|
|
||||||
path('temp/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
path('temp/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||||
path('temp/reseni/<int:problem>/<int:resitel>/', org_required(views.ReseniProblemuView.as_view()), name='odevzdavatko_reseni_resitele_k_problemu'),
|
path('temp/reseni/<int:problem>/<int:resitel>/', org_required(views.ReseniProblemuView.as_view()), name='odevzdavatko_reseni_resitele_k_problemu'),
|
||||||
path('temp/reseni/<int:pk>', org_required(views.DetailReseniView.as_view()), name='odevzdavatko_detail_reseni'),
|
path('temp/reseni/<int:pk>', 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/all', org_required(views.SeznamReseniView.as_view())),
|
||||||
path('temp/reseni/akt', org_required(views.SeznamAktualnichReseniView.as_view())),
|
path('temp/reseni/akt', org_required(views.SeznamAktualnichReseniView.as_view())),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,6 +5,7 @@ import datetime
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
|
from django import views as DjangoViews
|
||||||
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
@ -191,3 +192,30 @@ def aktivniResitele(cislo, pouze_letosni=False):
|
||||||
else:
|
else:
|
||||||
# spojíme querysety s řešiteli loni a letos do daného čísla
|
# spojíme querysety s řešiteli loni a letos do daného čísla
|
||||||
return (resi_v_rocniku(loni) | resi_v_rocniku(letos, cislo)).distinct()
|
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()
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
from django.views.generic import ListView, DetailView
|
from django.views.generic import ListView, DetailView, FormView
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import seminar.models as m
|
import seminar.models as m
|
||||||
|
import seminar.forms as f
|
||||||
from seminar.utils import aktivniResitele, resi_v_rocniku
|
from seminar.utils import aktivniResitele, resi_v_rocniku
|
||||||
|
|
||||||
# Co chceme?
|
# Co chceme?
|
||||||
|
@ -109,10 +110,31 @@ class ReseniProblemuView(ListView):
|
||||||
|
|
||||||
# Kontext automaticky?
|
# Kontext automaticky?
|
||||||
|
|
||||||
|
## XXX: https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#avoid-anything-more-complex
|
||||||
class DetailReseniView(DetailView):
|
class DetailReseniView(DetailView):
|
||||||
model = m.Reseni
|
model = m.Reseni
|
||||||
template_name = 'seminar/odevzdavatko/detail.html'
|
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í
|
# Přehled všech řešení kvůli debugování
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue