162 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| Stránky, které se mi nepovedlo lépe zařadit.
 | |
| 
 | |
| Oproti `./pomocne.py` se tyto views používají přímo ve various
 | |
| a naopak importují spoustu věcí odjinud
 | |
| """
 | |
| import datetime
 | |
| 
 | |
| from django.contrib.contenttypes.models import ContentType
 | |
| from django.shortcuts import get_object_or_404, render
 | |
| from django.utils import timezone
 | |
| from django.views import generic
 | |
| 
 | |
| import novinky.views
 | |
| import treenode.treelib as t
 | |
| import tvorba.views
 | |
| 
 | |
| from treenode.models import CisloNode
 | |
| from personalni.models import Resitel, Osoba
 | |
| from tvorba.models import Clanek, Deadline
 | |
| 
 | |
| from ..models import Nastaveni
 | |
| 
 | |
| 
 | |
| class TitulniStranaView(generic.ListView):
 | |
| 	template_name = 'various/titulnistrana/titulnistrana.html'
 | |
| 
 | |
| 	def get_queryset(self):
 | |
| 		return novinky.views.spravne_novinky(self.request)[:3]
 | |
| 
 | |
| 	def get_context_data(self, **kwargs):
 | |
| 		context = super(TitulniStranaView, self).get_context_data(**kwargs)
 | |
| 		nastaveni = get_object_or_404(Nastaveni)
 | |
| 
 | |
| 		deadline = Deadline.objects.filter(
 | |
| 			deadline__gte=timezone.now()).order_by("deadline").first()
 | |
| 		context['nejblizsi_deadline'] = deadline
 | |
| 
 | |
| 		# Aktuální témata
 | |
| 		nazvy_a_odkazy_na_aktualni_temata = []
 | |
| 		akt_temata = tvorba.views.aktualni_temata(nastaveni.aktualni_rocnik)
 | |
| 
 | |
| 		for tema in akt_temata:
 | |
| 			# FIXME: netuším, jestli funguje tema.verejne_url(), nemáme testdata na témátka - je to asi url vzhledem k ročníku
 | |
| 			nazvy_a_odkazy_na_aktualni_temata.append({
 | |
| 				'nazev': tema.nazev,
 | |
| 				'url': tema.verejne_url()
 | |
| 			})
 | |
| 
 | |
| 		context['aktualni_temata'] = nazvy_a_odkazy_na_aktualni_temata
 | |
| 
 | |
| 		return context
 | |
| 
 | |
| 
 | |
| class JakResitView(generic.ListView):
 | |
| 	template_name = 'various/jakresit/jak-resit.html'
 | |
| 
 | |
| 	def get_queryset(self):
 | |
| 		return None
 | |
| 
 | |
| 
 | |
| ### Status
 | |
| def histogram(seznam):
 | |
| 	d = {}
 | |
| 	for i in seznam:
 | |
| 		if i not in d:
 | |
| 			d[i] = 0
 | |
| 		d[i] += 1
 | |
| 	return d
 | |
| 
 | |
| 
 | |
| def seznam_problemu():
 | |
| 	"""Funkce pro hledání nekonzistencí v databázi a dalších nežádoucích stavů webu/databáze.
 | |
| 
 | |
| 	Nijak nesouvisí s Problémy zadanými řešitelům."""
 | |
| 	# FIXME: přejmenovat funkci?
 | |
| 	problemy = []
 | |
| 
 | |
| 	# Pomocna fce k formatovani problemovych hlasek
 | |
| 	def prb(cls, msg, objs=None):
 | |
| 		s = '<b>%s:</b> %s' % (cls.__name__, msg)
 | |
| 		if objs:
 | |
| 			s += ' ['
 | |
| 			for o in objs:
 | |
| 				try:
 | |
| 					url = o.admin_url()
 | |
| 				except:
 | |
| 					url = None
 | |
| 				if url:
 | |
| 					s += '<a href="%s">%s</a>, ' % (url, o.pk,)
 | |
| 				else:
 | |
| 					s += '%s, ' % (o.pk,)
 | |
| 			s = s[:-2] + ']'
 | |
| 		problemy.append(s)
 | |
| 
 | |
| 	# Duplicita jmen
 | |
| 	jmena = {}
 | |
| 	for r in Resitel.objects.all():
 | |
| 		j = r.osoba.plne_jmeno()
 | |
| 		if j not in jmena:
 | |
| 			jmena[j] = []
 | |
| 		jmena[j].append(r)
 | |
| 	for j in jmena:
 | |
| 		if len(jmena[j]) > 1:
 | |
| 			prb(Resitel, 'Duplicitní jméno "%s"' % (j,), jmena[j])
 | |
| 
 | |
| 	# Data maturity a narození
 | |
| 	for r in Resitel.objects.all():
 | |
| 		if not r.rok_maturity:
 | |
| 			prb(Resitel, 'Neznámý rok maturity', [r])
 | |
| 		if r.rok_maturity and (r.rok_maturity < 1990 or r.rok_maturity > datetime.date.today().year + 10):
 | |
| 			prb(Resitel, 'Podezřelé datum maturity', [r])
 | |
| 		if r.osoba.datum_narozeni and (
 | |
| 				r.osoba.datum_narozeni.year < 1970 or r.osoba.datum_narozeni.year > datetime.date.today().year - 12):
 | |
| 			prb(Resitel, 'Podezřelé datum narození', [r])
 | |
| 	#		if not r.email:
 | |
| 	#			prb(Resitel, u'Neznámý email', [r])
 | |
| 
 | |
| 	## Kontroly konzistence databáze a TreeNodů
 | |
| 
 | |
| 	# Články
 | |
| 	for clanek in Clanek.objects.all():
 | |
| 		# získáme řešení svázané se článkem a z něj node ve stromě
 | |
| 		reseni = clanek.reseni_set
 | |
| 		if (reseni.count() != 1):
 | |
| 			raise ValueError("Článek k sobě má nejedno řešení!")
 | |
| 		r = reseni.first()
 | |
| 		clanek_node = r.text_cely	# vazba na ReseniNode z Reseni
 | |
| 		# content type je věc pomáhající rozeznávat různé typy objektů v django-polymorphic
 | |
| 		# protože isinstance vrátí vždy jen TreeNode
 | |
| 		# https://django-polymorphic.readthedocs.io/en/stable/migrating.html
 | |
| 		cislonode_ct = ContentType.objects.get_for_model(CisloNode)
 | |
| 		node = clanek_node
 | |
| 		while node is not None:
 | |
| 			node_ct = node.polymorphic_ctype
 | |
| 			if node_ct == cislonode_ct:	# dostali jsme se k CisloNode
 | |
| 				# zkontrolujeme, že stromové číslo odpovídá atributu
 | |
| 				# .cislonode je opačná vazba k treenode_ptr, abychom z TreeNode dostali
 | |
| 				# CisloNode
 | |
| 				if clanek.cislo != node.cislonode.cislo:
 | |
| 					prb(Clanek, "Číslo otištění uložené u článku nesedí s "
 | |
| 								  "číslem otištění podle struktury treenodů.", [clanek])
 | |
| 				break
 | |
| 			node = t.get_parent(node)
 | |
| 
 | |
| 	return problemy
 | |
| 
 | |
| def StavDatabazeView(request):
 | |
| 	# nastaveni = Nastaveni.objects.get()
 | |
| 	problemy = seznam_problemu()
 | |
| 	muzi = Resitel.objects.filter(osoba__osloveni=Osoba.OSLOVENI_MUZSKE)
 | |
| 	zeny = Resitel.objects.filter(osoba__osloveni=Osoba.OSLOVENI_ZENSKE)
 | |
| 	return render(request, 'various/stav_databaze.html', {
 | |
| 		# 'nastaveni': nastaveni,
 | |
| 		'problemy': problemy,
 | |
| 
 | |
| 		'resitele': Resitel.objects.all(),
 | |
| 		'muzi': muzi,
 | |
| 		'zeny': zeny,
 | |
| 		'jmena_muzu': histogram([r.osoba.jmeno for r in muzi]),
 | |
| 		'jmena_zen': histogram([r.osoba.jmeno for r in zeny]),
 | |
| 	})
 |