Hlasování o přednáškách pomocí formsetů…
This commit is contained in:
		
							parent
							
								
									e12b614e1c
								
							
						
					
					
						commit
						fbd75d2f72
					
				
					 6 changed files with 122 additions and 58 deletions
				
			
		|  | @ -57,6 +57,7 @@ DOBA_ODHLASENI_PRI_ZASKRTNUTI_NEODHLASOVAT = 365 * 24 * 3600  # rok | ||||||
| CSRF_FAILURE_VIEW = 'various.views.csrf.csrf_error' | CSRF_FAILURE_VIEW = 'various.views.csrf.csrf_error' | ||||||
| 
 | 
 | ||||||
| # Modules configuration | # Modules configuration | ||||||
|  | FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer" | ||||||
| 
 | 
 | ||||||
| AUTHENTICATION_BACKENDS = ( | AUTHENTICATION_BACKENDS = ( | ||||||
| 	'django.contrib.auth.backends.ModelBackend', | 	'django.contrib.auth.backends.ModelBackend', | ||||||
|  |  | ||||||
|  | @ -100,7 +100,7 @@ admin.site.register(Prednaska, PrednaskaAdmin) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ZnalostAdmin(PrednaskaAdmin): # Trochu hack, ať nemusím vypisovat všechno znovu | class ZnalostAdmin(PrednaskaAdmin): # Trochu hack, ať nemusím vypisovat všechno znovu | ||||||
| 	list_display = [] | 	list_display = ("__str__",) | ||||||
| 	list_filter = [] | 	list_filter = () | ||||||
| 
 | 
 | ||||||
| admin.site.register(Znalost, ZnalostAdmin) | admin.site.register(Znalost, ZnalostAdmin) | ||||||
|  |  | ||||||
|  | @ -1 +1,15 @@ | ||||||
| from django import forms | from django import forms | ||||||
|  | 
 | ||||||
|  | from .models import Hlasovani, HlasovaniOZnalostech | ||||||
|  | 
 | ||||||
|  | class HlasovaniPrednaskaForm(forms.Form): | ||||||
|  | 	prednaska_id = forms.IntegerField(widget=forms.HiddenInput) | ||||||
|  | 	body = forms.ChoiceField(label=False, widget=forms.RadioSelect, choices=Hlasovani.Body.choices, initial=Hlasovani.Body.JEDNO) | ||||||
|  | 
 | ||||||
|  | HlasovaniPrednaskaFormSet = forms.formset_factory(HlasovaniPrednaskaForm, extra=0) | ||||||
|  | 
 | ||||||
|  | class HlasovaniZnalostiForm(forms.Form): | ||||||
|  | 	znalost_id = forms.IntegerField(widget=forms.HiddenInput) | ||||||
|  | 	odpoved = forms.ChoiceField(label=False, widget=forms.RadioSelect, choices=HlasovaniOZnalostech.Odpoved.choices) | ||||||
|  | 
 | ||||||
|  | HlasovaniZnalostiFormSet = forms.formset_factory(HlasovaniZnalostiForm, extra=0) | ||||||
|  |  | ||||||
|  | @ -64,6 +64,10 @@ class Hlasovani(models.Model): | ||||||
| 	id = models.AutoField(primary_key=True) | 	id = models.AutoField(primary_key=True) | ||||||
| 	prednaska = models.ForeignKey(Prednaska, on_delete=models.CASCADE) | 	prednaska = models.ForeignKey(Prednaska, on_delete=models.CASCADE) | ||||||
| 	body = models.IntegerField("Body", default=Body.JEDNO, choices=Body.choices) | 	body = models.IntegerField("Body", default=Body.JEDNO, choices=Body.choices) | ||||||
|  | 
 | ||||||
|  | 	# (přechod z jména na objekt Osoby nějak kape na tom, | ||||||
|  | 	# že všechna předchozí hlasování zde mají náhodný string…) | ||||||
|  | 	# TODO Změnit to na Osobu | ||||||
| 	ucastnik = models.CharField("Účastník", max_length=100) | 	ucastnik = models.CharField("Účastník", max_length=100) | ||||||
| 	seznam = models.ForeignKey(Seznam, null=True, on_delete=models.SET_NULL) | 	seznam = models.ForeignKey(Seznam, null=True, on_delete=models.SET_NULL) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,36 +5,36 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| {% block content %} | {% block content %} | ||||||
| <h1> | <h1>{% block nadpis1a %}Hlasování o přednáškách{% endblock %}</h1> | ||||||
| {% block nadpis1a %}Hlasování o přednáškách{% endblock %} |  | ||||||
| </h1> |  | ||||||
| 
 |  | ||||||
| <p> |  | ||||||
| Jak moc by ses chtěl(a) zúčastnit následujících přednášek? |  | ||||||
| <br> |  | ||||||
| <span style="font-size: 75%">Obtížnost 1 je nejlehčí, 3 nejtěžší.</span> |  | ||||||
| </p> |  | ||||||
| 
 | 
 | ||||||
| <form enctype="multipart/form-data" action="." method="post"> | <form enctype="multipart/form-data" action="." method="post"> | ||||||
|   {% csrf_token %} |   {% csrf_token %} | ||||||
|   <table> | 
 | ||||||
|     {% for p, h in prednasky %} | <h3>Jak moc by ses chtěl(a) zúčastnit následujících přednášek?</h3> | ||||||
|     <tr><td><label>{{p.org}}: <span style="font-size: 175%">{{p.nazev}}</span></label></td></tr> | <p>Obtížnost 1 je nejlehčí, 3 nejtěžší.</p> | ||||||
|     <tr><td><p><i>{{p.anotace}}</i></p></td></tr> |   {{ form_set_prednasky.management_form }} | ||||||
|     <tr><td><label>Obor: </label> {{p.obor}}</td></tr> |   {% for f, p in formy_a_prednasky %} | ||||||
|     <tr><td><label>Obtížnost: </label> {{p.obtiznost}}</td>   </tr> |     <h4>{{p.nazev}} ({{p.org}})</h4> | ||||||
|     {% if p.klicova %}<tr><td><label>Klíčová slova: </label> {{p.klicova}}</td></tr>{% endif%} |     <p class="textprednasky">{{p.anotace}}</p> | ||||||
|     <tr><td>Hodnocení: |     <label>Obor: </label> {{p.obor}}<br> | ||||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="-1" {% if h == -1 %} CHECKED="checked" {% endif %} > rozhodně nechci |     <label>Obtížnost: </label> {{p.obtiznost}}<br> | ||||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="0" {% if h == 0 %} CHECKED="checked" {% endif %}> je mi to jedno |     {% if p.klicova %}<label>Klíčová slova: </label> {{p.klicova}}<br>{% endif%} | ||||||
|         <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="1" {% if h == 1 %} CHECKED="checked" {% endif %}> rozhodně chci |     <br> | ||||||
|     </td></tr> |     {{ f }} | ||||||
|     <tr><td> </td></tr> |     <br> | ||||||
|     {% empty %} |   {% empty %} | ||||||
|       Nejsou žádné přednášky o kterých by šlo hlasovat. |     Nejsou žádné přednášky o kterých by šlo hlasovat. | ||||||
|     {% endfor %} |   {% endfor %} | ||||||
|     <tr><td><input name="odeslat" type="submit" value="Odeslat"></td><tr> | 
 | ||||||
|   </table> |   {{ form_set_znalosti.management_form }} | ||||||
|  |   {% for f, z in formy_a_znalosti %} | ||||||
|  |     {% if forloop.first %}<hr/><h3>Jak moc znáš následující?</h3>{% endif %} | ||||||
|  |     <h4>{{z.nazev}}</h4> | ||||||
|  |     <p class="textznalosti">{{z.text}}</p> | ||||||
|  |     {{ f }} | ||||||
|  |     <br> | ||||||
|  |   {% endfor %} | ||||||
|  |   <input type="submit" value="Odeslat"/> | ||||||
| </form> | </form> | ||||||
|     |     | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  |  | ||||||
|  | @ -1,19 +1,25 @@ | ||||||
| import http | import http | ||||||
|  | import logging | ||||||
| 
 | 
 | ||||||
| from django.shortcuts import render, get_object_or_404 | from django.shortcuts import render, get_object_or_404 | ||||||
| from django.views import generic | from django.views import generic | ||||||
| from django.shortcuts import HttpResponseRedirect | from django.shortcuts import HttpResponseRedirect | ||||||
| from django.core.exceptions import ObjectDoesNotExist | from django.core.exceptions import ObjectDoesNotExist | ||||||
| from django.db.models import Sum | from django.db import transaction | ||||||
| from django.forms import Form |  | ||||||
| 
 | 
 | ||||||
| from various.views.pomocne import formularOKView | from various.views.pomocne import formularOKView | ||||||
|  | from .forms import HlasovaniPrednaskaFormSet, HlasovaniZnalostiFormSet | ||||||
| 
 | 
 | ||||||
| from various.models import Nastaveni | from various.models import Nastaveni | ||||||
| from prednasky.models import Prednaska, Hlasovani, Seznam | from prednasky.models import Prednaska, Hlasovani, Znalost, HlasovaniOZnalostech, Seznam | ||||||
| from soustredeni.models import Soustredeni | from soustredeni.models import Soustredeni | ||||||
| from personalni.models import Osoba | from personalni.models import Osoba | ||||||
| 
 | 
 | ||||||
|  | PREDNASKY_PREFIX = "prednasky" | ||||||
|  | ZNALOSTI_PREFIX = "znalosti" | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
| def newPrednaska(request): | def newPrednaska(request): | ||||||
| 	# hlasovani se vztahuje k nejnovejsimu soustredeni | 	# hlasovani se vztahuje k nejnovejsimu soustredeni | ||||||
| 	sous = Nastaveni.get_solo().aktualni_sous | 	sous = Nastaveni.get_solo().aktualni_sous | ||||||
|  | @ -23,43 +29,82 @@ def newPrednaska(request): | ||||||
| 			'title': "Nelze hlasovat", | 			'title': "Nelze hlasovat", | ||||||
| 			'text': "Není žádný seznam přednášek, o kterém by se dalo hlasovat.", | 			'text': "Není žádný seznam přednášek, o kterém by se dalo hlasovat.", | ||||||
| 		}, status=http.HTTPStatus.NOT_FOUND) | 		}, status=http.HTTPStatus.NOT_FOUND) | ||||||
|  | 
 | ||||||
| 	osoba = Osoba.objects.filter(user=request.user).first() | 	osoba = Osoba.objects.filter(user=request.user).first() | ||||||
| 	ucastnik = osoba.plne_jmeno() + ' ' + str(osoba.id) | 	ucastnik = osoba.plne_jmeno() + ' ' + str(osoba.id) | ||||||
| 	# obsluha formulare | 
 | ||||||
| 	if request.method == 'POST': | 	if request.method == 'POST': | ||||||
| 		form = Form(request.POST, request.FILES) | 		form_set_prednasky = HlasovaniPrednaskaFormSet(request.POST, prefix=PREDNASKY_PREFIX) | ||||||
| 		if form.is_valid(): | 		form_set_znalosti = HlasovaniZnalostiFormSet(request.POST, prefix=ZNALOSTI_PREFIX) | ||||||
| 			# id z důvodu duplicitních jmen (přechod z jména na objekt Osoby nějak kape na tom, |  | ||||||
| 			# že všechna předchozí hlasování zde mají náhodný string…) |  | ||||||
| 			# TODO Změnit to na Osobu |  | ||||||
| 
 | 
 | ||||||
| 			# TODO v následujících řádcích je zbytečně mnoho dotazů na QuerySet (pokud účastník hlasoval, hlasoval u všech) | 		if form_set_prednasky.is_valid() and form_set_znalosti.is_valid(): | ||||||
| 			for i in request.POST: | 			with transaction.atomic(): | ||||||
| 				if i[0] == 'q': | 				seznam.hlasovani_set.filter(ucastnik=ucastnik).delete() | ||||||
| 					prednaska = Prednaska.objects.filter(pk=int(i[1:]))[0] | 				seznam.hlasovanioznalostech_set.filter(ucastnik=osoba).delete() | ||||||
| 					hlasovani = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first() | 
 | ||||||
| 					if not hlasovani: | 				for form in form_set_prednasky: | ||||||
| 						hlasovani = Hlasovani() | 					prednaska_id = form.cleaned_data['prednaska_id'] | ||||||
| 						hlasovani.prednaska = prednaska | 					prednaska = Prednaska.objects.filter(id=prednaska_id).first() | ||||||
| 						hlasovani.ucastnik = ucastnik | 					if prednaska is None: | ||||||
| 						hlasovani.seznam = seznam | 						logger.error(f"Účastník {ucastnik} hodnotil neexistující přednášku {prednaska_id} číslem {form.cleaned_data['body']}") | ||||||
| 					hlasovani.body = int(request.POST[i]) | 						continue | ||||||
| 					hlasovani.save() | 
 | ||||||
|  | 					Hlasovani.objects.create( | ||||||
|  | 						prednaska=prednaska, | ||||||
|  | 						body=form.cleaned_data['body'], | ||||||
|  | 						ucastnik=ucastnik, | ||||||
|  | 						seznam=seznam, | ||||||
|  | 					) | ||||||
|  | 
 | ||||||
|  | 				for form in form_set_znalosti: | ||||||
|  | 					znalost_id = form.cleaned_data['znalost_id'] | ||||||
|  | 					znalost = Znalost.objects.filter(id=znalost_id).first() | ||||||
|  | 					if znalost is None: | ||||||
|  | 						logger.error(f"Účastník {ucastnik} hodnotil neexistující znalost {znalost_id} číslem {form.cleaned_data['odpoved']}") | ||||||
|  | 						continue | ||||||
|  | 
 | ||||||
|  | 					HlasovaniOZnalostech.objects.create( | ||||||
|  | 						odpoved=form.cleaned_data['odpoved'], | ||||||
|  | 						znalost=znalost, | ||||||
|  | 						ucastnik=osoba, | ||||||
|  | 						seznam=seznam, | ||||||
|  | 					) | ||||||
| 
 | 
 | ||||||
| 			# presmerovani na prave vzniklou galerii |  | ||||||
| 			return HttpResponseRedirect('./hotovo') | 			return HttpResponseRedirect('./hotovo') | ||||||
| 
 |  | ||||||
| 	def prednaska_hodnoceni(prednaska): |  | ||||||
| 		h = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first() |  | ||||||
| 		if h: |  | ||||||
| 			return prednaska, h.body |  | ||||||
| 		else: | 		else: | ||||||
| 			return prednaska, 0 | 			prednasky = seznam.prednaska_set.all() | ||||||
|  | 			znalosti = seznam.znalost_set.all() | ||||||
|  | 			# Spadnout, pokud nesedí přednáška/znalost s formulářem. (Nějak se mi to nepovedlo.) | ||||||
|  | 
 | ||||||
|  | 	else: | ||||||
|  | 		def odpoved_prednasky(p): | ||||||
|  | 			hlasovani = p.hlasovani_set.filter(ucastnik=ucastnik).first() | ||||||
|  | 			return hlasovani.body if hlasovani else Hlasovani.Body.JEDNO | ||||||
|  | 
 | ||||||
|  | 		def odpoved_znalosti(z): | ||||||
|  | 			hlasovani = z.hlasovanioznalostech_set.filter(ucastnik=osoba).first() | ||||||
|  | 			return hlasovani.odpoved if hlasovani else Hlasovani.Body.JEDNO | ||||||
|  | 
 | ||||||
|  | 		prednasky = seznam.prednaska_set.all() | ||||||
|  | 		znalosti = seznam.znalost_set.all() | ||||||
|  | 
 | ||||||
|  | 		form_set_prednasky = HlasovaniPrednaskaFormSet(initial=[ | ||||||
|  | 			{"prednaska_id": p.id, "body": odpoved_prednasky(p)} for p in prednasky | ||||||
|  | 		], prefix=PREDNASKY_PREFIX) | ||||||
|  | 
 | ||||||
|  | 		form_set_znalosti = HlasovaniZnalostiFormSet(initial=[ | ||||||
|  | 			{"znalost_id": z.id, "odpoved": odpoved_znalosti(z)} for z in znalosti | ||||||
|  | 		], prefix=ZNALOSTI_PREFIX) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 	return render( | 	return render( | ||||||
| 		request, | 		request, | ||||||
| 		'prednasky/base.html', | 		'prednasky/base.html', | ||||||
| 		{'prednasky': map(prednaska_hodnoceni, seznam.prednaska_set.all())} | 		{ | ||||||
|  | 			'form_set_prednasky': form_set_prednasky, 'form_set_znalosti': form_set_znalosti, | ||||||
|  | 			'formy_a_prednasky': zip(form_set_prednasky, prednasky), | ||||||
|  | 			'formy_a_znalosti': zip(form_set_znalosti, znalosti), | ||||||
|  | 		} | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue