Upgrade odevzdavatka #30
|
@ -70,23 +70,17 @@ class PublicResitelAutocomplete(LoginRequiredAjaxMixin, autocomplete.Select2Quer
|
|||
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
||||
def get_queryset(self):
|
||||
nastaveni = get_object_or_404(m.Nastaveni)
|
||||
rocnik = nastaveni.aktualni_rocnik
|
||||
# Od tohoto místa dál jsem zkoušel spoustu variací podle https://django-polymorphic.readthedocs.io/en/stable/advanced.html
|
||||
temaQ = Q(Tema___rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||
clanekQ = Q(Clanek___cislo__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||
qs = m.Problem.objects.filter(temaQ | ulohaQ | clanekQ)
|
||||
#print(temata, ulohy, clanky)
|
||||
#ulohy.union(temata, all=True)
|
||||
#print(ulohy)
|
||||
#ulohy.union(clanky, all=True)
|
||||
#print(ulohy)
|
||||
#qs = ulohy
|
||||
print(qs)
|
||||
qs = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY)
|
||||
if self.q:
|
||||
qs = qs.filter(
|
||||
Q(nazev__icontains=self.q))
|
||||
|
||||
nadproblem_id = int(self.forwarded.get("nadproblem_id", -1))
|
||||
if nadproblem_id != -1:
|
||||
# Seřadíme tak, aby ty s nadproblem==None byly dole (větší motivace tam naklikat konkrétní úlohy) a pak nějak rozumně.
|
||||
# Tohle je řazení pro odevzdávátko, kde je definován nadproblém, proto je to v tomto ifu. (Jinde si to netroufám řadit)
|
||||
qs = qs.order_by("nadproblem", "kod", "nazev")
|
||||
qs = list(filter(lambda problem: problem.hlavni_problem.id == nadproblem_id, qs))
|
||||
zelvuska marked this conversation as resolved
Outdated
|
||||
return qs
|
||||
|
||||
class ProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||
|
|
|
@ -437,7 +437,7 @@
|
|||
"insitetree": true,
|
||||
"parent": 21,
|
||||
"sort_order": 36,
|
||||
"title": "Poslat řešení",
|
||||
"title": "Nahrát řešení",
|
||||
"tree": 1,
|
||||
"url": "seminar_nahraj_reseni",
|
||||
"urlaspattern": true
|
||||
|
@ -719,7 +719,7 @@
|
|||
"insitetree": true,
|
||||
"parent": 21,
|
||||
"sort_order": 36,
|
||||
"title": "Nahrát řešení",
|
||||
"title": "Vložit řešení",
|
||||
"tree": 1,
|
||||
"url": "seminar_vloz_reseni",
|
||||
"urlaspattern": true
|
||||
|
@ -1026,6 +1026,36 @@
|
|||
"model": "sitetree.treeitem",
|
||||
"pk": 51
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"access_guest": false,
|
||||
"access_loggedin": false,
|
||||
"access_perm_type": 1,
|
||||
"access_permissions": [
|
||||
[
|
||||
"resitel",
|
||||
"auth",
|
||||
"user"
|
||||
]
|
||||
],
|
||||
"access_restricted": true,
|
||||
"alias": null,
|
||||
"description": "",
|
||||
"hidden": false,
|
||||
"hint": "",
|
||||
"inbreadcrumbs": true,
|
||||
"inmenu": true,
|
||||
"insitetree": true,
|
||||
"parent": 23,
|
||||
"sort_order": 52,
|
||||
"title": "Nahrát řešení k nadproblému {{nadproblem_id}}",
|
||||
zelvuska marked this conversation as resolved
ledoian
commented
Zatím jsem neviděl realizaci, ale pojem „nadproblém“ bych nepsal nikam, kde ho můžou vidět řešitelé. Přijde mi dost matoucí i pro orgy, ale ti se aspoň mají koho zeptat :-) Zatím jsem neviděl realizaci, ale pojem „nadproblém“ bych nepsal nikam, kde ho můžou vidět řešitelé. Přijde mi dost matoucí i pro orgy, ale ti se aspoň mají koho zeptat :-)
zelvuska
commented
Tohle políčkoje skryté, takže ho vidí jen pokud budou prohlížet html. To mi přijde dostatečně „ne můžou vidět“. Tohle políčkoje skryté, takže ho vidí jen pokud budou prohlížet html. To mi přijde dostatečně „ne můžou vidět“.
|
||||
"tree": 1,
|
||||
"url": "seminar_nahraj_reseni nadproblem_id",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
"pk": 52
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"access_guest": false,
|
||||
|
@ -1041,13 +1071,13 @@
|
|||
"inmenu": true,
|
||||
"insitetree": true,
|
||||
"parent": 28,
|
||||
"sort_order": 52,
|
||||
"sort_order": 53,
|
||||
"title": "Přidat PDF",
|
||||
"tree": 1,
|
||||
"url": "/admin/korektury/korekturovanepdf/add/",
|
||||
"urlaspattern": false
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
"pk": 52
|
||||
"pk": 53
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -28,7 +28,7 @@ Generuje se za pomocí::
|
|||
|
||||
nebo (v případě meníčka)::
|
||||
|
||||
./manage.py dumpdata sitetree --natrual-foreign > data/sitetree_new.json
|
||||
./manage.py dumpdata sitetree --natural-foreign > data/sitetree_new.json
|
||||
./fix_json.py data/sitetree_new.json data/sitetree.json
|
||||
|
||||
deploy_v2
|
||||
|
|
|
@ -1260,3 +1260,22 @@ label[for=id_skola] {
|
|||
.bodovani>input {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
|
||||
/* Select2 používaný hlavně multiple selectem. Přidání checkboxů a změna barvy. */
|
||||
/* Podle https://stackoverflow.com/a/48290544 */
|
||||
/* U autocomplete.ModelSelect2Multiple vyžaduje 'data-dropdown-css-class': 's2m-se-zaskrtavatky' */
|
||||
.s2m-se-zaskrtavatky .select2-results__option[aria-selected=true]:before {
|
||||
content: '☑ ';
|
||||
padding: 0 0 0 8px;
|
||||
}
|
||||
|
||||
.s2m-se-zaskrtavatky .select2-results__option[aria-selected=false]:before {
|
||||
content: '◻ ';
|
||||
padding: 0 0 0 8px;
|
||||
}
|
||||
|
||||
/* Oranžové zvýraznění v Select2 */
|
||||
.select2-results__option--highlighted {
|
||||
background-color: #e84e10 !important;
|
||||
zelvuska marked this conversation as resolved
ledoian
commented
Přemýšlím, kde všude jsou Select2Multiple, jestli je to nerozbíjí. Ale snad ne. Přemýšlím, kde všude jsou Select2Multiple, jestli je to nerozbíjí. Ale snad ne.
zelvuska
commented
Tak tohle je jen tam, kam jsme explicitně přidali Tak tohle je jen tam, kam jsme explicitně přidali `'data-dropdown-css-class': 'select2multiple'`. Spíš si teď naopak říkám, že ta barva možná měla být bez toho `.select2multiple`
ledoian
commented
Měl jsem na mysli obecně všechny Select2Multiple, nemělo se to týkat jen barvy… Barva asi může být všude (v Adminu tyhle styly stejně nepoužíváme, ne?) Měl jsem na mysli obecně všechny Select2Multiple, nemělo se to týkat jen barvy…
Barva asi může být všude (v Adminu tyhle styly stejně nepoužíváme, ne?)
zelvuska
commented
No ale tohle neovlivňuje všechny selecty. Tohle ovlivňuje jen ty, kterým tu třídu předhodíme… No ale tohle neovlivňuje všechny selecty. Tohle ovlivňuje jen ty, kterým tu třídu předhodíme…
zelvuska
commented
A barvu bych tedy dal všude… A barvu bych tedy dal všude…
ledoian
commented
Třída Možná Třída `.select2multiple` je naše? Tak bych ji tím pádem pojmenoval nějak aspoň parciálně česky, myslel jsem, že hackujeme nějakou vestavěnou. (Uznávám, nečetl jsem kód moc pozorně…)
Možná `.s2m-se-zaskrtavatky`?
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ Obsahuje vše, co se týká odevzdávání (+ nahrávání) a opravování řeš
|
|||
Slovníček:
|
||||
Moje řešení = Přehled řešení = Řešení, která odevzdal aktuálního uživatel sám.
|
||||
Došlá řešení = Tabulka + seznam + detail + ... = Řešení, která poslal někdo jiný.
|
||||
Poslat řešení = Odevdat mé řešení. (Tj. řešení se vztahem k aktuálnímu uživateli.)
|
||||
Nahrát řešení = Nahrání řešení bez vztahu k aktuálnímu uživateli.
|
||||
Nahrát řešení = Odevdat mé řešení. (Tj. řešení se vztahem k aktuálnímu uživateli.)
|
||||
Vlož řešení = Vložit řešení bez vztahu k aktuálnímu uživateli.
|
||||
|
||||
TODO: Místo vložit řešení v nahrávání a posílání řešení dát něco jiného?
|
||||
"""
|
||||
"""
|
||||
|
|
|
@ -29,6 +29,8 @@ class PosliReseniForm(forms.Form):
|
|||
attrs={
|
||||
'data-placeholder--id': '-1',
|
||||
'data-placeholder--text': '---',
|
||||
'data-close-on-select': 'false',
|
||||
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||
'data-allow-clear': 'true'
|
||||
},
|
||||
),
|
||||
|
@ -43,6 +45,8 @@ class PosliReseniForm(forms.Form):
|
|||
url='autocomplete_resitel',
|
||||
attrs = {'data-placeholder--id': '-1',
|
||||
'data-placeholder--text' : '---',
|
||||
'data-close-on-select': 'false',
|
||||
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||
'data-allow-clear': 'true'})
|
||||
)
|
||||
|
||||
|
@ -62,12 +66,6 @@ class PosliReseniForm(forms.Form):
|
|||
#poznamka = models.TextField('neveřejná poznámka', blank=True,
|
||||
# help_text='Neveřejná poznámka k řešení (plain text)')
|
||||
|
||||
#TODO body do cisla
|
||||
#TODO prilohy
|
||||
|
||||
##def __init__(self, *args, **kwargs):
|
||||
## super().__init__(*args, **kwargs)
|
||||
## #self.fields['favorite_color'] = forms.ChoiceField(choices=[(color.id, color.name) for color in Resitel.objects.all()])
|
||||
|
||||
class NahrajReseniForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
@ -80,23 +78,40 @@ class NahrajReseniForm(forms.ModelForm):
|
|||
url='autocomplete_problem_odevzdatelny',
|
||||
attrs = {'data-placeholder--id': '-1',
|
||||
'data-placeholder--text' : '---',
|
||||
'data-close-on-select': 'false',
|
||||
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||
'data-allow-clear': 'true'},
|
||||
forward=["nadproblem_id"],
|
||||
),
|
||||
'resitele':
|
||||
autocomplete.ModelSelect2Multiple(
|
||||
url='autocomplete_resitel_public',
|
||||
attrs = {'data-placeholder--id': '-1',
|
||||
'data-placeholder--text' : '---',
|
||||
'data-close-on-select': 'false',
|
||||
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||
'data-allow-clear': 'true'},
|
||||
)
|
||||
}
|
||||
|
||||
nadproblem_id = forms.IntegerField(required=False, disabled=True, widget=forms.HiddenInput())
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# FIXME Z nějakého důvodu se do této třídy dostaneme i bez resitele
|
||||
if 'resitele' in self.fields:
|
||||
# FIXME Mnohem hezčí by to bylo u definice resitele výše, ale nepodařilo se mi to.
|
||||
self.fields['resitele'].required = False
|
||||
self.fields['resitele'].label = "Další autoři"
|
||||
if 'problem' in self.fields:
|
||||
self.fields['problem'].label = "Všechny řešené problémy"
|
||||
|
||||
def clean_problem(self):
|
||||
problem = self.cleaned_data.get('problem')
|
||||
for p in problem:
|
||||
if p.stav != m.Problem.STAV_ZADANY:
|
||||
raise forms.ValidationError("Problém " + str(p) + " již nelze řešit!")
|
||||
return problem
|
||||
|
||||
ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni,
|
||||
form = NahrajReseniForm,
|
||||
|
|
|
@ -7,19 +7,20 @@
|
|||
{% block content %}
|
||||
<h1>
|
||||
{% block nadpis1a %}
|
||||
Vložit řešení
|
||||
Nahrát řešení
|
||||
{% endblock %}
|
||||
</h1>
|
||||
|
||||
<p style="text-align: justify">Když řešení různých témátek vložíš každé zvlášť, lépe se v nich vyznáme a třeba ti je i rychleji opravíme.</p>
|
||||
|
||||
<p>Pokud řešíte ve více lidech, je <strong>nutné</strong> přidat tyto lidi jako „Autory řešení“. V tomto poli se vyhledává podle přezdívek, které si lze nastavit v „Osobní údaje“. Sebe vyplňovat nemusíte a za skupinu odevzdávejte pouze <strong>jednou</strong> (ne každý sám).</p>
|
||||
|
||||
<form enctype="multipart/form-data" action="{% url 'seminar_nahraj_reseni' %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
||||
<form enctype="multipart/form-data" action="{% url 'seminar_nahraj_reseni' nadproblem_id %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
||||
{% csrf_token %}
|
||||
<table class='form' id="reseni">
|
||||
<table class='form'>
|
||||
<tr>
|
||||
<td><label class="field-label field-required" for="tema">Téma:</label></td>
|
||||
<td><input id="tema" disabled="" type="text" value="{{ nadproblem }}"></td>
|
||||
</tr>
|
||||
|
||||
{% with field=form.problem %}
|
||||
<tr>
|
||||
{% for field in form %}
|
||||
<td>
|
||||
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
|
||||
{{ field.label }}:
|
||||
|
@ -28,15 +29,54 @@
|
|||
<td>
|
||||
{{ field }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
{% if field.errors %}
|
||||
<tr>
|
||||
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% endwith %}
|
||||
</table>
|
||||
|
||||
{% for field in form.hidden_fields %}
|
||||
{{ field }}
|
||||
{% endfor %}
|
||||
|
||||
<hr>
|
||||
<h4>Spolupráce s dalšími řešiteli</h4>
|
||||
|
||||
<p>Pokud řešíte ve více lidech, je <strong>potřeba</strong> přidat tyto lidi jako „Další autory“. V tomto poli se vyhledává podle přezdívek, které si lze nastavit v „Osobních údajích“. Sebe vyplňovat nemusíte a za skupinu odevzdávejte pouze <strong>jednou</strong> (ne každý sám).</p>
|
||||
zelvuska marked this conversation as resolved
Outdated
ledoian
commented
„Další auto__ry__“ „Další auto__ry__“
ledoian
commented
„Osobní__ch__ údaj__ích__“ „Osobní__ch__ údaj__ích__“
|
||||
|
||||
<table class='form'>
|
||||
{% with field=form.resitele %}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
|
||||
{{ field.label }}:
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
{{ field }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if field.errors %}
|
||||
<tr>
|
||||
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% endwith %}
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
{% include "odevzdavatko/prilohy.html" %}
|
||||
|
||||
{{form.non_field_errors}}
|
||||
|
||||
<hr>
|
||||
<h4>Odevzdat řešení</h4>
|
||||
<input type="submit" value="Odevzdat">
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<h1>
|
||||
{% block nadpis1a %}
|
||||
Nahrát řešení
|
||||
{% endblock %}
|
||||
</h1>
|
||||
|
||||
<h4>Seznam témat k odevzdání</h4>
|
||||
|
||||
<ul>
|
||||
{% for problem in object_list %}
|
||||
<li><a href="{% url 'seminar_nahraj_reseni' problem.id %}">{{ problem }}</a></li>
|
||||
{% empty %}
|
||||
<li>Nelze nic odevzdávat.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
<h4>Soubory s řešením</h4>
|
||||
|
||||
<p style="text-align: justify">Maximální součet velikostí příloh je cca 49 MB. Pokud je to možné a dává to smysl, pošli nám prosím své řešení ve formátu PDF, ostatní formáty nemusíme umět otevřít.</p>
|
||||
<p style="text-align: justify">Pokud svůj soubor rozumně pojmenuješ, urychlíš opravování a předejdeš tomu, že si nějakého tvého řešení nevšimneme. Například z <code>img_250921_101205.pdf</code> nepoznáme, kterou úlohu jsi odevzdal, zato <code>uloha_3.pdf</code> nebo <code>tema_1.pdf</code>, to už je něco jiného. Případně můžeš využít i poznámku řešitele.</p>
|
||||
<p style="text-align: justify">Pokud je to možné a dává to smysl (tj. není to třeba kód nebo doprovodný obrázek), pošli nám prosím své řešení ve formátu <strong>PDF</strong>, ostatní formáty nemusíme umět otevřít.</p>
|
||||
<p style="text-align: justify">Pokud svůj soubor <strong>rozumně pojmenuješ</strong>, urychlíš opravování a předejdeš tomu, že si nějakého tvého řešení nevšimneme. Například z <code>img_250921_101205.pdf</code> nepoznáme, kterou úlohu jsi odevzdal, zato <code>uloha_3.pdf</code> nebo <code>tema_1.pdf</code>, to už je něco jiného. Případně můžeš využít i poznámku řešitele.</p>
|
||||
<p style="text-align: justify">Maximální součet velikostí příloh je cca <strong>49 MB</strong>.</p>
|
||||
|
||||
<div id="form_set">
|
||||
{% for form in prilohy.forms %}
|
||||
|
|
|
@ -19,8 +19,9 @@ from seminar.utils import org_required, resitel_required, viewMethodSwitch, \
|
|||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('org/add_solution', org_required(views.PosliReseniView.as_view()), name='seminar_vloz_reseni'),
|
||||
path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
|
||||
path('org/add_solution', org_required(views.VlozReseniView.as_view()), name='seminar_vloz_reseni'),
|
||||
path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniRozcestnikTematekView.as_view()), name='seminar_nahraj_reseni'),
|
||||
path('resitel/nahraj_reseni/<int:nadproblem_id>/', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
|
||||
path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'),
|
||||
|
||||
path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||
|
|
|
@ -367,8 +367,8 @@ class SeznamAktualnichReseniView(SeznamReseniView):
|
|||
return qs
|
||||
|
||||
|
||||
class PosliReseniView(LoginRequiredMixin, FormView):
|
||||
template_name = 'odevzdavatko/posli_reseni.html'
|
||||
class VlozReseniView(LoginRequiredMixin, FormView):
|
||||
template_name = 'odevzdavatko/vloz_reseni.html'
|
||||
form_class = f.PosliReseniForm
|
||||
|
||||
def form_valid(self, form):
|
||||
|
@ -399,12 +399,27 @@ class PosliReseniView(LoginRequiredMixin, FormView):
|
|||
return data
|
||||
|
||||
|
||||
class NahrajReseniRozcestnikTematekView(LoginRequiredMixin, ListView):
|
||||
zelvuska marked this conversation as resolved
Outdated
ledoian
commented
Možná lepší pojmenovat ve stylu Možná lepší pojmenovat ve stylu `NahrajReseniRozcestnikTematekView` nebo `NahrajReseniVyberHlavnihoProblemuView`, nebo dokonce `OdevzdavatkoVyberTematkaView`? Tady se žádné řešení nenahrává, a technicky to ani není nadproblém, ale hlavní problém (bo i nadproblém může mít nadproblém, teoreticky).
|
||||
model = m.Problem
|
||||
template_name = 'odevzdavatko/nahraj_reseni_nadproblem.html'
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().filter(stav=m.Problem.STAV_ZADANY, nadproblem__isnull=True)
|
||||
|
||||
|
||||
class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||
model = m.Reseni
|
||||
template_name = 'odevzdavatko/nahraj_reseni.html'
|
||||
form_class = f.NahrajReseniForm
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
# Zaříznutí nezadaných problémů
|
||||
nadproblem_id = self.kwargs["nadproblem_id"]
|
||||
self.nadproblem = get_object_or_404(m.Problem, id=nadproblem_id)
|
||||
if self.nadproblem.stav != "zadany":
|
||||
raise PermissionDenied()
|
||||
|
||||
|
||||
# Zaříznutí starých řešitelů:
|
||||
# FIXME: Je to tady dost naprasené, mělo by to asi být jinde…
|
||||
zelvuska marked this conversation as resolved
ledoian
commented
Tohle FIXME se vztahuje IMHO i na zaříznutí nezadaných problémů… Teď bych to asi neřešil, ale možná ho dává smysl přesunout výš… ( Tohle FIXME se vztahuje IMHO i na zaříznutí nezadaných problémů… Teď bych to asi neřešil, ale možná ho dává smysl přesunout výš…
(`.get()` není funkce, která by měla za úkol řešit jakákoliv práva, takže by to sémanticky mělo být někam vyčleněno. Ale pořád nemám rozmyšleno / nastudováno kam…)
|
||||
osoba = m.Osoba.objects.get(user=self.request.user)
|
||||
|
@ -417,12 +432,23 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
|||
})
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_initial(self):
|
||||
nadproblem_id = self.nadproblem.id
|
||||
zelvuska marked this conversation as resolved
Outdated
ledoian
commented
Nechceme ten nadproblém rovnou uložit jako Problém do Nechceme ten nadproblém rovnou uložit jako Problém do `self`? Na první čtení jsem tady měl pocit, že když mi někdo předhodí blbost do URL, že někde něco musí spadnout…
ledoian
commented
Užitečnost uložení přímo Problemu je i v tom, že pak podproblémy můžeš určit jako Disclaimer: kód haluzím, nechtělo se mi to hledat přesně :-) Užitečnost uložení přímo Problemu je i v tom, že pak podproblémy můžeš určit jako `nadproblem.podproblemy.count() > 0` o kus níž (v rychlosti nevidím, jestli related managers umí i `.exists()`)
Disclaimer: kód haluzím, nechtělo se mi to hledat přesně :-)
|
||||
return {
|
||||
"nadproblem_id": nadproblem_id,
|
||||
"problem": [] if self.nadproblem.podproblem.filter(stav=m.Problem.STAV_ZADANY).exists() else nadproblem_id
|
||||
zelvuska marked this conversation as resolved
Outdated
ledoian
commented
Uh, tohle dělá co? Ať už to dělá cokoliv, tak to z toho není zřejmé. Zejména není samozřejmé, kdy je Po chvíli čtení: když to má podproblémy, tak nic nenabízíme, jinak nabídneme tu věc přímo. Buď bych za ten QuerySet aspoň přidal
Uh, tohle dělá co? Ať už to dělá cokoliv, tak to z toho není zřejmé. Zejména není samozřejmé, kdy je `QuerySet` falsey.
Po chvíli čtení: když to má podproblémy, tak nic nenabízíme, jinak nabídneme tu věc přímo.
Buď bych za ten QuerySet aspoň přidal `.exists()` ([Dokumentace](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#exists)), nebo úplně vyčlenil:
```python3
...
ma_podproblemy = QuerySet….exists()
...
return {
...
"problem": [] if ma_podproblemy else nadproblem_id,
...
}
```
|
||||
|
||||
}
|
||||
|
||||
def get_context_data(self,**kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
if self.request.POST:
|
||||
data['prilohy'] = f.ReseniSPrilohamiFormSet(self.request.POST,self.request.FILES)
|
||||
else:
|
||||
data['prilohy'] = f.ReseniSPrilohamiFormSet()
|
||||
|
||||
data["nadproblem_id"] = self.nadproblem.id
|
||||
data["nadproblem"] = get_object_or_404(m.Problem, id=self.nadproblem.id)
|
||||
return data
|
||||
|
||||
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
|
||||
|
@ -474,4 +500,8 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
|||
to=list(prijemci),
|
||||
).send()
|
||||
|
||||
return formularOKView(self.request, text='Řešení úspěšně odevzdáno')
|
||||
return formularOKView(
|
||||
self.request,
|
||||
text='Řešení úspěšně odevzdáno',
|
||||
dalsi_odkazy=[("Odevzdat další řešení", reverse("seminar_nahraj_reseni"))],
|
||||
)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<a href="{% url 'logout' %}">Odhlásit se</a><br>
|
||||
<a href="{% url 'seminar_resitel_edit' %}">Upravit údaje</a><br>
|
||||
<a href="{% url 'seminar_nahraj_reseni' %}">Poslat řešení</a><br>
|
||||
<a href="{% url 'seminar_nahraj_reseni' %}">Nahrát řešení</a><br>
|
||||
zelvuska marked this conversation as resolved
Outdated
ledoian
commented
„Nahrát “ bez í asi „Nahrát “ bez í asi
|
||||
<a href="{% url 'seminar_resitel_odevzdana_reseni' %}">Již odevzdaná řešení</a><br>
|
||||
|
||||
|
||||
|
|
|
@ -173,7 +173,11 @@ def resitelEditView(request):
|
|||
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
|
||||
resitel_edit.save()
|
||||
osoba_edit.save()
|
||||
return formularOKView(request, text=f'Údaje byly úspěšně uloženy. <a href="{reverse("profil")}">Vrátit se zpět na profil.</a>')
|
||||
return formularOKView(
|
||||
request,
|
||||
text='Údaje byly úspěšně uloženy.',
|
||||
dalsi_odkazy=[("Vrátit se zpět na profil", reverse("profil"))],
|
||||
)
|
||||
|
||||
return render(request, 'personalni/udaje/edit.html', {'form': form})
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ from django.conf import settings
|
|||
import unicodedata
|
||||
import logging
|
||||
import time
|
||||
from collections.abc import Sequence
|
||||
|
||||
from seminar.utils import aktivniResitele
|
||||
|
||||
|
@ -677,9 +678,9 @@ def StavDatabazeView(request):
|
|||
|
||||
|
||||
# Interní, nemá se nikdy objevit v urls (jinak to účastníci vytrolí)
|
||||
def formularOKView(request, text=''):
|
||||
def formularOKView(request, text='', dalsi_odkazy: Sequence[tuple[str, str]] = ()):
|
||||
zelvuska marked this conversation as resolved
Outdated
ledoian
commented
V zájmu bezpečnosti bych možná spíš než Ne že by někdo aktuálně moc kontroloval typy, ale třeba jednou bude :-D V zájmu bezpečnosti bych možná spíš než `Iterable` použil `Sequence`, tj. věc, kde mají věci dané pořadí (množina a slovník jsou Iterable, ale ne Sequence; asi chceme, aby to pořadí, co tady napíšeme, se dodrželo.)
Ne že by někdo aktuálně moc kontroloval typy, ale třeba jednou bude :-D
|
||||
template_name = 'seminar/formular_ok.html'
|
||||
odkazy = [
|
||||
odkazy = list(dalsi_odkazy) + [
|
||||
# (Text, odkaz)
|
||||
('Vrátit se na titulní stránku', reverse('titulni_strana')),
|
||||
('Zobrazit aktuální zadání', reverse('seminar_aktualni_zadani')),
|
||||
|
|
Tohle je možná lepší psát nějakým filterem (ať už QuerySetovým, nebo čistě pythonovým
list(filter(lambda: ..., qs))
– není to úprava dat, jen filtrování, tak ať je to názornější.(A přirozeně, pokud by to šlo tím QuerySetovým, tak to může být rychlejší, protože databáze není napsaná v Pythonu :-))
No QuerySetovým to nejde, protože hlavni_problem není databázová věc… Nebo to jde nějak obejít?
Já si úplně nepamatuju, jestli to je nebo není DB věc :-) Takže holt klasickým pythoním filterem.