Pavel "LEdoian" Turinsky
1 year ago
53 changed files with 975 additions and 229 deletions
@ -1,25 +0,0 @@ |
|||||
.. Není odkázaná z menu, je to záměr |
|
||||
|
|
||||
Tabulka prerekvizit v různých distribucích |
|
||||
========= |
|
||||
|
|
||||
.. admonition:: Metodika |
|
||||
|
|
||||
Na čistém repozitáři (``git clean -fxd``) a čistém systému spouštíme |
|
||||
``make/init_local``. Když to spadne, tak do tabulky zapíšeme, co jsme |
|
||||
přiinstalovali. Protože větev ``makefiles`` aktuálně není mergenutá do |
|
||||
masteru, nefunguje synchronizace flatpages (a stejně nemáme SSH klíč), takže |
|
||||
tam ``make/init_local`` sestřelíme a vyzkoušíme, že ``make/test`` spustí |
|
||||
testy. |
|
||||
|
|
||||
.. Grafické tabulky (grid-tables, simple-tables) jsou strašný porod vyrábět, dlabu na to a cpu to do CSV… |
|
||||
|
|
||||
.. csv-table:: Prerekvizity v jednotlivých distribucích |
|
||||
:header: Distribuce / OS, Repozitář s Py3.9, venv, py knihovny, PostgreSQL knihovna, poznámky |
|
||||
|
|
||||
Ubuntu 22.10, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "Je potřeba zapnout zdroj ``universe`` a nainstalovat kompilátor C (``gcc``)?" |
|
||||
Linux Mint 21, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "" |
|
||||
Archlinux 2022.11.01, AUR, vestavěný, vestavěné, ``postgresql-libs``, "Je potřeba céčkový kompilátor (``gcc``)" |
|
||||
openSUSE Leap 15.4, oficiální (``python39``), předinstalovaný?, ``python39-devel``, ??FIXME!!, "Výchozí verze pythonu je 3.6 a ta je moc stará, potřeba instalovat ``gcc``. Nevím jak sehnat pg_config." |
|
||||
Debian 11, "oficiální, výchozí", ??, ??, ??, "Určitě to tam rozběhat jde, protože Gimli. Nejspíš bude relativně podobné Ubuntu." |
|
||||
|
|
@ -0,0 +1,97 @@ |
|||||
|
Závislosti webu |
||||
|
@@@@@@@@@@@@@@@ |
||||
|
|
||||
|
Web ke svému běhu potřebuje různé další programy. Tahle stránka se snaží je pokrýt. |
||||
|
|
||||
|
Stránka je koncipována jako odrážkový seznam balíčků pro Ubuntu s případnými |
||||
|
komentáři, na konci stránky jsou uvedena :ref:`jména balíčků <Alternativní jména |
||||
|
balíčků>` v různých dalších distribucích. (Seznam mj. cílí na lokální |
||||
|
rozchození, proto popisuji Ubuntu a ne Debian. I tak se ale snažíme popsat web |
||||
|
v úplnosti.) |
||||
|
|
||||
|
.. I use Arch, btw. |
||||
|
|
||||
|
|
||||
|
Základ webu |
||||
|
=========== |
||||
|
|
||||
|
- ``python3`` – Ideálně Python 3.9, jenž je na Gimlim |
||||
|
- ``python3-pip`` pro instalaci dalších Pythoních balíčků podle ``requirements.txt`` |
||||
|
- ``python3-venv`` |
||||
|
- ``gcc`` – kompilace Pythoních knihoven ze zdrojových distribucí (sdist), možná (neotestováno) jde jako alternativu použít ``python3-wheel`` a stahovat bdists |
||||
|
- ``python3-dev`` – taktéž |
||||
|
- ``libpq-dev`` do třetice… |
||||
|
- ``ghostscript`` TODO konverze PDF v korekturovátku |
||||
|
- ``pdflatex`` FIXME! generování obálek a stvrzenek |
||||
|
- ``git`` – používán :ref:`Make skripty` |
||||
|
- ``locales`` pro české formáty |
||||
|
|
||||
|
Nasazení na produkci / testweb |
||||
|
============================== |
||||
|
|
||||
|
(nejsou nutně potřeba k provozu lokální instance) |
||||
|
|
||||
|
- ``rsync`` |
||||
|
- ``pg_utils`` FIXME |
||||
|
- ``htpasswd`` FIXME – aby testweb nepoužívali náhodní kolemjdoucí |
||||
|
- ``postgresql-server`` TODO |
||||
|
- ``acl`` pro nastavování práv přes ``setfacl`` |
||||
|
|
||||
|
Pro testweb je potřeba i všechno pro :ref:`dokumentaci <Dokumentace>`, vizte níž. |
||||
|
|
||||
|
Předpokládá se nasazení v uWSGI pod Nginxem a služba běžící pod systemd, nicméně to už je spíš záležitost infrastruktury a ne specifikum mamwebu. |
||||
|
|
||||
|
Dokumentace |
||||
|
=========== |
||||
|
|
||||
|
- ``make`` pro zbuildění |
||||
|
- Pythoní balíčky podle příslušné části ``requirements.txt`` |
||||
|
|
||||
|
Vývojové nástroje |
||||
|
================= |
||||
|
|
||||
|
(Nejsou nezbytně nutné, ale předpokládáme jejich užitečnost. Mohou se hodit i na produkci.) |
||||
|
|
||||
|
- ``psql`` TODO pro manuální dotazy do PostgreSQL |
||||
|
- ``sqlite3`` TODO totéž pro SQLite3 |
||||
|
- ``ssh`` |
||||
|
- ``graphviz`` pro vygenerování schématu |
||||
|
- ``rsync`` |
||||
|
- ``ipython3`` – hezčí interaktivní shell (stačí z ``requirements.txt``) |
||||
|
|
||||
|
Potenciální usnadnění života |
||||
|
============================ |
||||
|
|
||||
|
(Úplně zbytečné, ale sdílíme pozitivní zkušenosti :-)) |
||||
|
|
||||
|
- ``tea`` – CLI klient pro Giteu, aby člověk nepotřeboval otevírat web pro založení PR |
||||
|
|
||||
|
|
||||
|
Alternativní jména balíčků |
||||
|
========================== |
||||
|
|
||||
|
Různé distribuce balí SW různě, takže to, co je v jedné distribuci jeden |
||||
|
balíček může být v jiné rozděleno do víc. Pro usnadnění nasazení je tady |
||||
|
přehled známých alternativních jmen. |
||||
|
|
||||
|
TODO: tabulka není úplná. Pokud na něco narazíte, tak ji prosím doplňte. |
||||
|
|
||||
|
.. admonition:: Jak se pozná, že web funguje, pro účely tabulky? |
||||
|
|
||||
|
Na čistém repozitáři (``git clean -fxd``) a čistém systému spouštíme |
||||
|
``make/init_local``. Když to spadne, tak do tabulky zapíšeme, co jsme |
||||
|
přiinstalovali. Protože nefunguje synchronizace flatpages (nemáme SSH klíč), |
||||
|
``make/init_local`` sestřelíme při pokusu o synchronizaci a vyzkoušíme, že |
||||
|
``make/test`` spustí testy. |
||||
|
|
||||
|
.. Grafické tabulky (grid-tables, simple-tables) jsou strašný porod vyrábět, dlabu na to a cpu to do CSV… |
||||
|
|
||||
|
.. csv-table:: Prerekvizity v jednotlivých distribucích |
||||
|
:header: Distribuce / OS, Repozitář s Py3.9, venv, py knihovny, PostgreSQL knihovna, poznámky |
||||
|
|
||||
|
Ubuntu 22.10, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "Je potřeba zapnout zdroj ``universe`` a nainstalovat kompilátor C (``gcc``)?" |
||||
|
Linux Mint 21, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "" |
||||
|
Archlinux 2022.11.01, AUR, vestavěný, vestavěné, ``postgresql-libs``, "Je potřeba céčkový kompilátor (``gcc``)" |
||||
|
openSUSE Leap 15.4, oficiální (``python39``), předinstalovaný?, ``python39-devel``, ??FIXME!!, "Výchozí verze pythonu je 3.6 a ta je moc stará, potřeba instalovat ``gcc``. Nevím jak sehnat pg_config." |
||||
|
Debian 11, "oficiální, výchozí", ??, ??, ??, "Určitě to tam rozběhat jde, protože Gimli. Nejspíš bude relativně podobné Ubuntu." |
||||
|
|
@ -0,0 +1,18 @@ |
|||||
|
# Generated by Django 2.2.28 on 2023-06-19 19:38 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('korektury', '0019_auto_20221205_2014'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='korekturovanepdf', |
||||
|
name='nazev', |
||||
|
field=models.CharField(help_text='Název (např. `22.1 | analyza v4` nebo `propagace | letacek v0`) korekturovaného PDF', max_length=50, verbose_name='název PDF'), |
||||
|
), |
||||
|
] |
@ -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 %} |
@ -0,0 +1,15 @@ |
|||||
|
from django import template |
||||
|
register = template.Library() |
||||
|
|
||||
|
from functools import cache |
||||
|
import seminar.models as m |
||||
|
|
||||
|
@register.filter |
||||
|
@cache |
||||
|
def barva_reseni(r: m.Reseni): |
||||
|
"""Vrátí nějakou barvu pro daný problém, ve tvaru '#RRGGBB' |
||||
|
|
||||
|
Efektivně hešujeme do barev.""" |
||||
|
|
||||
|
#TODO: ne všechny barvy jsou dobře rozlišitelné a vidět… |
||||
|
return f'#{hash(str(r.id)) & 0xffffff:06x}' |
@ -0,0 +1,63 @@ |
|||||
|
from django.test import TestCase, RequestFactory |
||||
|
|
||||
|
from django.contrib.auth.models import User, Group |
||||
|
from django.contrib.admin.sites import AdminSite |
||||
|
from personalni.admin import OsobaAdmin |
||||
|
# Tohle bude peklo, až jednou ty modely fakt rozstřelíme… Možná vyrobit various.all_models, které půjdou importovat jako m? :-) |
||||
|
import seminar.models as m |
||||
|
|
||||
|
import logging |
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
class DelaniOrguTest(TestCase): |
||||
|
def setUp(self): |
||||
|
# Admin musí mít instanci |
||||
|
# Ref: https://www.argpar.se/posts/programming/testing-django-admin/ |
||||
|
adm_site = AdminSite() |
||||
|
self.admin = OsobaAdmin(m.Osoba, adm_site) |
||||
|
|
||||
|
from django.contrib.messages.storage.cookie import CookieStorage |
||||
|
self.request = RequestFactory().get('/admin') |
||||
|
self.request._messages = CookieStorage(self.request) |
||||
|
|
||||
|
self.org_group = Group.objects.get(name='org') |
||||
|
|
||||
|
novy_user = User.objects.create(username='osoba') |
||||
|
self.nova_osoba = m.Osoba.objects.create( |
||||
|
jmeno='Milada', |
||||
|
prijmeni='Von Kolej', |
||||
|
user = novy_user, |
||||
|
# Snad nic dalšího nepotřebujeme, kdyžtak se doplní… |
||||
|
) |
||||
|
stary_user = User.objects.create(username='stary_user') |
||||
|
stara_osoba = m.Osoba.objects.create(user=stary_user) |
||||
|
self.stary_org = m.Organizator.objects.create(osoba=stara_osoba) |
||||
|
|
||||
|
def test_pridani_orga(self): |
||||
|
# Nejdřív to není org… |
||||
|
self.assertFalse(m.Organizator.objects.filter(osoba=self.nova_osoba).exists()) |
||||
|
self.assertNotIn(self.org_group, self.nova_osoba.user.groups.all()) |
||||
|
self.assertFalse(self.nova_osoba.user.has_perm('auth.org')) |
||||
|
self.assertFalse(self.nova_osoba.user.is_staff) |
||||
|
|
||||
|
# Pak orga uděláme… |
||||
|
qs = m.Osoba.objects.filter(id=self.nova_osoba.id) |
||||
|
self.admin.udelej_orgem(self.request, qs) |
||||
|
|
||||
|
# A pak už to org má být. |
||||
|
self.nova_osoba.refresh_from_db() |
||||
|
self.assertTrue(self.nova_osoba.user.is_staff) |
||||
|
# FIXME: V db nejsou práva. Nový org je sice ve skupině "org", ale ta nemá právo "auth.org" |
||||
|
# Očekávané řešení: dodat fixture, která to přidá. |
||||
|
#self.assertTrue(self.nova_osoba.user.has_perm('auth.org')) |
||||
|
self.assertIn(self.org_group, self.nova_osoba.user.groups.all()) |
||||
|
self.assertTrue(m.Organizator.objects.filter(osoba=self.nova_osoba).exists()) |
||||
|
novy_org = m.Organizator.objects.get(osoba=self.nova_osoba) |
||||
|
self.assertIsNotNone(novy_org.organizuje_od) |
||||
|
|
||||
|
def test_pridani_stareho_orga(self): |
||||
|
self.admin.udelej_orgem(self.request, m.Osoba.objects.filter(id=self.stary_org.osoba.id)) # Ugly |
||||
|
# Když to spadne, tak jsem se to dozvěděl, takže už nepotřebuju nic kontrolovat. |
||||
|
# Jestli to funguje správně má řešit jiný test. |
||||
|
|
||||
|
|
@ -0,0 +1,8 @@ |
|||||
|
from django.contrib import admin |
||||
|
|
||||
|
from .models import OdpovedUcastnika, SpravnaOdpoved |
||||
|
|
||||
|
# Register your models here. |
||||
|
|
||||
|
admin.site.register(OdpovedUcastnika) |
||||
|
admin.site.register(SpravnaOdpoved) |
@ -0,0 +1,5 @@ |
|||||
|
from django.apps import AppConfig |
||||
|
|
||||
|
|
||||
|
class SifrovackaConfig(AppConfig): |
||||
|
name = 'sifrovacka' |
@ -0,0 +1,18 @@ |
|||||
|
from django.core.exceptions import ValidationError |
||||
|
from django.forms import ModelForm, Textarea |
||||
|
from .models import OdpovedUcastnika, SpravnaOdpoved |
||||
|
|
||||
|
|
||||
|
class SifrovackaForm(ModelForm): |
||||
|
class Meta: |
||||
|
model = OdpovedUcastnika |
||||
|
fields = ["sifra", "odpoved", ] |
||||
|
widgets = { |
||||
|
"odpoved": Textarea(attrs={'rows': 1, 'cols': 30}), |
||||
|
} |
||||
|
|
||||
|
def clean_sifra(self): |
||||
|
sifra = self.cleaned_data.get('sifra') |
||||
|
if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0: |
||||
|
raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.") |
||||
|
return sifra |
@ -0,0 +1,34 @@ |
|||||
|
# Generated by Django 3.2.22 on 2023-10-14 09:20 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
initial = True |
||||
|
|
||||
|
dependencies = [ |
||||
|
('seminar', '0113_resitel_zasilat_cislo_papirove'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.CreateModel( |
||||
|
name='SpravnaOdpoved', |
||||
|
fields=[ |
||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('odpoved', models.TextField()), |
||||
|
('sifra', models.IntegerField()), |
||||
|
('skryty_text', models.TextField()), |
||||
|
], |
||||
|
), |
||||
|
migrations.CreateModel( |
||||
|
name='OdpovedUcastnika', |
||||
|
fields=[ |
||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
|
('odpoved', models.TextField(verbose_name='Tajenka')), |
||||
|
('sifra', models.IntegerField(verbose_name='Číslo šifry')), |
||||
|
('resitel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='seminar.resitel')), |
||||
|
], |
||||
|
), |
||||
|
] |
@ -0,0 +1,28 @@ |
|||||
|
# Generated by Django 3.2.22 on 2023-10-15 17:44 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.utils.timezone |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('sifrovacka', '0001_initial'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='odpoveducastnika', |
||||
|
options={'ordering': ['-timestamp']}, |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='odpoveducastnika', |
||||
|
name='timestamp', |
||||
|
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Timestamp'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='odpoveducastnika', |
||||
|
name='odpoved', |
||||
|
field=models.TextField(verbose_name='Tajenka bez diakritiky'), |
||||
|
), |
||||
|
] |
@ -0,0 +1,18 @@ |
|||||
|
# Generated by Django 3.2.22 on 2023-10-16 17:51 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('sifrovacka', '0002_auto_20231015_1944'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='odpoveducastnika', |
||||
|
name='uspech', |
||||
|
field=models.BooleanField(default=False, verbose_name='Úspěch'), |
||||
|
), |
||||
|
] |
@ -0,0 +1,27 @@ |
|||||
|
from django.db import models |
||||
|
from django.utils import timezone |
||||
|
|
||||
|
from seminar.models.personalni import Resitel |
||||
|
|
||||
|
|
||||
|
# Create your models here. |
||||
|
|
||||
|
|
||||
|
class OdpovedUcastnika(models.Model): |
||||
|
class Meta: |
||||
|
ordering = ["-timestamp"] |
||||
|
|
||||
|
resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE) |
||||
|
odpoved = models.TextField("Tajenka bez diakritiky", blank=False, null=False,) |
||||
|
sifra = models.IntegerField("Číslo šifry", blank=False, null=False,) |
||||
|
timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now) |
||||
|
uspech = models.BooleanField("Úspěch", blank=False, null=False, default=False) |
||||
|
|
||||
|
|
||||
|
class SpravnaOdpoved(models.Model): |
||||
|
odpoved = models.TextField(blank=False, null=False,) |
||||
|
sifra = models.IntegerField(blank=False, null=False,) |
||||
|
skryty_text = models.TextField(blank=False, null=False,) |
||||
|
|
||||
|
def __str__(self): |
||||
|
return f"{self.sifra}: {self.odpoved}" |
@ -0,0 +1,25 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
<h1>{% block nadpis1a %}Šifrovačka odpovědi{% endblock nadpis1a %}</h1> |
||||
|
|
||||
|
<table class="dosla_reseni"> |
||||
|
<tr> |
||||
|
<th>Timestamp</th> |
||||
|
<th>Řešitel</th> |
||||
|
<th>Šifra</th> |
||||
|
<th>Odpověď</th> |
||||
|
</tr> |
||||
|
|
||||
|
{% for u in object_list %} |
||||
|
<tr> |
||||
|
<td>{{ u.timestamp }}</td> |
||||
|
<td>{{ u.resitel }}</td> |
||||
|
<td>{{ u.sifra }}</td> |
||||
|
<td style="color: {% if u.uspech %}green{% else %}red{% endif %};">{{ u.odpoved }}</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
</table> |
||||
|
|
||||
|
{% endblock content %} |
@ -0,0 +1,46 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1> |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<h2>Zadat tajenku šifry:</h2> |
||||
|
|
||||
|
<form action="{% url 'sifrovacka' %}" method="post"> |
||||
|
<table class="form"> |
||||
|
{{form.non_field_errors}} |
||||
|
{% for field in form %} |
||||
|
<tr> |
||||
|
<td> |
||||
|
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}"> |
||||
|
{{ field.label }} |
||||
|
</label> |
||||
|
|
||||
|
</td> |
||||
|
|
||||
|
<td {% if field.help_text %} class="field-with-comment"{% endif %}> |
||||
|
{{ field }} |
||||
|
<span class="field-comment">{{ field.help_text|safe }}</span> |
||||
|
</td> |
||||
|
|
||||
|
</tr> |
||||
|
|
||||
|
|
||||
|
{% if field.errors %} |
||||
|
<tr> |
||||
|
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td> |
||||
|
</tr> |
||||
|
{% endif %} |
||||
|
{% endfor %} |
||||
|
</table> |
||||
|
|
||||
|
{% csrf_token %} |
||||
|
|
||||
|
<input type="submit" value="Tak pravím!"> |
||||
|
</form> |
||||
|
|
||||
|
{% endblock content %} |
@ -0,0 +1,17 @@ |
|||||
|
from django.urls import path |
||||
|
|
||||
|
from seminar.utils import org_required, resitel_or_org_required |
||||
|
from .views import SifrovackaView, SifrovackaListView |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path( |
||||
|
'', |
||||
|
resitel_or_org_required(SifrovackaView.as_view()), |
||||
|
name='sifrovacka' |
||||
|
), |
||||
|
path( |
||||
|
'odpovedi/', |
||||
|
org_required(SifrovackaListView.as_view()), |
||||
|
name='sifrovacka_odpovedi' |
||||
|
), |
||||
|
] |
@ -0,0 +1,33 @@ |
|||||
|
from django.urls import reverse |
||||
|
from django.views.generic import FormView, ListView |
||||
|
|
||||
|
from seminar.views import formularOKView |
||||
|
from .forms import SifrovackaForm |
||||
|
from .models import OdpovedUcastnika, SpravnaOdpoved |
||||
|
from seminar.models.personalni import Resitel |
||||
|
|
||||
|
|
||||
|
# Create your views here. |
||||
|
|
||||
|
class SifrovackaView(FormView): |
||||
|
template_name = 'sifrovacka/sifrovacka.html' |
||||
|
form_class = SifrovackaForm |
||||
|
|
||||
|
def form_valid(self, form): |
||||
|
instance = form.save(commit=False) |
||||
|
resitel = Resitel.objects.get(osoba__user=self.request.user) |
||||
|
instance.resitel = resitel |
||||
|
instance.save() |
||||
|
sifra = SpravnaOdpoved.objects.filter(sifra=instance.sifra, odpoved__iexact=instance.odpoved.strip()).first() |
||||
|
if sifra is None: |
||||
|
return formularOKView(self.request, f'<h1>Bohužel vám hvězdy nebyly nakloněny. Rozumějte <i>máte to blbě</i>.</h1> <p><a href="{reverse("sifrovacka")}">Zkusit znovu.</a></p><br><br><br>') |
||||
|
|
||||
|
instance.uspech = True |
||||
|
instance.save() |
||||
|
|
||||
|
return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Odevzdat další.</a></p><br><br><br>') |
||||
|
|
||||
|
|
||||
|
class SifrovackaListView(ListView): |
||||
|
template_name = 'sifrovacka/odpovedi_list.html' |
||||
|
model = OdpovedUcastnika |
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,19 @@ |
|||||
|
{#{% extends "error_base.html" %} Z toho nedědíme, protože se nemá přecházet na titulní stránku. #} |
||||
|
{% extends "base.html" %} |
||||
|
|
||||
|
{% load static %} |
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
<h2>{% block nadpis1a %}O-jo-jo-jo-joj{% endblock nadpis1a %}</h2> |
||||
|
|
||||
|
<p> |
||||
|
Problém se sušenkami či něčím podobným. Zkuste {% if url %}to prosím znovu: <a href="{{ url }}">{{ url }}</a>. Případně můžete {% endif %}přejít na <a href="/">titulní stránku</a>. |
||||
|
</p> |
||||
|
|
||||
|
<p>Pokud problém přetrvává obraťte se na nás přes e-mail: <a href="mailto:mam@matfyz.cz">mailto:mam@matfyz.cz</a> a pošlete nám následující popis chyby: <code>{{ reason }}</code></p> |
||||
|
|
||||
|
<img src="{% static 'various/img/zere_kostku.svg' %}"> |
||||
|
|
||||
|
|
||||
|
{% endblock %} |
@ -1,3 +1,13 @@ |
|||||
|
from django.http import HttpResponseForbidden |
||||
from django.shortcuts import render |
from django.shortcuts import render |
||||
|
|
||||
# Create your views here. |
# Create your views here. |
||||
|
|
||||
|
|
||||
|
def csrf_error(request, reason=""): |
||||
|
""" Jednoduchý „template view“ (třída to být nemůže) pro CSRF chyby """ |
||||
|
return render( |
||||
|
request, 'various/403_csrf.html', |
||||
|
{"url": request.META.get("HTTP_REFERER", None), "reason": reason}, |
||||
|
status=HttpResponseForbidden.status_code, |
||||
|
) |
||||
|
Loading…
Reference in new issue