Merge branch 'master' into split-apps

Aby se to snáz mergeovalo
This commit is contained in:
Pavel "LEdoian" Turinsky 2024-04-30 22:20:06 +02:00
commit 5070a4d914
26 changed files with 435 additions and 115 deletions

View file

@ -87,7 +87,6 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.request',
'django.contrib.messages.context_processors.messages',
'sekizai.context_processors.sekizai',
'header_fotky.context_processors.vzhled',
'various.context_processors.rozliseni',
'various.context_processors.april',
@ -110,7 +109,6 @@ INSTALLED_APPS = (
'django.contrib.auth',
# Utilities
'sekizai',
'reversion',
'django_countries',
'solo',
@ -120,9 +118,6 @@ INSTALLED_APPS = (
'dal',
'dal_select2',
'crispy_forms',
'django_comments',
'django.contrib.flatpages',
'django.contrib.humanize',

View file

@ -39,7 +39,7 @@ div.login-bar {
position: fixed;
margin-top: -20px;
min-height: 20px;
z-index: 20;
z-index: 4086;
padding-left: 5px;
padding-right: 5px;
@ -199,22 +199,13 @@ h1 {
margin-top: 0px;
}
/* Comments */
#id_comment {
width: 100%;
height: 6em;
}
/* Headline & Header */
#title { /*dělá blbosti šířka, je to kvůli fixed pozici, zatím natvrdo, vyřešit*/
height: 55px;
width: 970px;
position: fixed;
z-index: 10;
z-index: 2048;
background-color: #e84e10;
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
@ -1252,6 +1243,35 @@ div.gdpr {
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 {
border: 1px solid black;

View file

@ -1,29 +1,35 @@
/* Rozlišení mezi lokálním, test a produkčním webem */
.localweb {
border-left: 20px solid greenyellow;
border-right: 20px solid greenyellow;
body.localweb:before, body.localweb:after,
body.testweb:before, body.testweb:after,
body.suprodweb:before, body.suprodweb:after {
content: "";
position: fixed;
width: 20px;
height: 100%;
top: 0;
}
.localweb .login-bar {
margin-left: -20px;
body.localweb:before,
body.testweb:before,
body.suprodweb:before {
left: 0;
}
.testweb {
border-left: 20px solid darkorange;
border-right: 20px solid darkorange;
body.localweb:after,
body.testweb:after,
body.suprodweb:after {
right: 0;
}
.testweb .login-bar {
margin-left: -20px;
body.localweb:before, body.localweb:after {
background: greenyellow;
}
/* Produkční web z pohledu superuživatele */
.suprodweb {
border-left: 20px solid red;
border-right: 20px solid red;
body.testweb:before, body.testweb:after {
background: darkorange;
}
.suprodweb .login-bar {
margin-left: -20px;
body.suprodweb:before, body.suprodweb:after {
background: red;
}

View file

@ -1,4 +1,4 @@
{% load static sekizai_tags %}
{% load static %}
{% load sitetree %}
<!DOCTYPE html>
<html lang='cs'>
@ -7,7 +7,6 @@
<title>{% block title %}{% block nadpis1a %}🦊{% endblock %} | Korespondenční seminář M&amp;M{% endblock title %}</title>
<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">
{# {% render_block css %}#}
{% block custom_css %}{% endblock %}
<link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet">
<link href="{% static 'css/bootstrap.css' %}" rel="stylesheet">
@ -189,6 +188,24 @@
walkText(document.body);
</script>
{% 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>
</html>

View file

@ -13,7 +13,6 @@ Soubor sloužící jako základní „router“, tj. zde se includují veškeré
- :mod:`api.urls`
- :mod:`treenode.urls`
- :mod:`aesop.urls`
- ``comments_dj/`` :mod:`django_comments.urls`
"""
from django.urls import path, include
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
@ -62,9 +61,6 @@ urlpatterns = [
# Aesop (ma vlastni podadresare)
path('', include('aesop.urls')),
# Comments (interni i verejne)
path('comments_dj/', include('django_comments.urls')),
# REST API
# path('api/', include(router.urls)),

View file

@ -21,8 +21,8 @@ Do data (včetně): {{ filtr.reseni_do }}
<input type=submit value="Změň ročník">
</form>
<div style="overflow-x: scroll;">
<table class="dosla_reseni">
<thead>
<tr>
<td></td> {# Prázdná buňka v levém horním rohu #}
{% for p in problemy %}
@ -32,6 +32,8 @@ Do data (včetně): {{ filtr.reseni_do }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for resitel,hodnoty in radky%}
<tr>
<td>
@ -52,8 +54,8 @@ Do data (včetně): {{ filtr.reseni_do }}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View file

@ -1,43 +1,32 @@
# -*- coding: utf-8 -*-
-c constraints.txt
# basic libs
psycopg2
html5lib
ipython
psycopg2 # PostgreSQL adaptér
ipython # Interaktivní shell
Unidecode # Přepisuje unicode do ASCII (např. soubory nebo e-maily)
Pillow
pilkit>=3.0 # Kvůli kompatibilitě s Pillow>=10.0.0
pytz
six
pexpect
traitlets
Unidecode
# Django and modules
Django<5.0
#django-bootstrap-sass
django-mptt
django-reversion
django-sekizai
django-countries
django-solo
django-ckeditor
django-reversion # Version control na datech v databázi
django-countries # Políčko ve formu / field v modelu ohledně států
django-solo # Singleton model (speciálně Nastavení)
django-ckeditor # Editor htmlka (hlavně v adminu u flatpages)
django-cleanup # Uklízí media/ od smazaných „databázových“ souborů
django-flat-theme
django-taggit
django-autocomplete-light>=3.9.0
django-crispy-forms
django-imagekit
django-polymorphic
django-sitetree
django_reverse_admin
django-taggit # Taggy v djangu (speciálně zaměření problémů)
django-autocomplete-light>=3.9.0 # Automatické doplňování (problémů, účastníků, …) ve formulářích
django-imagekit # Všechny možné obrázky v Djangu
django-polymorphic # Polymorfismus na django modelech (hlavně Problém nebo treenode)
django-sitetree # Struktura stránek, hlavně pro meníčko
django_reverse_admin # Lepší handlování OneToOne fieldů v adminu
django-rest-framework
django-webpack-loader
django-rest-polymorphic
# Comments
django-contrib-comments
# debug tools/extensions
django-debug-toolbar

View file

@ -38,9 +38,11 @@
<h2> Orgovské odkazy </h2>
<ul>
<li><a href="obalky.pdf">Obálky (PDF)</a></li>
<li><a href="tituly.tex" download>Tituly (TeX)</a></li>
<li><a href="vysledkovka.tex" download>Výsledkovka (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, 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="{% 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>
</div>
{% endif %}

View file

@ -1,7 +1,5 @@
{% extends "base.html" %}
{% load comments %}
{% block content %}
<div {% if not problem.verejne and user.je_org %}class="mam-org-only"{% endif %}>
{% block problem %}
@ -13,10 +11,6 @@
<h2>Text - org</h2>
{{ problem.text_org |safe }}
<h2>Diskuse - org</h2>
{% render_comment_list for object %}
{% render_comment_form for object %}
</div>
{% endif %}

View file

@ -120,8 +120,7 @@
{% if user.je_org %}
<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="tituly.tex" download>Tituly (TeX, do konce ročníku = pro poslední číslo)</a></p>
<p><a href="posledni_vysledkovka.tex" download>Výsledkovka posledního čísla</a></p>
<p><a href="tituly.tex" download>Tituly (TeX, včetně neveřejných, všechny, nevhodné do mamtexu)</a></p>
{# 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>
<h2>Výsledková listina včetně neveřejných bodů</h2>

View file

@ -1,7 +1,6 @@
from django import template
from django.utils.safestring import mark_safe
from datetime import datetime, timedelta
from pytz import timezone
from mamweb.settings import TIME_ZONE
import logging
register = template.Library()

View file

@ -4,7 +4,6 @@ import datetime
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from pytz import timezone
import random
import lorem
import django.contrib.auth
@ -177,13 +176,13 @@ def gen_organizatori(rnd, osoby, last_rocnik):
year=1993 + pusobnost,
month=rnd.randint(1, 12),
day=rnd.randint(1, 28),
tzinfo=timezone('CET'),
tzinfo=datetime.timezone.utc,
)
do = datetime.datetime(
year=od.year + rnd.randint(1, 6),
month=rnd.randint(1, 12),
day=rnd.randint(1, 28),
tzinfo=timezone('CET'),
tzinfo=datetime.timezone.utc,
)
#aktualni organizatori jeste nemaji vyplnene organizuje_do

View file

@ -8,6 +8,7 @@ from django.http import Http404
from django.db.models import Q, Sum, Count
from django.views.generic.base import RedirectView
from django.core.exceptions import PermissionDenied
from django.contrib.staticfiles.finders import find
import seminar.models as s
import seminar.models as m
@ -36,6 +37,7 @@ import unicodedata
import logging
import time
from collections.abc import Sequence
import http
from seminar.utils import aktivniResitele
@ -562,17 +564,25 @@ def cisloObalkyView(request, rocnik, cislo):
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
tempdir = tempfile.mkdtemp()
with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode())
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with tempfile.TemporaryDirectory() as tempdir:
with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
return response

View file

@ -1,8 +1,10 @@
from django.contrib import admin
from .models import OdpovedUcastnika, SpravnaOdpoved
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
# Register your models here.
admin.site.register(OdpovedUcastnika)
admin.site.register(SpravnaOdpoved)
admin.site.register(Napoveda)
admin.site.register(NapovezenoUcastnikovi)

View file

@ -1,6 +1,6 @@
from django.core.exceptions import ValidationError
from django.forms import ModelForm, Textarea
from .models import OdpovedUcastnika, SpravnaOdpoved
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
class SifrovackaForm(ModelForm):
@ -16,3 +16,15 @@ class SifrovackaForm(ModelForm):
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
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

View 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"],
},
),
]

View file

@ -25,3 +25,20 @@ class SpravnaOdpoved(models.Model):
def __str__(self):
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}"

View 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 %}

View 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 %}

View 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 %}

View file

@ -43,4 +43,8 @@
<input type="submit" value="Tak pravím!">
</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 %}

View file

@ -1,7 +1,7 @@
from django.urls import path
from seminar.utils import org_required, resitel_or_org_required
from .views import SifrovackaView, SifrovackaListView
from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView, PreskoceniView
urlpatterns = [
path(
@ -14,4 +14,19 @@ urlpatterns = [
org_required(SifrovackaListView.as_view()),
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'
),
]

View file

@ -2,8 +2,8 @@ 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 .forms import SifrovackaForm, NapovedaForm
from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi
from seminar.models import Resitel
@ -24,10 +24,47 @@ class SifrovackaView(FormView):
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
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>')

View file

@ -58,16 +58,16 @@
{# Účastníci #}
<h2>Soustředění se zúčastnili tito účastníci:</h2>
<p>
{% for i in soustredeni.soustredeni_ucastnici_set.all %}
{{i.resitel}}{% if forloop.last %}.{% else %},{% endif %}
{% for i in soustredeni.ucastnici.all %}
{{i}}{% if forloop.last %}.{% else %},{% endif %}
{% empty %}
Nic!
{% endfor %}
</p>
<h2>Soustředění se účastnili tito organizátoři:</h2>
<p>
{% for i in soustredeni.soustredeni_organizatori_set.all %}
{{i.organizator}}{% if forloop.last %}.{% else %},{% endif %}
{% for i in soustredeni.organizatori.all %}
{{i}}{% if forloop.last %}.{% else %},{% endif %}
{% empty %}
Nic!
{% endfor %}

View file

@ -9,6 +9,7 @@ import tempfile
import shutil
import subprocess
from pathlib import Path
import http
from seminar.views import obalkyView
@ -17,6 +18,19 @@ class SoustredeniListView(generic.ListView):
model = Soustredeni
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):
soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
@ -63,17 +77,25 @@ def soustredeniUcastniciExportView(request, soustredeni):
def soustredeniStvrzenkyView(request, soustredeni):
soustredeni = get_object_or_404(Soustredeni, id=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
tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content
tempdir = Path(tempfile.mkdtemp())
with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
with tempfile.TemporaryDirectory() as tempdirfn:
tempdir = Path(tempdirfn)
with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
return response

View file

@ -1,19 +1,10 @@
{% extends "seminar/archiv/base.html" %}
{% 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 %}
<link rel="stylesheet" type="text/css" href="{% static 'css/mamweb-dev.css' %}" />
{% endblock custom_css %}
{% load comments %}
{% block content %}
<ul>
{% for obj in object_list %}