Merge branch 'data_migrations' of gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb into data_migrations
This commit is contained in:
		
						commit
						f960853239
					
				
					 26 changed files with 382 additions and 64 deletions
				
			
		|  | @ -695,13 +695,13 @@ | ||||||
| 			"alias": null, | 			"alias": null, | ||||||
| 			"description": "", | 			"description": "", | ||||||
| 			"hidden": false, | 			"hidden": false, | ||||||
| 			"hint": "", | 			"hint": "To, co ŘEŠITELÉ poslali", | ||||||
| 			"inbreadcrumbs": true, | 			"inbreadcrumbs": true, | ||||||
| 			"inmenu": true, | 			"inmenu": true, | ||||||
| 			"insitetree": true, | 			"insitetree": true, | ||||||
| 			"parent": 21, | 			"parent": 21, | ||||||
| 			"sort_order": 37, | 			"sort_order": 38, | ||||||
| 			"title": "Odevzdaná řešení", | 			"title": "Došlá řešení", | ||||||
| 			"tree": 1, | 			"tree": 1, | ||||||
| 			"url": "odevzdavatko_tabulka", | 			"url": "odevzdavatko_tabulka", | ||||||
| 			"urlaspattern": true | 			"urlaspattern": true | ||||||
|  | @ -724,7 +724,7 @@ | ||||||
| 			"inmenu": true, | 			"inmenu": true, | ||||||
| 			"insitetree": true, | 			"insitetree": true, | ||||||
| 			"parent": 21, | 			"parent": 21, | ||||||
| 			"sort_order": 38, | 			"sort_order": 42, | ||||||
| 			"title": "Odhlásit se", | 			"title": "Odhlásit se", | ||||||
| 			"tree": 1, | 			"tree": 1, | ||||||
| 			"url": "logout", | 			"url": "logout", | ||||||
|  | @ -806,5 +806,31 @@ | ||||||
| 		}, | 		}, | ||||||
| 		"model": "sitetree.treeitem", | 		"model": "sitetree.treeitem", | ||||||
| 		"pk": 41 | 		"pk": 41 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": false, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [ | ||||||
|  | 				2 | ||||||
|  | 			], | ||||||
|  | 			"access_restricted": true, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "To, co jsem JÁ odevzdal", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": 21, | ||||||
|  | 			"sort_order": 37, | ||||||
|  | 			"title": "Odevzdaná řešení", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_resitel_odevzdana_reseni", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 42 | ||||||
| 	} | 	} | ||||||
| ] | ] | ||||||
|  | @ -78,6 +78,7 @@ TEMPLATES = [ | ||||||
|                 'django.contrib.messages.context_processors.messages', |                 'django.contrib.messages.context_processors.messages', | ||||||
|                 'sekizai.context_processors.sekizai', |                 'sekizai.context_processors.sekizai', | ||||||
|                 'header_fotky.context_processors.vzhled', |                 'header_fotky.context_processors.vzhled', | ||||||
|  |                 'various.context_processors.april', | ||||||
|             ) |             ) | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
|  | @ -132,6 +133,7 @@ INSTALLED_APPS = ( | ||||||
|     'korektury', |     'korektury', | ||||||
|     'prednasky', |     'prednasky', | ||||||
|     'header_fotky', |     'header_fotky', | ||||||
|  |     'various', | ||||||
| 
 | 
 | ||||||
|     # Admin upravy: |     # Admin upravy: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -131,6 +131,48 @@ | ||||||
| 	   $("a[rel^='gallery-image']").prettyPhoto(prettyparams); | 	   $("a[rel^='gallery-image']").prettyPhoto(prettyparams); | ||||||
| 	}); | 	}); | ||||||
|     </script> |     </script> | ||||||
|  | 	{% if april == 2021 %} | ||||||
|  |     <script type="text/javascript" charset="utf-8"> | ||||||
|  | 	function rotace(vektor, uhel_deg) { | ||||||
|  | 		var uhel = uhel_deg *(Math.PI / 180); | ||||||
|  | 		var x = vektor[0]; | ||||||
|  | 		var y = vektor[1]; | ||||||
|  | 		return [x*Math.cos(uhel) - y*Math.sin(uhel), x*Math.sin(uhel) + y*Math.cos(uhel)]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	function rotace_a_posun(obj, uhel) { | ||||||
|  | 		var ow = obj.width(); | ||||||
|  | 		var oh = obj.height(); | ||||||
|  | 
 | ||||||
|  | 		var rohy = [[0,0], [0,oh], [ow, 0], [ow, oh]]; | ||||||
|  | 		var minx = 0; | ||||||
|  | 		var miny = 0; | ||||||
|  | 		for (var roh of rohy) { | ||||||
|  | 			var otoceny = rotace(roh, uhel); | ||||||
|  | 			if (otoceny[0] < minx) { | ||||||
|  | 				minx = otoceny[0]; | ||||||
|  | 			} | ||||||
|  | 			if (otoceny[1] < miny) { | ||||||
|  | 				miny = otoceny[1]; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		miny *= -1; | ||||||
|  | 		minx *= -1; | ||||||
|  | 
 | ||||||
|  | 		var transf_str = "translateX("+minx+"px) translateY("+miny+"px) rotate("+uhel+"deg)"; | ||||||
|  | 		obj.css('transform-origin', 'top left'); | ||||||
|  | 		obj.css('transform', transf_str); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	function randomUhel() { | ||||||
|  | 		return Math.floor(360*Math.random()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	$('.container').css('margin', 0); | ||||||
|  | 	rotace_a_posun($('.container'), randomUhel()); | ||||||
|  | 	</script> | ||||||
|  | 	{% endif %} | ||||||
|     {% render_block "js" %} |     {% render_block "js" %} | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -142,6 +142,28 @@ class PrihlaskaForm(forms.Form): | ||||||
| 			elif data.get('skola_adresa')=='': | 			elif data.get('skola_adresa')=='': | ||||||
| 				self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy')) | 				self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy')) | ||||||
| 
 | 
 | ||||||
|  | # Editační formulář bez řešitele. | ||||||
|  | class ProfileEditFormPoMaturite(forms.Form): | ||||||
|  | 	username = forms.CharField(label='Přihlašovací jméno', | ||||||
|  | 			max_length=256, | ||||||
|  | 			required=True) | ||||||
|  | 
 | ||||||
|  | 	jmeno = forms.CharField(label='Jméno', max_length=256, required=True) | ||||||
|  | 	prijmeni = forms.CharField(label='Příjmení', max_length=256, required=True) | ||||||
|  | 	pohlavi_muz = forms.ChoiceField(label='Pohlaví', | ||||||
|  | 			choices = ((True,'muž'),(False,'žena')), required=True) | ||||||
|  | 	email = forms.EmailField(label='E-mail',max_length=256, required=True) | ||||||
|  | 	telefon = forms.CharField(widget=TelInput(),label='Telefon',max_length=256, required=False) | ||||||
|  | 	datum_narozeni = forms.DateField(widget=DateInput(),label='Datum narození', required=False) | ||||||
|  | 	ulice = forms.CharField(label='Ulice', max_length=256, required=False) | ||||||
|  | 	mesto = forms.CharField(label='Město', max_length=256, required=False) | ||||||
|  | 	psc = forms.CharField(label='PSČ', max_length=32, required=False) | ||||||
|  | 	stat = forms.ChoiceField(label='Stát', | ||||||
|  | 			choices = (('CZ', 'Česká Republika'), | ||||||
|  | 				('SK', 'Slovenská Republika'), | ||||||
|  | 				('other', 'Jiné')), | ||||||
|  | 			required=False) | ||||||
|  | 	stat_text = forms.CharField(label='Stát', max_length=256, required=False) | ||||||
| 
 | 
 | ||||||
| class ProfileEditForm(forms.Form): | class ProfileEditForm(forms.Form): | ||||||
| 	username = forms.CharField(label='Přihlašovací jméno',  | 	username = forms.CharField(label='Přihlašovací jméno',  | ||||||
|  |  | ||||||
|  | @ -107,15 +107,41 @@ def spoj_k_organizatorum_osoby(apps, scema_editor): | ||||||
| 	for org in Organizator.objects.all(): | 	for org in Organizator.objects.all(): | ||||||
| 		 | 		 | ||||||
| 		# Spárování organizátora s osobou | 		# Spárování organizátora s osobou | ||||||
|  | 		# Myšlenka: Když najdeme řešitele pro daného uživatele, tak se vezme Osoba příslušná uživateli, | ||||||
|  | 		# Pokud nenajdeme uživatele, tak ještě zkusíme dohledat Osobu podle e-mailu | ||||||
| 		user = org.user | 		user = org.user | ||||||
| 		resitele = Resitel.objects.filter(user=user) | 		if user is None: | ||||||
| 		if resitele.count() != 0: | 			logger.error(f'Org {org} nemá uživatele!') | ||||||
| 			osoba = resitele.first().osoba | 			# Je to podezřelé, ale prostě vyrobíme novou osobu. | ||||||
|  | 			osoba = Osoba(user=user) | ||||||
|  | 			# Téhle osobě nejdou nastavit detaily, protože žádné nemáme. | ||||||
| 		else: | 		else: | ||||||
|  | 			logger.info(f'Org {org.user.email}(ID: {org.id}) má uživatele {user}') | ||||||
|  | 			# 💢💢💢 Python nemá goto, ale prý má výjimky… 💢💢💢 | ||||||
|  | 			class EndException(Exception): pass | ||||||
|  | 			try: | ||||||
|  | 				# Hledáme podle uživatele | ||||||
|  | 				resitele = Resitel.objects.filter(user=user) | ||||||
|  | 				if resitele.count() != 0 and user is not None: | ||||||
|  | 					osoba = resitele.first().osoba | ||||||
|  | 					logger.info(f'Našel jsem řešitele {resitele.first().email} podle uživatele, používám jeho Osobu') | ||||||
|  | 					raise EndException | ||||||
|  | 				 | ||||||
|  | 				# Hledáme podle e-mailu | ||||||
|  | 				osoby = Osoba.objects.filter(email__iexact=user.email) | ||||||
|  | 				if osoby.count() != 0 and user.email != '': | ||||||
|  | 					osoba = osoby.first() | ||||||
|  | 					if osoba.user is None: | ||||||
|  | 						osoba.user = user | ||||||
|  | 					logger.info(f'Našel jsem Osobu {osoby.first().email} podle e-mailu') | ||||||
|  | 					raise EndException | ||||||
|  | 
 | ||||||
|  | 				# Fallback | ||||||
|  | 				logger.warning(f'Org neměl řešitele, zakládám novou Osobu.') | ||||||
| 				osoba = Osoba(user=user) | 				osoba = Osoba(user=user) | ||||||
| 
 | 
 | ||||||
| 				# Přesun informací z usera do osoby | 				# Přesun informací z usera do osoby | ||||||
| 			# pro řešitele již v minule migraci | 				# pro osoby z řešitelů (jediné dosud existující osoby) již v minule migraci | ||||||
| 				osoba.jmeno = user.first_name | 				osoba.jmeno = user.first_name | ||||||
| 				osoba.prijmeni = user.last_name | 				osoba.prijmeni = user.last_name | ||||||
| 				osoba.email = user.email | 				osoba.email = user.email | ||||||
|  | @ -124,6 +150,8 @@ def spoj_k_organizatorum_osoby(apps, scema_editor): | ||||||
| 				user.email = "Použij osobu!" | 				user.email = "Použij osobu!" | ||||||
| 				user.save() | 				user.save() | ||||||
| 
 | 
 | ||||||
|  | 			except EndException: pass | ||||||
|  | 
 | ||||||
| 		# Přesun informací z organizátora do jeho osoby | 		# Přesun informací z organizátora do jeho osoby | ||||||
| 		osoba.prezdivka = org.prezdivka if org.prezdivka is not None else '' | 		osoba.prezdivka = org.prezdivka if org.prezdivka is not None else '' | ||||||
| 		osoba.foto = org.foto | 		osoba.foto = org.foto | ||||||
|  | @ -142,7 +170,10 @@ def fix_problem(apps, schema_editor): | ||||||
| 		else: | 		else: | ||||||
| 			pr.autor = None | 			pr.autor = None | ||||||
| 		if pr.opravovatel is not None: | 		if pr.opravovatel is not None: | ||||||
|  | 			if Organizator.objects.filter(osoba__user=pr.opravovatel).first() is not None: | ||||||
| 				pr.opravovatele.add(Organizator.objects.filter(osoba__user=pr.opravovatel).first()) | 				pr.opravovatele.add(Organizator.objects.filter(osoba__user=pr.opravovatel).first()) | ||||||
|  | 			else: | ||||||
|  | 				logger.error(f'WTF, nespárovaný opravovatel {pr.opravovatel} problému {pr}') | ||||||
| 		pr.save() | 		pr.save() | ||||||
| 
 | 
 | ||||||
| def fix_pohadka(apps, schema_editor): | def fix_pohadka(apps, schema_editor): | ||||||
|  |  | ||||||
|  | @ -28,26 +28,23 @@ def resitel_to_osoba(apps,schema_editor): | ||||||
| 			if u.first_name: | 			if u.first_name: | ||||||
| 				if not o.jmeno: | 				if not o.jmeno: | ||||||
| 					o.jmeno = u.first_name | 					o.jmeno = u.first_name | ||||||
| 					u.first_name = 'Použij osobu!' | 					u.first_name += ' (Uživatel!)' | ||||||
| 				elif o.jmeno == u.first_name: | 				elif o.jmeno == u.first_name: | ||||||
| 					u.first_name = 'Použij osobu!' | 					u.first_name += ' (Uživatel!)' | ||||||
| 				else: | 				else: | ||||||
| 					raise ValueError('jmeno a first_name rozdílné: "{}" vs. "{}"'.format(o.jmeno, u.first_name)) | 					raise ValueError('jmeno a first_name rozdílné: "{}" vs. "{}"'.format(o.jmeno, u.first_name)) | ||||||
| 			if u.last_name: | 			if u.last_name: | ||||||
| 				if not o.prijmeni: | 				if not o.prijmeni: | ||||||
| 					o.prijmeni = u.last_name | 					o.prijmeni = u.last_name | ||||||
| 					u.last_name = 'Použij osobu!' | 					u.last_name += ' (Uživatel!)' | ||||||
| 				elif o.prijmeni == u.last_name: | 				elif o.prijmeni == u.last_name: | ||||||
| 					u.last_name = 'Použij osobu!' | 					u.last_name += ' (Uživatel!)' | ||||||
| 				else: | 				else: | ||||||
| 					raise ValueError('prijmeni a last_name rozdílné: "{}" vs. "{}"'.format(o.prijmeni, u.last_name)) | 					raise ValueError('prijmeni a last_name rozdílné: "{}" vs. "{}"'.format(o.prijmeni, u.last_name)) | ||||||
| 			if u.email: | 			if u.email: | ||||||
| 				if not o.email: | 				if not o.email: | ||||||
| 					o.email = u.email | 					o.email = u.email | ||||||
| 					u.email = 'Použij osobu!' | 				elif o.email != u.email: | ||||||
| 				elif o.email == u.email: |  | ||||||
| 					u.email = 'Použij osobu!' |  | ||||||
| 				else: |  | ||||||
| 					raise ValueError('o.email a u.email rozdílné: "{}" vs. "{}"'.format(o.email, u.email)) | 					raise ValueError('o.email a u.email rozdílné: "{}" vs. "{}"'.format(o.email, u.email)) | ||||||
| 			u.save() | 			u.save() | ||||||
| 					 | 					 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,10 @@ from __future__ import unicode_literals | ||||||
| 
 | 
 | ||||||
| from django.db import migrations | from django.db import migrations | ||||||
| 
 | 
 | ||||||
|  | import logging | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
| def spoj_k_organizatorum_osoby(apps, scema_editor):	 | def spoj_k_organizatorum_osoby(apps, scema_editor):	 | ||||||
| 	Organizator = apps.get_model('seminar', 'Organizator') | 	Organizator = apps.get_model('seminar', 'Organizator') | ||||||
| 	Resitel = apps.get_model('seminar', 'Resitel') | 	Resitel = apps.get_model('seminar', 'Resitel') | ||||||
|  | @ -11,23 +15,50 @@ def spoj_k_organizatorum_osoby(apps, scema_editor): | ||||||
| 	for org in Organizator.objects.all(): | 	for org in Organizator.objects.all(): | ||||||
| 		 | 		 | ||||||
| 		# Spárování organizátora s osobou | 		# Spárování organizátora s osobou | ||||||
|  | 		# Myšlenka: Když najdeme řešitele pro daného uživatele, tak se vezme Osoba příslušná uživateli, | ||||||
|  | 		# Pokud nenajdeme uživatele, tak ještě zkusíme dohledat Osobu podle e-mailu | ||||||
| 		user = org.user | 		user = org.user | ||||||
| 		resitele = Resitel.objects.filter(user=user) | 		if user is None: | ||||||
| 		if resitele.count() != 0: | 			logger.error(f'Org {org} nemá uživatele!') | ||||||
| 			osoba = resitele.first().osoba | 			# Je to podezřelé, ale prostě vyrobíme novou osobu. | ||||||
|  | 			osoba = Osoba(user=user) | ||||||
|  | 			# Téhle osobě nejdou nastavit detaily, protože žádné nemáme. | ||||||
| 		else: | 		else: | ||||||
|  | 			logger.info(f'Org {org.user.email}(ID: {org.id}) má uživatele {user}') | ||||||
|  | 			# 💢💢💢 Python nemá goto, ale prý má výjimky… 💢💢💢 | ||||||
|  | 			class EndException(Exception): pass | ||||||
|  | 			try: | ||||||
|  | 				# Hledáme podle uživatele | ||||||
|  | 				resitele = Resitel.objects.filter(user=user) | ||||||
|  | 				if resitele.count() != 0 and user is not None: | ||||||
|  | 					osoba = resitele.first().osoba | ||||||
|  | 					logger.info(f'Našel jsem řešitele {resitele.first().email} podle uživatele, používám jeho Osobu') | ||||||
|  | 					raise EndException | ||||||
|  | 				 | ||||||
|  | 				# Hledáme podle e-mailu | ||||||
|  | 				osoby = Osoba.objects.filter(email__iexact=user.email) | ||||||
|  | 				if osoby.count() != 0 and user.email != '': | ||||||
|  | 					osoba = osoby.first() | ||||||
|  | 					if osoba.user is None: | ||||||
|  | 						osoba.user = user | ||||||
|  | 					logger.info(f'Našel jsem Osobu {osoby.first().email} podle e-mailu') | ||||||
|  | 					raise EndException | ||||||
|  | 
 | ||||||
|  | 				# Fallback | ||||||
|  | 				logger.warning(f'Org neměl řešitele, zakládám novou Osobu.') | ||||||
| 				osoba = Osoba(user=user) | 				osoba = Osoba(user=user) | ||||||
| 
 | 
 | ||||||
| 				# Přesun informací z usera do osoby | 				# Přesun informací z usera do osoby | ||||||
| 			# pro řešitele již v minule migraci | 				# pro osoby z řešitelů (jediné dosud existující osoby) již v minule migraci | ||||||
| 				osoba.jmeno = user.first_name | 				osoba.jmeno = user.first_name | ||||||
| 				osoba.prijmeni = user.last_name | 				osoba.prijmeni = user.last_name | ||||||
| 				osoba.email = user.email | 				osoba.email = user.email | ||||||
| 			user.jmeno = "Použij osobu!" | 				user.jmeno += " (Uživatel!)" | ||||||
| 			user.prijmeni = "Použij osobu!" | 				user.prijmeni += " (Uživatel!)" | ||||||
| 			user.email = "Použij osobu!" |  | ||||||
| 				user.save() | 				user.save() | ||||||
| 
 | 
 | ||||||
|  | 			except EndException: pass | ||||||
|  | 
 | ||||||
| 		# Přesun informací z organizátora do jeho osoby | 		# Přesun informací z organizátora do jeho osoby | ||||||
| 		osoba.prezdivka = org.prezdivka if org.prezdivka is not None else '' | 		osoba.prezdivka = org.prezdivka if org.prezdivka is not None else '' | ||||||
| 		osoba.foto = org.foto | 		osoba.foto = org.foto | ||||||
|  | @ -46,7 +77,10 @@ def fix_problem(apps, schema_editor): | ||||||
| 		else: | 		else: | ||||||
| 			pr.autor = None | 			pr.autor = None | ||||||
| 		if pr.opravovatel is not None: | 		if pr.opravovatel is not None: | ||||||
|  | 			if Organizator.objects.filter(osoba__user=pr.opravovatel).first() is not None: | ||||||
| 				pr.opravovatele.add(Organizator.objects.filter(osoba__user=pr.opravovatel).first()) | 				pr.opravovatele.add(Organizator.objects.filter(osoba__user=pr.opravovatel).first()) | ||||||
|  | 			else: | ||||||
|  | 				logger.error(f'WTF, nespárovaný opravovatel {pr.opravovatel} problému {pr}') | ||||||
| 		pr.save() | 		pr.save() | ||||||
| 
 | 
 | ||||||
| def fix_pohadka(apps, schema_editor): | def fix_pohadka(apps, schema_editor): | ||||||
|  |  | ||||||
|  | @ -602,13 +602,18 @@ class Cislo(SeminarModelBase): | ||||||
| 			png_filename = pathlib.Path(tempfile.mkdtemp(), 'nahled.png') | 			png_filename = pathlib.Path(tempfile.mkdtemp(), 'nahled.png') | ||||||
| 
 | 
 | ||||||
| 			subprocess.run([ | 			subprocess.run([ | ||||||
| 				"convert", | 				"gs", | ||||||
| 				"-density", "300x300", | 				"-sstdout=%stderr", | ||||||
| 				"-geometry", "{}x{}".format(VYSKA, sirka), | 				"-dSAFER", | ||||||
| 				"-background", "white", | 				"-dNOPAUSE", | ||||||
| 				"-flatten", | 				"-dBATCH", | ||||||
| 				"{}[0]".format(self.pdf.path),  # titulní strana | 				"-dNOPROMPT", | ||||||
| 				png_filename | 				"-sDEVICE=pngalpha", | ||||||
|  | 				"-r{}x{}".format(VYSKA, sirka), | ||||||
|  | 				"-dFirstPage=1d", | ||||||
|  | 				"-dLastPage=1d", | ||||||
|  | 				"-sOutputFile=" + str(png_filename), | ||||||
|  | 				"-f%s" % self.pdf.path | ||||||
| 				], | 				], | ||||||
| 				check=True, | 				check=True, | ||||||
| 				capture_output=True | 				capture_output=True | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| {% extends "base.html" %} | {% extends "base.html" %} | ||||||
| {% load static %} | {% load static %} | ||||||
|  | {% load deadliny %} | ||||||
| 
 | 
 | ||||||
| {% block content %} | {% block content %} | ||||||
| 
 | 
 | ||||||
|  | @ -62,7 +63,9 @@ $(document).ready(function(){ | ||||||
| <p>Řešitelé: {{ object.resitele.all | join:", " }}</p> | <p>Řešitelé: {{ object.resitele.all | join:", " }}</p> | ||||||
| 
 | 
 | ||||||
| {# https://docs.djangoproject.com/en/3.1/ref/models/instances/#django.db.models.Model.get_FOO_display #} | {# https://docs.djangoproject.com/en/3.1/ref/models/instances/#django.db.models.Model.get_FOO_display #} | ||||||
| <p>Forma: {{ object.get_forma_display }}, doručeno {{ object.cas_doruceni }}</p> | <p>Forma: {{ object.get_forma_display }}</p> | ||||||
|  | 
 | ||||||
|  | <p>Doručeno {{ object.cas_doruceni }}, deadline: {{object.cas_doruceni | deadline_html }}</p> | ||||||
| 
 | 
 | ||||||
| {# Soubory: #} | {# Soubory: #} | ||||||
| <h3>Přílohy:</h3> | <h3>Přílohy:</h3> | ||||||
|  |  | ||||||
							
								
								
									
										38
									
								
								seminar/templates/seminar/odevzdavatko/resitel_prehled.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								seminar/templates/seminar/odevzdavatko/resitel_prehled.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | {% extends "base.html" %} | ||||||
|  | {% load static %} | ||||||
|  | {% load deadliny %} | ||||||
|  | 
 | ||||||
|  | {% block custom_css %} | ||||||
|  | <style type=text/css> | ||||||
|  | .dosla_reseni tr th { | ||||||
|  | 	text-align: center; | ||||||
|  | } | ||||||
|  | .dosla_reseni tr th, .dosla_reseni tr td { | ||||||
|  | 	border: 1px solid black; | ||||||
|  | 	padding: 1px 10px 1px 10px; | ||||||
|  | 	border-collapse: collapse; | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | {% endblock custom_css %} | ||||||
|  | 
 | ||||||
|  | {% block content %} | ||||||
|  | {% for rocnik, hodnoceni in podle_rocniku %} | ||||||
|  | <h1>Ročník {{ rocnik }}</h1> | ||||||
|  | <table class="dosla_reseni"> | ||||||
|  | 	<tr> | ||||||
|  | 		<th>Doručeno</th> | ||||||
|  | 		<th>Problém</th> | ||||||
|  | 		<th>Body</th> | ||||||
|  | 		<th>Deadline</th> | ||||||
|  | 	</tr> | ||||||
|  | 	{% for hodn in hodnoceni %} | ||||||
|  | 	<tr> | ||||||
|  | 		<td>{{ hodn.reseni.cas_doruceni }}</td> | ||||||
|  | 		<td>{{ hodn.problem }}</td> | ||||||
|  | 		<td>{{ hodn.body|default_if_none:"---" }}</td> | ||||||
|  | 		<td>{{ hodn.reseni.cas_doruceni | deadline_html }}</td> | ||||||
|  | 	</tr> | ||||||
|  | 	{% endfor %} | ||||||
|  | </table> | ||||||
|  | {% endfor %} | ||||||
|  | {% endblock %} | ||||||
|  | @ -1,11 +1,15 @@ | ||||||
| {% extends "base.html" %} | {% extends "base.html" %} | ||||||
|  | {% load deadliny %} | ||||||
| 
 | 
 | ||||||
| {% block content %} | {% block content %} | ||||||
| 
 | 
 | ||||||
|  | {% for dl, mnozina_reseni in reseni_podle_deadlinu.items %} | ||||||
|  | <h1>{{ dl.2 | deadline_html }}</h1> | ||||||
| <ul> | <ul> | ||||||
| 	{% for obj in object_list %} | 	{% for obj in mnozina_reseni %} | ||||||
| 	<li><a href="{% url 'odevzdavatko_detail_reseni' pk=obj.id %}">{{ obj }}</a> ({{ obj.get_forma_display }} {{ obj.cas_doruceni }}) | 	<li><a href="{% url 'odevzdavatko_detail_reseni' pk=obj.id %}">{{ obj }}</a> ({{ obj.get_forma_display }} {{ obj.cas_doruceni }}) | ||||||
| 	{% endfor %} | 	{% endfor %} | ||||||
| </ul> | </ul> | ||||||
|  | {% endfor %} | ||||||
| 
 | 
 | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ | ||||||
|        {% include "seminar/profil/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} |        {% include "seminar/profil/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} | ||||||
|      </table> |      </table> | ||||||
| 
 | 
 | ||||||
|  | {% if not po_maturite %} {# Vysloužilým účastníkům skrýt editaci školy apod. #} | ||||||
|  <hr> |  <hr> | ||||||
| 
 | 
 | ||||||
|     <h4> |     <h4> | ||||||
|  | @ -95,6 +96,7 @@ | ||||||
|      </table> |      </table> | ||||||
| 
 | 
 | ||||||
|  <hr> |  <hr> | ||||||
|  | {% endif %} | ||||||
| 
 | 
 | ||||||
|     <input type="submit" value="Změnit"> |     <input type="submit" value="Změnit"> | ||||||
| </form> | </form> | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| 
 | 
 | ||||||
| <a href="{% url 'logout' %}">Odhlásit se</a><br> | <a href="{% url 'logout' %}">Odhlásit se</a><br> | ||||||
| <a href="{% url 'seminar_resitel_edit' %}">Upravit údaje</a><br> | <a href="{% url 'seminar_resitel_edit' %}">Upravit údaje</a><br> | ||||||
|  | <a href="{% url 'seminar_resitel_odevzdana_reseni' %}">Odevzdaná řešení</a><br> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								seminar/templatetags/deadliny.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								seminar/templatetags/deadliny.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | from django import template | ||||||
|  | from django.utils.safestring import mark_safe | ||||||
|  | from seminar.utils import TypDeadline, deadline | ||||||
|  | register = template.Library() | ||||||
|  | 
 | ||||||
|  | @register.filter(name='deadline') | ||||||
|  | def deadline_text(datum): | ||||||
|  | 	typ, cislo, dl = deadline(datum) | ||||||
|  | 	strings = { | ||||||
|  | 		TypDeadline.PredDeadline: f"1. deadline čísla {cislo} ({dl})", | ||||||
|  | 		TypDeadline.SousDeadline: f"Soustřeďkový deadline čísla {cislo} ({dl})", | ||||||
|  | 		TypDeadline.FinalDeadline: f"Finální deadline čísla {cislo} ({dl})", | ||||||
|  | 		} | ||||||
|  | 	return strings[typ] | ||||||
|  | 
 | ||||||
|  | @register.filter(name='deadline_kratseji') | ||||||
|  | def deadline_kratsi_text(datum): | ||||||
|  | 	typ, cislo, dl = deadline(datum) | ||||||
|  | 	strings = { | ||||||
|  | 		TypDeadline.PredDeadline: f"1. deadline {cislo}", | ||||||
|  | 		TypDeadline.SousDeadline: f"Soustřeďkový deadline {cislo}", | ||||||
|  | 		TypDeadline.FinalDeadline: f"Finální deadline {cislo}", | ||||||
|  | 		} | ||||||
|  | 	return strings[typ] | ||||||
|  | 
 | ||||||
|  | @register.filter(name='deadline_html') | ||||||
|  | def deadline_html(datum): | ||||||
|  | 	typ, _, _ = deadline(datum) | ||||||
|  | 	text = deadline_kratsi_text(datum) | ||||||
|  | 	classes = { | ||||||
|  | 		TypDeadline.PredDeadline: 'preddeadline', | ||||||
|  | 		TypDeadline.SousDeadline: 'sous_deadline', | ||||||
|  | 		TypDeadline.FinalDeadline: 'final_deadline', | ||||||
|  | 		} | ||||||
|  | 	return mark_safe(f'<span class="{classes[typ]}">{text}</span>') | ||||||
|  | @ -135,6 +135,7 @@ urlpatterns = [ | ||||||
| 	path('prihlasit/', views.LoginView.as_view(), name='login'), | 	path('prihlasit/', views.LoginView.as_view(), name='login'), | ||||||
| 	path('odhlasit/', views.LogoutView.as_view(), name='logout'), | 	path('odhlasit/', views.LogoutView.as_view(), name='logout'), | ||||||
| 	path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'), | 	path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'), | ||||||
|  | 	path('resitel/odevzdana_reseni/', resitel_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'), | ||||||
| 	path('reset-hesla/', views.PasswordResetView.as_view(), name='reset_password'), | 	path('reset-hesla/', views.PasswordResetView.as_view(), name='reset_password'), | ||||||
| 	path('zmena-hesla/', views.PasswordChangeView.as_view(), name='change_password'), | 	path('zmena-hesla/', views.PasswordChangeView.as_view(), name='change_password'), | ||||||
| 	path('reset-hesla/2/', views.PasswordResetDoneView.as_view(), name='reset_password_done'), | 	path('reset-hesla/2/', views.PasswordResetDoneView.as_view(), name='reset_password_done'), | ||||||
|  |  | ||||||
|  | @ -309,7 +309,7 @@ def deadline_v_rocniku(datum, rocnik): | ||||||
| 			deadliny.append((TypDeadline.FinalDeadline, c, c.datum_deadline)) | 			deadliny.append((TypDeadline.FinalDeadline, c, c.datum_deadline)) | ||||||
| 	deadliny = sorted(deadliny, key=lambda x: x[2])	# podle data | 	deadliny = sorted(deadliny, key=lambda x: x[2])	# podle data | ||||||
| 	for dl in deadliny: | 	for dl in deadliny: | ||||||
| 		if datum <= dl: | 		if datum <= dl[2]: | ||||||
| 			# První takový deadline je ten nejtěsnější | 			# První takový deadline je ten nejtěsnější | ||||||
| 			return dl | 			return dl | ||||||
| 
 | 
 | ||||||
|  | @ -319,20 +319,22 @@ def deadline(datum): | ||||||
| 	Vrací trojici (TypDeadline, Cislo, datumDeadline: date). | 	Vrací trojici (TypDeadline, Cislo, datumDeadline: date). | ||||||
| 	""" | 	""" | ||||||
| 
 | 
 | ||||||
|  | 	if isinstance(datum, datetime.datetime): | ||||||
|  | 		datum = datum.date() | ||||||
| 	rok = datum.year | 	rok = datum.year | ||||||
| 	# Dva ročníky podezřelé z obsahování dat | 	# Dva ročníky podezřelé z obsahování dat | ||||||
| 	pozdejsi_rocnik = m.Rocnik.filter(prvni_rok=rok) | 	pozdejsi_rocnik = m.Rocnik.objects.filter(prvni_rok=rok) | ||||||
| 	drivejsi_rocnik = m.Rocnik.filter(druhy_rok=rok) | 	drivejsi_rocnik = m.Rocnik.objects.filter(prvni_rok=rok-1) | ||||||
| 	if any( | 	if any([ | ||||||
| 			pozdejsi_rocnik.count() > 1, | 			pozdejsi_rocnik.count() > 1, | ||||||
| 			drivejsi_rocnik.count() > 1, | 			drivejsi_rocnik.count() > 1, | ||||||
| 			): | 			]): | ||||||
| 		raise ValueError(f"Více ročníků začíná/končí stejným rokem: {rok}") | 		raise ValueError(f"Více ročníků začíná/končí stejným rokem: {rok}") | ||||||
| 	pozdejsi_rocnik = pozdejsi_rocnik.first() if pozdejsi_rocnik.count() > 0 else None | 	pozdejsi_rocnik = pozdejsi_rocnik.first() if pozdejsi_rocnik.count() > 0 else None | ||||||
| 	drivejsi_rocnik = drivejsi_rocnik.first() if drivejsi_rocnik.count() > 0 else None | 	drivejsi_rocnik = drivejsi_rocnik.first() if drivejsi_rocnik.count() > 0 else None | ||||||
| 
 | 
 | ||||||
| 	# Předpokládáme, že neexistuje číslo, které má deadline ale nemá finální deadline. | 	# Předpokládáme, že neexistuje číslo, které má deadline ale nemá finální deadline. | ||||||
| 	posledni_deadline_drivejsiho_rocniku = m.Cislo.objects.get(rocnik=drivejsi_rocnik, datum_deadline__isnull=False).datum_deadline | 	posledni_deadline_drivejsiho_rocniku = m.Cislo.objects.filter(rocnik=drivejsi_rocnik, datum_deadline__isnull=False).last().datum_deadline | ||||||
| 
 | 
 | ||||||
| 	if datum <= posledni_deadline_drivejsiho_rocniku: | 	if datum <= posledni_deadline_drivejsiho_rocniku: | ||||||
| 		return deadline_v_rocniku(datum, drivejsi_rocnik) | 		return deadline_v_rocniku(datum, drivejsi_rocnik) | ||||||
|  |  | ||||||
|  | @ -8,12 +8,13 @@ from django.db import transaction | ||||||
| 
 | 
 | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| import datetime | import datetime | ||||||
|  | from itertools import groupby | ||||||
| import logging | import logging | ||||||
| 
 | 
 | ||||||
| import seminar.models as m | import seminar.models as m | ||||||
| import seminar.forms as f | import seminar.forms as f | ||||||
| from seminar.forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm | from seminar.forms import OdevzdavatkoTabulkaFiltrForm as FiltrForm | ||||||
| from seminar.utils import aktivniResitele, resi_v_rocniku | from seminar.utils import aktivniResitele, resi_v_rocniku, deadline | ||||||
| 
 | 
 | ||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
|  | @ -24,6 +25,8 @@ logger = logging.getLogger(__name__) | ||||||
| # 	- ReseniProblemuView | # 	- ReseniProblemuView | ||||||
| # - Detail konkrétního řešení -- všechny soubory, datum, ... | # - Detail konkrétního řešení -- všechny soubory, datum, ... | ||||||
| # 	- DetailReseniView | # 	- DetailReseniView | ||||||
|  | # - Pro řešitele: přehled jejich odevzdaných řešení | ||||||
|  | #	- PrehledOdevzdanychReseni | ||||||
| # | # | ||||||
| # Taky se může hodit: | # Taky se může hodit: | ||||||
| # - Tabulka všech řešitelů x všech problémů? | # - Tabulka všech řešitelů x všech problémů? | ||||||
|  | @ -169,7 +172,14 @@ class ReseniProblemuView(MultipleObjectTemplateResponseMixin, MultipleObjectMixi | ||||||
| 			return redirect(reverse("odevzdavatko_detail_reseni", kwargs={"pk": jedine_reseni.id})) | 			return redirect(reverse("odevzdavatko_detail_reseni", kwargs={"pk": jedine_reseni.id})) | ||||||
| 		context = self.get_context_data() | 		context = self.get_context_data() | ||||||
| 		return self.render_to_response(context) | 		return self.render_to_response(context) | ||||||
| 	# Kontext automaticky? | 
 | ||||||
|  | 	def get_context_data(self, *args, **kwargs): | ||||||
|  | 		ctx = super().get_context_data(*args, **kwargs) | ||||||
|  | 		# XXX: Předat groupby do template nejde: https://stackoverflow.com/questions/6906593/itertools-groupby-in-a-django-template | ||||||
|  | 		# Django má {% regroup %}, ale ten potřebuje, aby klíč byl atribut položky: https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#regroup | ||||||
|  | 		# Takže rozbalíme groupby do slovníku klíč → seznam sami (dictionary comphrehension) | ||||||
|  | 		ctx['reseni_podle_deadlinu'] = {k: list(v) for k,v in groupby(ctx['object_list'], lambda r: deadline(r.cas_doruceni))} | ||||||
|  | 		return ctx | ||||||
| 
 | 
 | ||||||
| ## XXX: https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#avoid-anything-more-complex | ## XXX: https://docs.djangoproject.com/en/3.1/topics/class-based-views/mixins/#avoid-anything-more-complex | ||||||
| class DetailReseniView(DetailView): | class DetailReseniView(DetailView): | ||||||
|  | @ -230,6 +240,29 @@ def hodnoceniReseniView(request, pk, *args, **kwargs): | ||||||
| 	return redirect(success_url) | 	return redirect(success_url) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class PrehledOdevzdanychReseni(ListView): | ||||||
|  | 	model = m.Hodnoceni | ||||||
|  | 	template_name = 'seminar/odevzdavatko/resitel_prehled.html' | ||||||
|  | 
 | ||||||
|  | 	def get_queryset(self): | ||||||
|  | 		if not self.request.user.is_authenticated: | ||||||
|  | 			raise RuntimeError("Uživatel měl být přihlášený!") | ||||||
|  | 		resitel = m.Resitel.objects.get(osoba__user=self.request.user) | ||||||
|  | 		qs = super().get_queryset() | ||||||
|  | 		qs = qs.filter(reseni__resitele__in=[resitel]) | ||||||
|  | 		return qs | ||||||
|  | 	 | ||||||
|  | 	def get_context_data(self, *args, **kwargs): | ||||||
|  | 		ctx = super().get_context_data(*args, **kwargs) | ||||||
|  | 		# Ročník určujeme podle čísla, do jehož deadlinu došlo řešení. | ||||||
|  | 		# Chceme to mít seřazené, takže místo comphrerehsion ručně postavíme pole polí. Django templates neumí použít OrderedDict :-/ | ||||||
|  | 		podle_rocniku = [] | ||||||
|  | 		for rocnik, hodnoceni in groupby(ctx['object_list'], lambda ho: deadline(ho.reseni.cas_doruceni)[1].rocnik): | ||||||
|  | 			podle_rocniku.append((rocnik, list(hodnoceni))) | ||||||
|  | 		ctx['podle_rocniku'] = reversed(podle_rocniku) # Od nejnovějšího ročníku | ||||||
|  | 		# TODO: Umožnit stažení / zobrazení řešení | ||||||
|  | 		return ctx | ||||||
|  | 
 | ||||||
| # Přehled všech řešení kvůli debugování | # Přehled všech řešení kvůli debugování | ||||||
| 
 | 
 | ||||||
| class SeznamReseniView(ListView): | class SeznamReseniView(ListView): | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ import seminar.models as m | ||||||
| from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek, Osoba, Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci | from seminar.models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek, Osoba, Skola # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci | ||||||
| #from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva | #from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva | ||||||
| from seminar import utils, treelib | from seminar import utils, treelib | ||||||
| from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm | from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm, ProfileEditFormPoMaturite | ||||||
| import seminar.forms as f | import seminar.forms as f | ||||||
| import seminar.templatetags.treenodes as tnltt | import seminar.templatetags.treenodes as tnltt | ||||||
| import seminar.views.views_rest as vr | import seminar.views.views_rest as vr | ||||||
|  | @ -1095,14 +1095,22 @@ def resitelEditView(request): | ||||||
| 	user_edit = osoba_edit.user | 	user_edit = osoba_edit.user | ||||||
| 	## Vytvoření slovníku, kterým předvyplním formulář  | 	## Vytvoření slovníku, kterým předvyplním formulář  | ||||||
| 	prefill_1=model_to_dict(user_edit) | 	prefill_1=model_to_dict(user_edit) | ||||||
| 	if resitel_edit: | 	if resitel_edit and resitel_edit.rok_maturity >= date.today().year: | ||||||
| 		prefill_2=model_to_dict(resitel_edit) | 		prefill_2=model_to_dict(resitel_edit) | ||||||
| 		prefill_1.update(prefill_2) | 		prefill_1.update(prefill_2) | ||||||
| 	prefill_3=model_to_dict(osoba_edit) | 	prefill_3=model_to_dict(osoba_edit) | ||||||
| 	prefill_1.update(prefill_3) | 	prefill_1.update(prefill_3) | ||||||
|  | 	if 'datum_narozeni' in prefill_1: | ||||||
|  | 		prefill_1['datum_narozeni'] = str(prefill_1['datum_narozeni']) | ||||||
|  | 	if resitel_edit and resitel_edit.rok_maturity < date.today().year: | ||||||
|  | 		form = ProfileEditFormPoMaturite(initial=prefill_1) | ||||||
|  | 	else: | ||||||
| 		form = ProfileEditForm(initial=prefill_1) | 		form = ProfileEditForm(initial=prefill_1) | ||||||
| 	## Změna údajů a jejich uložení | 	## Změna údajů a jejich uložení | ||||||
| 	if request.method == 'POST': | 	if request.method == 'POST': | ||||||
|  | 		if resitel_edit and resitel_edit.rok_maturity < date.today().year: | ||||||
|  | 			form = ProfileEditFormPoMaturite(request.POST) | ||||||
|  | 		else: | ||||||
| 			form = ProfileEditForm(request.POST) | 			form = ProfileEditForm(request.POST) | ||||||
| 		if form.is_valid(): | 		if form.is_valid(): | ||||||
| 			## Změny v osobě | 			## Změny v osobě | ||||||
|  | @ -1115,6 +1123,7 @@ def resitelEditView(request): | ||||||
| 			osoba_edit.ulice = fcd['ulice'] | 			osoba_edit.ulice = fcd['ulice'] | ||||||
| 			osoba_edit.mesto = fcd['mesto'] | 			osoba_edit.mesto = fcd['mesto'] | ||||||
| 			osoba_edit.psc = fcd['psc'] | 			osoba_edit.psc = fcd['psc'] | ||||||
|  | 			osoba_edit.datum_narozeni = fcd['datum_narozeni'] | ||||||
| 			## Změny v osobě s podmínkami | 			## Změny v osobě s podmínkami | ||||||
| 			if fcd.get('spam',False): | 			if fcd.get('spam',False): | ||||||
| 				osoba_edit.datum_souhlasu_zasilani = date.today() | 				osoba_edit.datum_souhlasu_zasilani = date.today() | ||||||
|  | @ -1124,7 +1133,7 @@ def resitelEditView(request): | ||||||
| 				## Neznámá země | 				## Neznámá země | ||||||
| 				msg = "Unknown country {}".format(fcd['stat_text']) | 				msg = "Unknown country {}".format(fcd['stat_text']) | ||||||
| 
 | 
 | ||||||
| 			if resitel_edit: | 			if resitel_edit and resitel_edit.rok_maturity >= date.today().year: | ||||||
| 				## Změny v řešiteli | 				## Změny v řešiteli | ||||||
| 				resitel_edit.skola = fcd['skola'] | 				resitel_edit.skola = fcd['skola'] | ||||||
| 				resitel_edit.rok_maturity = fcd['rok_maturity'] | 				resitel_edit.rok_maturity = fcd['rok_maturity'] | ||||||
|  | @ -1140,7 +1149,7 @@ def resitelEditView(request): | ||||||
| 			return formularOKView(request) | 			return formularOKView(request) | ||||||
| 	else: | 	else: | ||||||
| 		## Stránka před odeslaním formuláře = předvyplněný formulář | 		## Stránka před odeslaním formuláře = předvyplněný formulář | ||||||
| 		return render(request, 'seminar/profil/edit.html', {'form': form}) | 		return render(request, 'seminar/profil/edit.html', {'form': form, 'po_maturite': resitel_edit and resitel_edit.rok_maturity < date.today().year}) | ||||||
| 
 | 
 | ||||||
| def prihlaskaView(request): | def prihlaskaView(request): | ||||||
| 	generic_logger = logging.getLogger('seminar.prihlaska') | 	generic_logger = logging.getLogger('seminar.prihlaska') | ||||||
|  |  | ||||||
							
								
								
									
										0
									
								
								various/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								various/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										3
									
								
								various/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								various/admin.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | from django.contrib import admin | ||||||
|  | 
 | ||||||
|  | # Register your models here. | ||||||
							
								
								
									
										5
									
								
								various/apps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								various/apps.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | from django.apps import AppConfig | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class VariousConfig(AppConfig): | ||||||
|  |     name = 'various' | ||||||
							
								
								
									
										14
									
								
								various/context_processors.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								various/context_processors.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | def april(req): | ||||||
|  | 	if 'X-April' in req.headers: | ||||||
|  | 		try: | ||||||
|  | 			year = int(req.headers['X-April']) | ||||||
|  | 			return {'april': year} | ||||||
|  | 		except: | ||||||
|  | 			pass # Fall-back to regular behaviour | ||||||
|  | 	 | ||||||
|  | 	import datetime | ||||||
|  | 	today = datetime.date.today() | ||||||
|  | 	if today.day == 1 and today.month == 4: | ||||||
|  | 		return {'april': today.year} | ||||||
|  | 	return {} | ||||||
|  | 
 | ||||||
							
								
								
									
										0
									
								
								various/migrations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								various/migrations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										3
									
								
								various/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								various/models.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | from django.db import models | ||||||
|  | 
 | ||||||
|  | # Create your models here. | ||||||
							
								
								
									
										3
									
								
								various/tests.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								various/tests.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | from django.test import TestCase | ||||||
|  | 
 | ||||||
|  | # Create your tests here. | ||||||
							
								
								
									
										3
									
								
								various/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								various/views.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | from django.shortcuts import render | ||||||
|  | 
 | ||||||
|  | # Create your views here. | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kateřina Č
						Kateřina Č