Merge branch 'master' into split-apps
Aby se to snáz mergeovalo
This commit is contained in:
commit
5070a4d914
26 changed files with 435 additions and 115 deletions
|
@ -87,7 +87,6 @@ TEMPLATES = [
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.template.context_processors.request',
|
'django.template.context_processors.request',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
'sekizai.context_processors.sekizai',
|
|
||||||
'header_fotky.context_processors.vzhled',
|
'header_fotky.context_processors.vzhled',
|
||||||
'various.context_processors.rozliseni',
|
'various.context_processors.rozliseni',
|
||||||
'various.context_processors.april',
|
'various.context_processors.april',
|
||||||
|
@ -110,7 +109,6 @@ INSTALLED_APPS = (
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
'sekizai',
|
|
||||||
'reversion',
|
'reversion',
|
||||||
'django_countries',
|
'django_countries',
|
||||||
'solo',
|
'solo',
|
||||||
|
@ -120,9 +118,6 @@ INSTALLED_APPS = (
|
||||||
'dal',
|
'dal',
|
||||||
'dal_select2',
|
'dal_select2',
|
||||||
|
|
||||||
'crispy_forms',
|
|
||||||
'django_comments',
|
|
||||||
|
|
||||||
'django.contrib.flatpages',
|
'django.contrib.flatpages',
|
||||||
'django.contrib.humanize',
|
'django.contrib.humanize',
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ div.login-bar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
margin-top: -20px;
|
margin-top: -20px;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
z-index: 20;
|
z-index: 4086;
|
||||||
|
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
|
@ -199,22 +199,13 @@ h1 {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Comments */
|
|
||||||
|
|
||||||
#id_comment {
|
|
||||||
width: 100%;
|
|
||||||
height: 6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Headline & Header */
|
/* Headline & Header */
|
||||||
|
|
||||||
#title { /*dělá blbosti šířka, je to kvůli fixed pozici, zatím natvrdo, vyřešit*/
|
#title { /*dělá blbosti šířka, je to kvůli fixed pozici, zatím natvrdo, vyřešit*/
|
||||||
height: 55px;
|
height: 55px;
|
||||||
width: 970px;
|
width: 970px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 10;
|
z-index: 2048;
|
||||||
background-color: #e84e10;
|
background-color: #e84e10;
|
||||||
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
||||||
|
|
||||||
|
@ -1252,6 +1243,35 @@ div.gdpr {
|
||||||
background: rgb(253, 237, 213);
|
background: rgb(253, 237, 213);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Přichycování prvního sloupce a řádku*/
|
||||||
|
.dosla_reseni {
|
||||||
|
display: block;
|
||||||
|
max-height: 90vh;
|
||||||
|
max-width: 90vw;
|
||||||
|
overflow: auto;
|
||||||
|
margin-left: 5vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dosla_reseni thead tr {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dosla_reseni tr:nth-child(even) td:first-child, .dosla_reseni thead tr, .dosla_reseni thead tr:first-child td:first-child {
|
||||||
|
background: rgb(253, 237, 213);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dosla_reseni tr:nth-child(odd) td:first-child {
|
||||||
|
background: #fffbf6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dosla_reseni tr td:first-child {
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
/* */
|
||||||
|
|
||||||
|
|
||||||
.odevzdana_reseni tr th, .odevzdana_reseni tr td {
|
.odevzdana_reseni tr th, .odevzdana_reseni tr td {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
|
|
|
@ -1,29 +1,35 @@
|
||||||
/* Rozlišení mezi lokálním, test a produkčním webem */
|
/* Rozlišení mezi lokálním, test a produkčním webem */
|
||||||
|
|
||||||
.localweb {
|
body.localweb:before, body.localweb:after,
|
||||||
border-left: 20px solid greenyellow;
|
body.testweb:before, body.testweb:after,
|
||||||
border-right: 20px solid greenyellow;
|
body.suprodweb:before, body.suprodweb:after {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
width: 20px;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.localweb .login-bar {
|
body.localweb:before,
|
||||||
margin-left: -20px;
|
body.testweb:before,
|
||||||
|
body.suprodweb:before {
|
||||||
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.testweb {
|
body.localweb:after,
|
||||||
border-left: 20px solid darkorange;
|
body.testweb:after,
|
||||||
border-right: 20px solid darkorange;
|
body.suprodweb:after {
|
||||||
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.testweb .login-bar {
|
body.localweb:before, body.localweb:after {
|
||||||
margin-left: -20px;
|
background: greenyellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Produkční web z pohledu superuživatele */
|
body.testweb:before, body.testweb:after {
|
||||||
.suprodweb {
|
background: darkorange;
|
||||||
border-left: 20px solid red;
|
|
||||||
border-right: 20px solid red;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.suprodweb .login-bar {
|
body.suprodweb:before, body.suprodweb:after {
|
||||||
margin-left: -20px;
|
background: red;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% load static sekizai_tags %}
|
{% load static %}
|
||||||
{% load sitetree %}
|
{% load sitetree %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang='cs'>
|
<html lang='cs'>
|
||||||
|
@ -7,7 +7,6 @@
|
||||||
<title>{% block title %}{% block nadpis1a %}🦊{% endblock %} | Korespondenční seminář M&M{% endblock title %}</title>
|
<title>{% block title %}{% block nadpis1a %}🦊{% endblock %} | Korespondenční seminář M&M{% endblock title %}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="shortcut icon" href="{% static 'images/MATFYZ_MM_barevne.svg' %}" type="image/x-icon">
|
<link rel="shortcut icon" href="{% static 'images/MATFYZ_MM_barevne.svg' %}" type="image/x-icon">
|
||||||
{# {% render_block css %}#}
|
|
||||||
{% block custom_css %}{% endblock %}
|
{% block custom_css %}{% endblock %}
|
||||||
<link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet">
|
<link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet">
|
||||||
<link href="{% static 'css/bootstrap.css' %}" rel="stylesheet">
|
<link href="{% static 'css/bootstrap.css' %}" rel="stylesheet">
|
||||||
|
@ -189,6 +188,24 @@
|
||||||
walkText(document.body);
|
walkText(document.body);
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% render_block "js" %}
|
|
||||||
|
{% if april == 2024 %}
|
||||||
|
<script>
|
||||||
|
{# By https://stackoverflow.com/a/34559316 #}
|
||||||
|
function walkText(node) {
|
||||||
|
if (node.nodeType == 3) {
|
||||||
|
node.data = node.data.replace(/M&M/g, "W8W");
|
||||||
|
}
|
||||||
|
if (node.nodeType == 1 && node.nodeName != "SCRIPT") {
|
||||||
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
|
walkText(node.childNodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
walkText(document.body);
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block js %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -13,7 +13,6 @@ Soubor sloužící jako základní „router“, tj. zde se includují veškeré
|
||||||
- :mod:`api.urls`
|
- :mod:`api.urls`
|
||||||
- :mod:`treenode.urls`
|
- :mod:`treenode.urls`
|
||||||
- :mod:`aesop.urls`
|
- :mod:`aesop.urls`
|
||||||
- ``comments_dj/`` :mod:`django_comments.urls`
|
|
||||||
"""
|
"""
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||||
|
@ -62,9 +61,6 @@ urlpatterns = [
|
||||||
# Aesop (ma vlastni podadresare)
|
# Aesop (ma vlastni podadresare)
|
||||||
path('', include('aesop.urls')),
|
path('', include('aesop.urls')),
|
||||||
|
|
||||||
# Comments (interni i verejne)
|
|
||||||
path('comments_dj/', include('django_comments.urls')),
|
|
||||||
|
|
||||||
# REST API
|
# REST API
|
||||||
# path('api/', include(router.urls)),
|
# path('api/', include(router.urls)),
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ Do data (včetně): {{ filtr.reseni_do }}
|
||||||
<input type=submit value="Změň ročník">
|
<input type=submit value="Změň ročník">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div style="overflow-x: scroll;">
|
|
||||||
<table class="dosla_reseni">
|
<table class="dosla_reseni">
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td> {# Prázdná buňka v levém horním rohu #}
|
<td></td> {# Prázdná buňka v levém horním rohu #}
|
||||||
{% for p in problemy %}
|
{% for p in problemy %}
|
||||||
|
@ -32,6 +32,8 @@ Do data (včetně): {{ filtr.reseni_do }}
|
||||||
</th>
|
</th>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% for resitel,hodnoty in radky%}
|
{% for resitel,hodnoty in radky%}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
@ -52,8 +54,8 @@ Do data (včetně): {{ filtr.reseni_do }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,32 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
-c constraints.txt
|
-c constraints.txt
|
||||||
# basic libs
|
# basic libs
|
||||||
|
|
||||||
psycopg2
|
psycopg2 # PostgreSQL adaptér
|
||||||
html5lib
|
ipython # Interaktivní shell
|
||||||
ipython
|
Unidecode # Přepisuje unicode do ASCII (např. soubory nebo e-maily)
|
||||||
Pillow
|
Pillow
|
||||||
pilkit>=3.0 # Kvůli kompatibilitě s Pillow>=10.0.0
|
pilkit>=3.0 # Kvůli kompatibilitě s Pillow>=10.0.0
|
||||||
pytz
|
|
||||||
six
|
|
||||||
pexpect
|
|
||||||
traitlets
|
|
||||||
Unidecode
|
|
||||||
|
|
||||||
# Django and modules
|
# Django and modules
|
||||||
|
|
||||||
Django<5.0
|
Django<5.0
|
||||||
#django-bootstrap-sass
|
#django-bootstrap-sass
|
||||||
django-mptt
|
django-reversion # Version control na datech v databázi
|
||||||
django-reversion
|
django-countries # Políčko ve formu / field v modelu ohledně států
|
||||||
django-sekizai
|
django-solo # Singleton model (speciálně Nastavení)
|
||||||
django-countries
|
django-ckeditor # Editor htmlka (hlavně v adminu u flatpages)
|
||||||
django-solo
|
|
||||||
django-ckeditor
|
|
||||||
django-cleanup # Uklízí media/ od smazaných „databázových“ souborů
|
django-cleanup # Uklízí media/ od smazaných „databázových“ souborů
|
||||||
django-flat-theme
|
django-taggit # Taggy v djangu (speciálně zaměření problémů)
|
||||||
django-taggit
|
django-autocomplete-light>=3.9.0 # Automatické doplňování (problémů, účastníků, …) ve formulářích
|
||||||
django-autocomplete-light>=3.9.0
|
django-imagekit # Všechny možné obrázky v Djangu
|
||||||
django-crispy-forms
|
django-polymorphic # Polymorfismus na django modelech (hlavně Problém nebo treenode)
|
||||||
django-imagekit
|
django-sitetree # Struktura stránek, hlavně pro meníčko
|
||||||
django-polymorphic
|
django_reverse_admin # Lepší handlování OneToOne fieldů v adminu
|
||||||
django-sitetree
|
|
||||||
django_reverse_admin
|
|
||||||
django-rest-framework
|
django-rest-framework
|
||||||
django-webpack-loader
|
django-webpack-loader
|
||||||
django-rest-polymorphic
|
django-rest-polymorphic
|
||||||
|
|
||||||
# Comments
|
|
||||||
django-contrib-comments
|
|
||||||
|
|
||||||
# debug tools/extensions
|
# debug tools/extensions
|
||||||
|
|
||||||
django-debug-toolbar
|
django-debug-toolbar
|
||||||
|
|
|
@ -38,9 +38,11 @@
|
||||||
<h2> Orgovské odkazy </h2>
|
<h2> Orgovské odkazy </h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="obalky.pdf">Obálky (PDF)</a></li>
|
<li><a href="obalky.pdf">Obálky (PDF)</a></li>
|
||||||
<li><a href="tituly.tex" download>Tituly (TeX)</a></li>
|
<li><a href="tituly.tex" download>Tituly (TeX, 2. deadline předchozího čísla a 1.deadline tohoto)</a></li>
|
||||||
<li><a href="vysledkovka.tex" download>Výsledkovka (TeX)</a></li>
|
<li><a href="vysledkovka.tex" download>Výsledkovka (TeX, 2. deadline předchozího čísla a 1.deadline tohoto)</a></li>
|
||||||
<li><a href="odmeny/{{prevcislo.rocnik.rocnik}}.{{prevcislo.poradi}}/">Odměny</a></li>
|
<li><a href="odmeny/{{prevcislo.rocnik.rocnik}}.{{prevcislo.poradi}}/">Odměny</a></li>
|
||||||
|
<li><a href="{% url "seminar_rocnik_titul" rocnik=cislo.rocnik.rocnik %}" download="posledni_tituly.tex">Tituly do závěrečného čísla (TeX, 2. deadline předchozího čísla a oba tohoto)</a></li>
|
||||||
|
<li><a href="{% url "seminar_rocnik_posledni_vysledkovka" rocnik=cislo.rocnik.rocnik %}" download>Výsledkovka závěrečného čísla ročníku (TeX, 2. deadline předchozího čísla a oba tohoto)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% load comments %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div {% if not problem.verejne and user.je_org %}class="mam-org-only"{% endif %}>
|
<div {% if not problem.verejne and user.je_org %}class="mam-org-only"{% endif %}>
|
||||||
{% block problem %}
|
{% block problem %}
|
||||||
|
@ -13,10 +11,6 @@
|
||||||
<h2>Text - org</h2>
|
<h2>Text - org</h2>
|
||||||
{{ problem.text_org |safe }}
|
{{ problem.text_org |safe }}
|
||||||
|
|
||||||
<h2>Diskuse - org</h2>
|
|
||||||
{% render_comment_list for object %}
|
|
||||||
{% render_comment_form for object %}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -120,8 +120,7 @@
|
||||||
{% if user.je_org %}
|
{% if user.je_org %}
|
||||||
<div class='mam-org-only'>
|
<div class='mam-org-only'>
|
||||||
<p><a href='vysledkovka.tex' download>Výsledkovka ročníku (LaTeX, včetně neveřejných)</a></p>
|
<p><a href='vysledkovka.tex' download>Výsledkovka ročníku (LaTeX, včetně neveřejných)</a></p>
|
||||||
<p><a href="tituly.tex" download>Tituly (TeX, do konce ročníku = pro poslední číslo)</a></p>
|
<p><a href="tituly.tex" download>Tituly (TeX, včetně neveřejných, všechny, nevhodné do mamtexu)</a></p>
|
||||||
<p><a href="posledni_vysledkovka.tex" download>Výsledkovka posledního čísla</a></p>
|
|
||||||
{# FIXME: Sice to sem asi nepatří sémanticky, ale bylo to nejjednodušší… #}
|
{# FIXME: Sice to sem asi nepatří sémanticky, ale bylo to nejjednodušší… #}
|
||||||
<p><a href='{% url 'seminar_rocnik_resitele_csv' rocnik=rocnik.rocnik %}' download>CSV export řešitelů</a></p>
|
<p><a href='{% url 'seminar_rocnik_resitele_csv' rocnik=rocnik.rocnik %}' download>CSV export řešitelů</a></p>
|
||||||
<h2>Výsledková listina včetně neveřejných bodů</h2>
|
<h2>Výsledková listina včetně neveřejných bodů</h2>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from django import template
|
from django import template
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from pytz import timezone
|
|
||||||
from mamweb.settings import TIME_ZONE
|
from mamweb.settings import TIME_ZONE
|
||||||
import logging
|
import logging
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
|
@ -4,7 +4,6 @@ import datetime
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from pytz import timezone
|
|
||||||
import random
|
import random
|
||||||
import lorem
|
import lorem
|
||||||
import django.contrib.auth
|
import django.contrib.auth
|
||||||
|
@ -177,13 +176,13 @@ def gen_organizatori(rnd, osoby, last_rocnik):
|
||||||
year=1993 + pusobnost,
|
year=1993 + pusobnost,
|
||||||
month=rnd.randint(1, 12),
|
month=rnd.randint(1, 12),
|
||||||
day=rnd.randint(1, 28),
|
day=rnd.randint(1, 28),
|
||||||
tzinfo=timezone('CET'),
|
tzinfo=datetime.timezone.utc,
|
||||||
)
|
)
|
||||||
do = datetime.datetime(
|
do = datetime.datetime(
|
||||||
year=od.year + rnd.randint(1, 6),
|
year=od.year + rnd.randint(1, 6),
|
||||||
month=rnd.randint(1, 12),
|
month=rnd.randint(1, 12),
|
||||||
day=rnd.randint(1, 28),
|
day=rnd.randint(1, 28),
|
||||||
tzinfo=timezone('CET'),
|
tzinfo=datetime.timezone.utc,
|
||||||
)
|
)
|
||||||
#aktualni organizatori jeste nemaji vyplnene organizuje_do
|
#aktualni organizatori jeste nemaji vyplnene organizuje_do
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ from django.http import Http404
|
||||||
from django.db.models import Q, Sum, Count
|
from django.db.models import Q, Sum, Count
|
||||||
from django.views.generic.base import RedirectView
|
from django.views.generic.base import RedirectView
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.contrib.staticfiles.finders import find
|
||||||
|
|
||||||
import seminar.models as s
|
import seminar.models as s
|
||||||
import seminar.models as m
|
import seminar.models as m
|
||||||
|
@ -36,6 +37,7 @@ import unicodedata
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
|
import http
|
||||||
|
|
||||||
from seminar.utils import aktivniResitele
|
from seminar.utils import aktivniResitele
|
||||||
|
|
||||||
|
@ -562,17 +564,25 @@ def cisloObalkyView(request, rocnik, cislo):
|
||||||
|
|
||||||
|
|
||||||
def obalkyView(request, resitele):
|
def obalkyView(request, resitele):
|
||||||
|
if len(resitele) == 0:
|
||||||
|
return HttpResponse(
|
||||||
|
render(request, 'universal.html', {
|
||||||
|
'title': 'Není pro koho vyrobit obálky.',
|
||||||
|
'text': 'Právě ses pokusil/a vygenerovat obálky pro prázdnou množinu lidí. Můžeš to zkusit změnit, případně se zeptej webařů :-)',
|
||||||
|
}),
|
||||||
|
status=http.HTTPStatus.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content
|
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content
|
||||||
|
|
||||||
tempdir = tempfile.mkdtemp()
|
with tempfile.TemporaryDirectory() as tempdir:
|
||||||
with open(tempdir+"/obalky.tex","w") as texfile:
|
with open(tempdir+"/obalky.tex","w") as texfile:
|
||||||
texfile.write(tex.decode())
|
texfile.write(tex.decode())
|
||||||
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir)
|
shutil.copy(find('seminar/lisak.pdf'), tempdir)
|
||||||
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
|
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
|
||||||
|
|
||||||
with open(tempdir+"/obalky.pdf","rb") as pdffile:
|
with open(tempdir+"/obalky.pdf","rb") as pdffile:
|
||||||
response = HttpResponse(pdffile.read(), content_type='application/pdf')
|
response = HttpResponse(pdffile.read(), content_type='application/pdf')
|
||||||
shutil.rmtree(tempdir)
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import OdpovedUcastnika, SpravnaOdpoved
|
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
|
||||||
admin.site.register(OdpovedUcastnika)
|
admin.site.register(OdpovedUcastnika)
|
||||||
admin.site.register(SpravnaOdpoved)
|
admin.site.register(SpravnaOdpoved)
|
||||||
|
admin.site.register(Napoveda)
|
||||||
|
admin.site.register(NapovezenoUcastnikovi)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms import ModelForm, Textarea
|
from django.forms import ModelForm, Textarea
|
||||||
from .models import OdpovedUcastnika, SpravnaOdpoved
|
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
|
||||||
|
|
||||||
|
|
||||||
class SifrovackaForm(ModelForm):
|
class SifrovackaForm(ModelForm):
|
||||||
|
@ -16,3 +16,15 @@ class SifrovackaForm(ModelForm):
|
||||||
if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0:
|
if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0:
|
||||||
raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.")
|
raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.")
|
||||||
return sifra
|
return sifra
|
||||||
|
|
||||||
|
|
||||||
|
class NapovedaForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = NapovezenoUcastnikovi
|
||||||
|
fields = ["sifra",]
|
||||||
|
|
||||||
|
def clean_sifra(self):
|
||||||
|
sifra = self.cleaned_data.get('sifra')
|
||||||
|
if Napoveda.objects.filter(sifra=sifra).count() == 0:
|
||||||
|
raise ValidationError("K tomuto číslu šifry nemáme nápovědu. Zkontrolujte si ho prosím.")
|
||||||
|
return sifra
|
||||||
|
|
65
sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py
Normal file
65
sifrovacka/migrations/0004_napoveda_napovezenoucastnikovi.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# Generated by Django 4.2.8 on 2024-04-14 12:57
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
(
|
||||||
|
"seminar",
|
||||||
|
"0114_related_name_se_zmenilo_a_django_chce_migraci_tak_dostane_migraci",
|
||||||
|
),
|
||||||
|
("sifrovacka", "0003_odpoveducastnika_uspech"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Napoveda",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("text", models.TextField()),
|
||||||
|
("sifra", models.IntegerField()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="NapovezenoUcastnikovi",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("sifra", models.IntegerField(verbose_name="Číslo šifry")),
|
||||||
|
(
|
||||||
|
"timestamp",
|
||||||
|
models.DateTimeField(
|
||||||
|
default=django.utils.timezone.now, verbose_name="Timestamp"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"resitel",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="seminar.resitel",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"ordering": ["-timestamp"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -25,3 +25,20 @@ class SpravnaOdpoved(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.sifra}: {self.odpoved}"
|
return f"{self.sifra}: {self.odpoved}"
|
||||||
|
|
||||||
|
|
||||||
|
class NapovezenoUcastnikovi(models.Model):
|
||||||
|
class Meta:
|
||||||
|
ordering = ["-timestamp"]
|
||||||
|
|
||||||
|
resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE)
|
||||||
|
sifra = models.IntegerField("Číslo šifry", blank=False, null=False,)
|
||||||
|
timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now)
|
||||||
|
|
||||||
|
|
||||||
|
class Napoveda(models.Model):
|
||||||
|
text = models.TextField(blank=False, null=False,)
|
||||||
|
sifra = models.IntegerField(blank=False, null=False,)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.sifra}: {self.text}"
|
||||||
|
|
50
sifrovacka/templates/sifrovacka/napoveda.html
Normal file
50
sifrovacka/templates/sifrovacka/napoveda.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h2>Získat nápovědu k šifře:</h2>
|
||||||
|
|
||||||
|
<form action="{% url 'sifrovacka_napoveda' %}" 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="Chci nápovědu">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p><a href="{% url 'sifrovacka' %}">Nechceme nápovědu, známe řešení!</a></p>
|
||||||
|
|
||||||
|
<p><a href="{% url 'sifrovacka_preskoceni' %}">Přeskoč šifru</a></p>
|
||||||
|
|
||||||
|
{% endblock content %}
|
23
sifrovacka/templates/sifrovacka/napovedy_list.html
Normal file
23
sifrovacka/templates/sifrovacka/napovedy_list.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>{% block nadpis1a %}Šifrovačka vzaté nápovědy{% endblock nadpis1a %}</h1>
|
||||||
|
|
||||||
|
<table class="dosla_reseni">
|
||||||
|
<tr>
|
||||||
|
<th>Timestamp</th>
|
||||||
|
<th>Řešitel</th>
|
||||||
|
<th>Šifra</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% for u in object_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ u.timestamp }}</td>
|
||||||
|
<td>{{ u.resitel }}</td>
|
||||||
|
<td>{{ u.sifra }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock content %}
|
54
sifrovacka/templates/sifrovacka/preskoceni.html
Normal file
54
sifrovacka/templates/sifrovacka/preskoceni.html
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h2>Přeskočit šifru:</h2>
|
||||||
|
|
||||||
|
<form action="{% url 'sifrovacka_preskoceni' %}" method="post">
|
||||||
|
<table class="form">
|
||||||
|
{{form.non_field_errors}}
|
||||||
|
{% for field in form %}
|
||||||
|
{% if field.id_for_label != "id_odpoved" %}
|
||||||
|
<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 %}
|
||||||
|
{% else %}
|
||||||
|
{{ field.as_hidden }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<input type="submit" value="Chceme další stanoviště bez vyřešení šifry">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p><a href="{% url 'sifrovacka' %}">Nechceme přeskočit, známe řešení!</a></p>
|
||||||
|
|
||||||
|
<p><a href="{% url 'sifrovacka_napoveda' %}">Nechceme přeskakovat, ale nápověda by se šikla.</a></p>
|
||||||
|
|
||||||
|
{% endblock content %}
|
|
@ -43,4 +43,8 @@
|
||||||
<input type="submit" value="Tak pravím!">
|
<input type="submit" value="Tak pravím!">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<p><a href="{% url 'sifrovacka_napoveda' %}">Získat nápovědu</a></p>
|
||||||
|
|
||||||
|
<p><a href="{% url 'sifrovacka_preskoceni' %}">Přeskoč šifru</a></p>
|
||||||
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from seminar.utils import org_required, resitel_or_org_required
|
from seminar.utils import org_required, resitel_or_org_required
|
||||||
from .views import SifrovackaView, SifrovackaListView
|
from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView, PreskoceniView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(
|
path(
|
||||||
|
@ -14,4 +14,19 @@ urlpatterns = [
|
||||||
org_required(SifrovackaListView.as_view()),
|
org_required(SifrovackaListView.as_view()),
|
||||||
name='sifrovacka_odpovedi'
|
name='sifrovacka_odpovedi'
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
'napoveda/',
|
||||||
|
resitel_or_org_required(NapovedaView.as_view()),
|
||||||
|
name='sifrovacka_napoveda'
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'napovedy/',
|
||||||
|
org_required(NapovedaListView.as_view()),
|
||||||
|
name='sifrovacka_napovedy'
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'preskoceni/',
|
||||||
|
resitel_or_org_required(PreskoceniView.as_view()),
|
||||||
|
name='sifrovacka_preskoceni'
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,8 +2,8 @@ from django.urls import reverse
|
||||||
from django.views.generic import FormView, ListView
|
from django.views.generic import FormView, ListView
|
||||||
|
|
||||||
from seminar.views import formularOKView
|
from seminar.views import formularOKView
|
||||||
from .forms import SifrovackaForm
|
from .forms import SifrovackaForm, NapovedaForm
|
||||||
from .models import OdpovedUcastnika, SpravnaOdpoved
|
from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi
|
||||||
from seminar.models import Resitel
|
from seminar.models import Resitel
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,10 +24,47 @@ class SifrovackaView(FormView):
|
||||||
|
|
||||||
instance.uspech = True
|
instance.uspech = True
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
||||||
return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Odevzdat další.</a></p><br><br><br>')
|
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):
|
class SifrovackaListView(ListView):
|
||||||
template_name = 'sifrovacka/odpovedi_list.html'
|
template_name = 'sifrovacka/odpovedi_list.html'
|
||||||
model = OdpovedUcastnika
|
model = OdpovedUcastnika
|
||||||
|
|
||||||
|
|
||||||
|
class NapovedaView(FormView):
|
||||||
|
template_name = 'sifrovacka/napoveda.html'
|
||||||
|
form_class = NapovedaForm
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
instance = form.save(commit=False)
|
||||||
|
resitel = Resitel.objects.get(osoba__user=self.request.user)
|
||||||
|
instance.resitel = resitel
|
||||||
|
|
||||||
|
if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra=instance.sifra).first() is None:
|
||||||
|
instance.save()
|
||||||
|
|
||||||
|
napoveda = Napoveda.objects.filter(sifra=instance.sifra).first()
|
||||||
|
return formularOKView(self.request, f'<h1>Nápověda k šifře číslo {instance.sifra} je:</h1><p>{napoveda.text}</p> <p><a href="{reverse("sifrovacka")}">Odevzdat řešení.</a></p><br><br><br>')
|
||||||
|
|
||||||
|
|
||||||
|
class NapovedaListView(ListView):
|
||||||
|
template_name = 'sifrovacka/napovedy_list.html'
|
||||||
|
model = NapovezenoUcastnikovi
|
||||||
|
|
||||||
|
|
||||||
|
class PreskoceniView(FormView):
|
||||||
|
template_name = 'sifrovacka/preskoceni.html'
|
||||||
|
form_class = SifrovackaForm
|
||||||
|
initial = {"odpoved": "=======PŘESKOČENO======="}
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
instance = form.save(commit=False)
|
||||||
|
instance.odpoved = "=======PŘESKOČENO======="
|
||||||
|
resitel = Resitel.objects.get(osoba__user=self.request.user)
|
||||||
|
instance.resitel = resitel
|
||||||
|
instance.save()
|
||||||
|
sifra = SpravnaOdpoved.objects.filter(sifra=instance.sifra).first() # FIXME co když je více "správných" odpovědí?
|
||||||
|
|
||||||
|
return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Zpět na odevzdávátko.</a></p><br><br><br>')
|
||||||
|
|
|
@ -58,16 +58,16 @@
|
||||||
{# Účastníci #}
|
{# Účastníci #}
|
||||||
<h2>Soustředění se zúčastnili tito účastníci:</h2>
|
<h2>Soustředění se zúčastnili tito účastníci:</h2>
|
||||||
<p>
|
<p>
|
||||||
{% for i in soustredeni.soustredeni_ucastnici_set.all %}
|
{% for i in soustredeni.ucastnici.all %}
|
||||||
{{i.resitel}}{% if forloop.last %}.{% else %},{% endif %}
|
{{i}}{% if forloop.last %}.{% else %},{% endif %}
|
||||||
{% empty %}
|
{% empty %}
|
||||||
Nic!
|
Nic!
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
<h2>Soustředění se účastnili tito organizátoři:</h2>
|
<h2>Soustředění se účastnili tito organizátoři:</h2>
|
||||||
<p>
|
<p>
|
||||||
{% for i in soustredeni.soustredeni_organizatori_set.all %}
|
{% for i in soustredeni.organizatori.all %}
|
||||||
{{i.organizator}}{% if forloop.last %}.{% else %},{% endif %}
|
{{i}}{% if forloop.last %}.{% else %},{% endif %}
|
||||||
{% empty %}
|
{% empty %}
|
||||||
Nic!
|
Nic!
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import tempfile
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import http
|
||||||
|
|
||||||
from seminar.views import obalkyView
|
from seminar.views import obalkyView
|
||||||
|
|
||||||
|
@ -17,6 +18,19 @@ class SoustredeniListView(generic.ListView):
|
||||||
model = Soustredeni
|
model = Soustredeni
|
||||||
template_name = 'soustredeni/seznam_soustredeni.html'
|
template_name = 'soustredeni/seznam_soustredeni.html'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if not self.request.user.je_org:
|
||||||
|
return super().get_queryset()
|
||||||
|
return (
|
||||||
|
Soustredeni.objects
|
||||||
|
.prefetch_related(
|
||||||
|
"ucastnici", "ucastnici__osoba",
|
||||||
|
"organizatori", "organizatori__osoba",
|
||||||
|
"galerie_set",
|
||||||
|
)
|
||||||
|
.select_related("rocnik")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def soustredeniObalkyView(request, soustredeni):
|
def soustredeniObalkyView(request, soustredeni):
|
||||||
soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
|
soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
|
||||||
|
@ -63,17 +77,25 @@ def soustredeniUcastniciExportView(request, soustredeni):
|
||||||
def soustredeniStvrzenkyView(request, soustredeni):
|
def soustredeniStvrzenkyView(request, soustredeni):
|
||||||
soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
|
soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
|
||||||
ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
|
ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
|
||||||
|
if ucastnici.count() == 0:
|
||||||
|
return HttpResponse(
|
||||||
|
render(request, 'universal.html', {
|
||||||
|
'title': 'Není pro koho vyrobit stvrzenky.',
|
||||||
|
'text': 'Právě ses pokusil/a vygenerovat stvrzenky pro prázdnou množinu lidí. Můžeš to zkusit změnit, případně se zeptej webařů :-)',
|
||||||
|
}),
|
||||||
|
status=http.HTTPStatus.NOT_FOUND,
|
||||||
|
)
|
||||||
castka = Nastaveni.get_solo().cena_sous
|
castka = Nastaveni.get_solo().cena_sous
|
||||||
tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content
|
tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content
|
||||||
|
|
||||||
tempdir = Path(tempfile.mkdtemp())
|
with tempfile.TemporaryDirectory() as tempdirfn:
|
||||||
with open(tempdir / "stvrzenky.tex", "w") as texfile:
|
tempdir = Path(tempdirfn)
|
||||||
texfile.write(tex.decode())
|
with open(tempdir / "stvrzenky.tex", "w") as texfile:
|
||||||
|
texfile.write(tex.decode())
|
||||||
|
|
||||||
shutil.copy(find('images/logomm.pdf'), tempdir)
|
shutil.copy(find('images/logomm.pdf'), tempdir)
|
||||||
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
|
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
|
||||||
|
|
||||||
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
|
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
|
||||||
response = HttpResponse(pdffile.read(), content_type='application/pdf')
|
response = HttpResponse(pdffile.read(), content_type='application/pdf')
|
||||||
shutil.rmtree(tempdir)
|
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -1,19 +1,10 @@
|
||||||
{% extends "seminar/archiv/base.html" %}
|
{% extends "seminar/archiv/base.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load sekizai_tags %}
|
|
||||||
|
|
||||||
{# toto z nejakeho duvodu nefunguje #}
|
|
||||||
{% addtoblock css %}
|
|
||||||
dfsdfs
|
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'css/mamweb-dev.css' %}" />
|
|
||||||
{% endaddtoblock "css" %}
|
|
||||||
|
|
||||||
{% block custom_css %}
|
{% block custom_css %}
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'css/mamweb-dev.css' %}" />
|
<link rel="stylesheet" type="text/css" href="{% static 'css/mamweb-dev.css' %}" />
|
||||||
{% endblock custom_css %}
|
{% endblock custom_css %}
|
||||||
|
|
||||||
{% load comments %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<ul>
|
<ul>
|
||||||
{% for obj in object_list %}
|
{% for obj in object_list %}
|
||||||
|
|
Loading…
Reference in a new issue