Browse Source

WIP: odevzdávátkové formsety

export_seznamu_prednasek
Pavel "LEdoian" Turinsky 4 years ago
parent
commit
658f2a53c6
  1. 10
      seminar/forms.py
  2. 4
      seminar/templates/seminar/odevzdavatko/detail.html
  3. 5
      seminar/urls.py
  4. 28
      seminar/utils.py
  5. 28
      seminar/views/odevzdavatko.py

10
seminar/forms.py

@ -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ší?
)
}
)

4
seminar/templates/seminar/odevzdavatko/detail.html

@ -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 %}

5
seminar/urls.py

@ -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())),
] ]

28
seminar/utils.py

@ -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í view jakožto funkce, takže u class-based views se 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()

28
seminar/views/odevzdavatko.py

@ -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…
Cancel
Save