Merge branch 'master' into galerie_videjka

This commit is contained in:
Pavel "LEdoian" Turinsky 2025-05-05 02:13:27 +02:00
commit 9786c42c4a
16 changed files with 284 additions and 119 deletions

View file

@ -1,4 +1,4 @@
from galerie.models import Obrazek, Galerie from galerie.models import Obrazek, Galerie, VZDY, ORG, NIKDY, UCASTNIK
from django.contrib import admin from django.contrib import admin
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django import forms from django import forms
@ -8,8 +8,9 @@ from django.db import models
def zverejnit_fotogalerii(modeladmin, request, queryset): def zverejnit_fotogalerii(modeladmin, request, queryset):
'''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' '''zverejni vybranou fotogalerii i jeji vsechny podgalerie'''
queryset = queryset.filter(zobrazit=ORG)
for galerie in queryset: for galerie in queryset:
galerie.zobrazit = 0 galerie.zobrazit = VZDY
galerie.save() galerie.save()
zverejnit_fotogalerii(modeladmin, request, zverejnit_fotogalerii(modeladmin, request,
Galerie.objects.filter(galerie_up = galerie)) Galerie.objects.filter(galerie_up = galerie))
@ -18,8 +19,9 @@ def zverejnit_fotogalerii(modeladmin, request, queryset):
def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset):
'''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' '''zneverjni vybranou fotogalerii i jeji vsechny podgalerie'''
queryset = queryset.filter(zobrazit=VZDY)
for galerie in queryset: for galerie in queryset:
galerie.zobrazit = 1 galerie.zobrazit = ORG
galerie.save() galerie.save()
prepnout_fotogalerii_do_org_rezimu(modeladmin, request, prepnout_fotogalerii_do_org_rezimu(modeladmin, request,
Galerie.objects.filter(galerie_up = galerie)) Galerie.objects.filter(galerie_up = galerie))

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.20 on 2025-04-23 18:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('galerie', '0013_post_split_soustredeni'),
]
operations = [
migrations.AlterField(
model_name='galerie',
name='zobrazit',
field=models.IntegerField(choices=[(0, 'Vždy'), (1, 'Organizátorům'), (3, 'Účastníkům a orgům'), (2, 'Nikdy')], default=1, verbose_name='Zobrazit?'),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 4.2.16 on 2025-04-30 18:53
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('galerie', '0014_alter_galerie_zobrazit'),
]
operations = [
migrations.AlterField(
model_name='galerie',
name='galerie_up',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='galerie.galerie'),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 4.2.16 on 2025-04-30 19:02
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('galerie', '0015_alter_galerie_galerie_up'),
]
operations = [
migrations.AlterField(
model_name='obrazek',
name='galerie',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='galerie.galerie'),
),
]

View file

@ -10,9 +10,11 @@ from soustredeni.models import Soustredeni
VZDY=0 VZDY=0
ORG=1 ORG=1
NIKDY=2 NIKDY=2
UCASTNIK=3
VIDITELNOST = ( VIDITELNOST = (
(VZDY, 'Vždy'), (VZDY, 'Vždy'),
(ORG, 'Organizátorům'), (ORG, 'Organizátorům'),
(UCASTNIK, 'Účastníkům a orgům'),
(NIKDY, 'Nikdy'), (NIKDY, 'Nikdy'),
) )
@ -59,7 +61,7 @@ class Obrazek(models.Model):
# ~~Rádoby~~ vtipný popisek od orgů # ~~Rádoby~~ vtipný popisek od orgů
popis = models.TextField('Popis', blank=True, null=True) popis = models.TextField('Popis', blank=True, null=True)
datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True)
galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.SET_NULL) galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.CASCADE)
# Primární klíč k řazení pro overridování řazení podle názvu # Primární klíč k řazení pro overridování řazení podle názvu
poradi = models.IntegerField('Pořadí', blank=True, null=True) poradi = models.IntegerField('Pořadí', blank=True, null=True)
@ -98,7 +100,7 @@ class Galerie(models.Model):
titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL)
zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST)
galerie_up = models.ForeignKey('Galerie', blank = True, null = True, galerie_up = models.ForeignKey('Galerie', blank = True, null = True,
on_delete=models.SET_NULL) on_delete=models.PROTECT)
soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True, soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True,
on_delete=models.PROTECT) on_delete=models.PROTECT)
poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0)
@ -108,25 +110,3 @@ class Galerie(models.Model):
class Meta: class Meta:
verbose_name = 'Galerie' verbose_name = 'Galerie'
verbose_name_plural = 'Galerie' verbose_name_plural = 'Galerie'
#def link_na_preview(self):
#"""Odkaz na galerii, používá se v admin rozhranní. """
#return '<a href="/fotogalerie/galerie/%s/">Preview</a>' % self.id
#link_na_preview.allow_tags = True
#link_na_preview.short_description = 'Zobrazit galerii'
#
#def je_publikovano(self):
#"""Vraci True, pokud je tato galerie publikovana. """
#if self.zobrazit == VZDY:
#return True
#if self.zobrazit == PODLE_CLANKU:
#for clanek in self.clanek_set.all():
#if clanek.je_publikovano():
#return True
#return False
#
#@staticmethod
#def publikovane_galerie():
#"""Vraci galerie, ktere uz maji byt publikovane."""
#clanky = Blog.models.Clanek.publikovane_clanky()
#return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct()

View file

@ -136,6 +136,11 @@
top: 160px; top: 160px;
} }
.podgalerie_nahled.mam-org-only, .podgalerie_nahled.mam-resitel-only {
margin: 10px;
padding: 0;
}
/* Odkazy na předchozí a následující podgalerii */ /* Odkazy na předchozí a následující podgalerii */
.galerie_predchozi_nasledujici { .galerie_predchozi_nasledujici {

View file

@ -47,6 +47,7 @@
{% block content %} {% block content %}
<div class="{% if obrazek.galerie.zobrazit == 1 or obrazek.galerie.zobrazit == 2 %}mam-org-only{% endif %}{% if obrazek.galerie.zobrazit == 3 %}mam-resitel-only{% endif %}">
<h2> <h2>
{% for g in cesta %} {% for g in cesta %}
@ -85,7 +86,7 @@
{# Popisek fotky #} {# Popisek fotky #}
<div class="popis"> <div class="popis">
{% if preview %} {% if upravy_popisku %}
<form action=".#nahoru" method="post" id="komentarform"> <form action=".#nahoru" method="post" id="komentarform">
{% csrf_token %} {% csrf_token %}
<table> <table>
@ -135,4 +136,6 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View file

@ -8,8 +8,11 @@ Galerie {{galerie.nazev}}
{% block content %} {% block content %}
{% if galerie.zobrazit > 0 %} {# FIXME: použít konstanty… #}
{% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
<div class="mam-org-only"> <div class="mam-org-only">
{% elif galerie.zobrazit == 3 %}
<div class="mam-resitel-only">
{% endif %} {% endif %}
<h2> <h2>
@ -47,34 +50,40 @@ Galerie {{galerie.nazev}}
{% if podgalerie %} {% if podgalerie %}
{% with 22 as max_delka_nazvu %} {% with 22 as max_delka_nazvu %}
<div class="galerie_nahledy"> <div class="galerie_nahledy">
{% for galerie in podgalerie %} {% for pgalerie in podgalerie %}
<a href="../{{galerie.pk}}" <a href="../{{pgalerie.pk}}"
{% if galerie.nazev|length > max_delka_nazvu %} {% if pgalerie.nazev|length > max_delka_nazvu %}
title="{{ galerie.nazev }}" title="{{ pgalerie.nazev }}"
{% endif %}
class="podgalerie_nahled">
{% if galerie.titulni_obrazek %}
{% zmenseny_nahled galerie.titulni_obrazek.jako_bazmek %}
{% endif %} {% endif %}
<div class="nazev_galerie"> class="podgalerie_nahled {% if pgalerie.zobrazit == 1 or pgalerie.zobrazit == 2 %}mam-org-only{% endif %}{% if pgalerie.zobrazit == 3 %}mam-resitel-only{% endif %}">
{{ galerie|truncatechars:max_delka_nazvu }} {% if pgalerie.titulni_obrazek %}
{% zmenseny_nahled pgalerie.titulni_obrazek.jako_bazmek %}
{% endif %}
<div class="nazev_galerie">
{{ pgalerie|truncatechars:max_delka_nazvu }}
</div>
</a>
{% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
{% if user.je_org %}
<div class="mam-org-only-galerie">
({{pgalerie.poradi}})
<span class="plus"><a href="plus/{{pgalerie.pk}}/">+</a></span>
<span class="minus"><a href="minus/{{pgalerie.pk}}/">-</a></span>
</div> </div>
</a> {% endif %}
{% if user.je_org and galerie.zobrazit > 0 %} {% endif %}
<div class="mam-org-only-galerie">
({{galerie.poradi}})
<span class="plus"><a href="plus/{{galerie.pk}}/">+</a></span>
<span class="minus"><a href="minus/{{galerie.pk}}/">-</a></span>
</div>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
{% endwith %} {% endwith %}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if user.je_org and galerie.zobrazit > 0 %} {% if user.je_org %}
<div class="mam-org-only"> <div class="mam-org-only">
<a href="./new">Vytvořit novou podgalerii </a> {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
<a href="./new">Vytvořit novou podgalerii</a>, <a href="{% url 'admin:galerie_galerie_change' galerie.pk %}">upravit galerii v adminu</a>
{% else %}
Jestli chceš změnit pořadí podgalerií nebo přidat novou, nastav zobrazení jen pro orgy v <a href="{% url 'admin:galerie_galerie_change' galerie.pk %}">adminu</a>.
{% endif %}
</div> </div>
{% endif %} {% endif %}
@ -118,8 +127,10 @@ Galerie {{galerie.nazev}}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if galerie.zobrazit > 0 %} {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
</div> {# mam-org-only #} </div> {# mam-org-only #}
{% elif galerie.zobrazit == 2 %}
</div> {# mam-resitel-only #}
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}

View file

@ -2,5 +2,5 @@
{% load static %} {% load static %}
{% block custom_css %} {% block custom_css %}
<link href="{% static 'css/galerie.css' %}?version=1" rel="stylesheet"> <link href="{% static 'css/galerie.css' %}?version=2" rel="stylesheet">
{% endblock %} {% endblock %}

6
galerie/utils.py Normal file
View file

@ -0,0 +1,6 @@
from galerie.models import Galerie
def top_galerie(g: Galerie) -> Galerie:
while g.galerie_up is not None:
g = g.galerie_up
return g

View file

@ -1,22 +1,41 @@
import random import random
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404, HttpRequest
from django.shortcuts import render, HttpResponseRedirect, get_object_or_404 from django.shortcuts import render, HttpResponseRedirect, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from datetime import datetime from datetime import datetime
from galerie.models import Obrazek, Galerie from galerie.utils import top_galerie
from personalni.utils import resitel_uzivatele
from galerie.models import Obrazek, Galerie, VZDY, ORG, UCASTNIK, NIKDY
from soustredeni.models import Soustredeni from soustredeni.models import Soustredeni
from galerie.forms import KomentarForm, NewGalerieForm from galerie.forms import KomentarForm, NewGalerieForm
def zobrazit(galerie, request): import logging
preview = False logger = logging.getLogger(__name__)
if galerie.zobrazit >= 1:
if request.user.je_org: def galerie_ke_zobrazeni(soustredeni: Soustredeni | None, request: HttpRequest) -> tuple[int]:
preview = True; if request.user.is_superuser: return (VZDY, ORG, UCASTNIK, NIKDY)
if request.user.je_org: return (VZDY, ORG, UCASTNIK)
if request.user.is_anonymous: return (VZDY,)
if soustredeni is None: return (VZDY,)
if (resitel := resitel_uzivatele(request.user)) is not None:
if resitel.soustredeni_set.contains(soustredeni):
return (VZDY, UCASTNIK)
else: else:
raise Http404 return (VZDY,)
return preview logger.warning("Nepodařilo se zjistit, jaké galerie se mají zobrazit!")
return (VZDY,)
def zobrazit(galerie: Galerie, request: HttpRequest) -> bool:
soustredeni = top_galerie(galerie).soustredeni
return galerie.zobrazit in galerie_ke_zobrazeni(soustredeni, request)
def dovolit_upravy_popisku(galerie: Galerie, request: HttpRequest) -> bool:
# FIXME: Dočasné: úpravy jen když je to v org-only stavu. (Odpovídá předchozímu chování)
return request.user.je_org and galerie.zobrazit in (ORG, NIKDY)
def cesta_od_korene(g): def cesta_od_korene(g):
@ -31,19 +50,19 @@ def cesta_od_korene(g):
def nahled(request, pk, soustredeni): def nahled(request, pk, soustredeni):
"""Zobrazeni nahledu vsech fotek ve skupine.""" """Zobrazeni nahledu vsech fotek ve skupine."""
galerie = get_object_or_404(Galerie, pk=pk) galerie = get_object_or_404(Galerie, pk=pk)
soustredeni = top_galerie(galerie).soustredeni
# FIXME: přepsat model a použít přímo dolů…
podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi')
if not request.user.je_org: podgalerie = podgalerie.filter(zobrazit__in=galerie_ke_zobrazeni(soustredeni, request))
podgalerie = podgalerie.filter(zobrazit__lt=1)
obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev')
preview = zobrazit(galerie, request) ma_se_zobrazit = zobrazit(galerie, request)
if not ma_se_zobrazit: raise Http404("Galerie sice existuje, ale my se tváříme, že ne :-D")
sourozenci = [] sourozenci = []
if galerie.galerie_up: if galerie.galerie_up:
sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') sourozenci = galerie.galerie_up.galerie_set.filter(zobrazit__in=galerie_ke_zobrazeni(soustredeni, request)).order_by('poradi')
if not request.user.je_org:
sourozenci = sourozenci.filter(zobrazit__lt=1)
predchozi = None predchozi = None
nasledujici = None nasledujici = None
@ -62,7 +81,6 @@ def nahled(request, pk, soustredeni):
{'galerie' : galerie, {'galerie' : galerie,
'podgalerie' : podgalerie, 'podgalerie' : podgalerie,
'obrazky' : obrazky, 'obrazky' : obrazky,
'preview' : preview,
'cesta': cesta, 'cesta': cesta,
'sourozenci': sourozenci, 'sourozenci': sourozenci,
'predchozi': predchozi, 'predchozi': predchozi,
@ -78,9 +96,41 @@ def detail(request, pk, fotka, soustredeni):
NAHLEDU = 1 NAHLEDU = 1
galerie = get_object_or_404(Galerie, pk=pk) galerie = get_object_or_404(Galerie, pk=pk)
preview = zobrazit(galerie, request) soustredeni = top_galerie(galerie).soustredeni
ma_se_zobrazit = zobrazit(galerie, request)
if not ma_se_zobrazit: raise Http404("Obrázek neukážu!")
obrazek = get_object_or_404(Obrazek, pk=fotka) obrazek = get_object_or_404(Obrazek, pk=fotka)
# Pořadí není povinné. FIXME: `nazev` je zavádějící… Ale tohle je kanonické pořadí obrázků v galerii…
obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev')
obrazky = list(obrazky)
index_obrazku = obrazky.index(obrazek)
# Podle mě se nemůže stát, že by volání výš selhalo, kdyžtak shodí web. (původně to byl explicitně ošetřený stav dávající 404)
predchozi_obrazky = list(reversed(obrazky[:index_obrazku]))
nasledujici_obrazky = obrazky[index_obrazku+1:]
# Může jich být hodně…
predchozi_obrazky = predchozi_obrazky[:NAHLEDU]
nasledujici_obrazky = nasledujici_obrazky[:NAHLEDU]
# Předchozí obrázky chceme v normálním pořadí
predchozi_obrazky = list(reversed(predchozi_obrazky))
if galerie.galerie_up is not None:
sousedni_galerie = Galerie.objects.filter(galerie_up=galerie.galerie_up, zobrazit__in=galerie_ke_zobrazeni(soustredeni, request)).order_by('poradi')
sousedni_galerie = list(sousedni_galerie)
# Teoreticky se můžeme dívat na galerie.poradi, ale jednak už tenhle pattern stejně je výš a druhak je galerií málo, takže pomalost nevadí.
index_galerie = sousedni_galerie.index(galerie)
predchozi_galerie = sousedni_galerie[index_galerie-1] if index_galerie > 0 else None
nasledujici_galerie = sousedni_galerie[index_galerie+1] if index_galerie < len(sousedni_galerie) - 1 else None
else:
predchozi_galerie = None
nasledujici_galerie = None
# Pokud je obrázků dost, tak další galerii nepotřebujeme
# (jo, mohli jsme si ušetřit práci, ale takhle je kód imho přehlednější a za pár ušetřených dotazů do DB to nestojí)
if len(predchozi_obrazky) >= NAHLEDU:
predchozi_galerie = None
if len(nasledujici_obrazky) >= NAHLEDU:
nasledujici_galerie = None
# vytvoreni a obslouzeni formulare # vytvoreni a obslouzeni formulare
if request.method == 'POST': if request.method == 'POST':
@ -90,49 +140,6 @@ def detail(request, pk, fotka, soustredeni):
obrazek.save() obrazek.save()
else: else:
form = KomentarForm({'komentar': obrazek.popis}) form = KomentarForm({'komentar': obrazek.popis})
# Poradi aktualniho obrazku v galerii/stitku.
for i in range(len(obrazky)):
if obrazky[i] == obrazek:
poradi = i
break
else:
# Obrazek neni v galerii/stitku.
raise Http404
# Nacteni okolnich obrazku a galerii
# TODO vyjmout zjisteni predchozich a nasledujicich galerii
# a udelat z toho funkci, ktera se pouzije u nahledu
predchozi_galerie = None
nasledujici_galerie = None
obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1]
if (poradi+1) > NAHLEDU:
obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi]
else:
obrazky_predchozi = obrazky[0:poradi]
if galerie.poradi > 1:
predchozi_galerie = Galerie.objects.\
filter(galerie_up=galerie.galerie_up).\
filter(poradi=(galerie.poradi-1))
if predchozi_galerie:
predchozi_galerie = predchozi_galerie[0]
else:
predchozi_galerie = None
if (poradi+1) == len(obrazky): # Tohle je poslední obrázek
if (galerie.poradi is not None
and galerie.galerie_up is not None):
nasledujici_galerie = Galerie.objects.\
filter(galerie_up=galerie.galerie_up).\
filter(poradi=(galerie.poradi+1))
else:
nasledujici_galerie = None
if nasledujici_galerie:
nasledujici_galerie = nasledujici_galerie[0]
else:
nasledujici_galerie = None
# Preskalovani obrazku do vybraneho prostoru. # Preskalovani obrazku do vybraneho prostoru.
vyska = obrazek.obrazek_stredni.height vyska = obrazek.obrazek_stredni.height
@ -151,9 +158,9 @@ def detail(request, pk, fotka, soustredeni):
'obrazek' : obrazek, 'obrazek' : obrazek,
'vyska' : vyska, 'vyska' : vyska,
'sirka' : sirka, 'sirka' : sirka,
'obrazky_predchozi' : obrazky_predchozi, 'obrazky_predchozi' : predchozi_obrazky,
'obrazky_dalsi' : obrazky_dalsi, 'obrazky_dalsi' : nasledujici_obrazky,
'preview' : preview, 'upravy_popisku' : dovolit_upravy_popisku(galerie, request),
'form' : form, 'form' : form,
'cesta': cesta_od_korene(galerie), 'cesta': cesta_od_korene(galerie),
}) })
@ -179,7 +186,7 @@ def new_galerie(request, galerie, soustredeni):
gal = Galerie() gal = Galerie()
gal.nazev = form.cleaned_data['nazev'] gal.nazev = form.cleaned_data['nazev']
#gal.popis = form.cleaned_data['popis'] # popis nepouzivame #gal.popis = form.cleaned_data['popis'] # popis nepouzivame
gal.zobrazit = 1 # galerie je v procesu vytvareni gal.zobrazit = ORG # galerie je v procesu vytvareni
''' pokud je to podgalerie pridej nadrazenou galerii ''' pokud je to podgalerie pridej nadrazenou galerii
a nadrazene soustredeni nechej volne, a nadrazene soustredeni nechej volne,
pokud je to hlavni galerie, tak nadrazena galerie neexistuje, pokud je to hlavni galerie, tak nadrazena galerie neexistuje,

View file

@ -0,0 +1,10 @@
.odevzdavatko-role {
font-size: 0.8em;
.vyrazne {
color: var(--hlavni-oranzova);
}
.nevyrazne {
color: #aaa;
}
}

View file

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% load static %}
{% block custom_css %}
<link href="{% static 'css/odevzdavatko.css' %}?version=1" rel="stylesheet">
{% endblock %}

View file

@ -1,6 +1,7 @@
{% extends "base.html" %} {% extends "odevzdavatko/base.html" %}
{% load barvy_reseni %} {% load barvy_reseni %}
{% load orgove %}
{% block content %} {% block content %}
@ -27,7 +28,15 @@ Do data (včetně): {{ filtr.reseni_do }}
{% for p in problemy %} {% for p in problemy %}
<th> <th>
{# TODO: Přehled řešení k problému, odkázaný odsud? #} {# TODO: Přehled řešení k problému, odkázaný odsud? #}
{{ p }} <span title="Autor: {{ p.autor }}, Garant: {{ p.garant }}, Opravovatelé: {{ p.opravovatele.all | join:", " }}">{{ p }}
<span class="odevzdavatko-role">
{% spaceless %}
<span class="{{ p|ma_autora:user|yesno:"vyrazne,nevyrazne" }}">A</span>
<span class="{{ p|ma_garanta:user|yesno:"vyrazne,nevyrazne" }}">G</span>
<span class="{{ p|ma_opravovatele:user|yesno:"vyrazne,nevyrazne" }}">O</span>
{% endspaceless %}
</span>
</span>
</th> </th>
{% endfor %} {% endfor %}
</tr> </tr>

View file

@ -0,0 +1,27 @@
from django import template
register = template.Library()
from personalni.utils import organizator_cehokoliv
# Jen typová anotace
from tvorba.models import Problem
from personalni.models import Osoba, Organizator, Resitel, Prijemce
from django.contrib.auth.models import AnonymousUser, User
@register.filter
def ma_autora(p: Problem, o: Osoba | Organizator | User | AnonymousUser | Resitel | Prijemce) -> bool | None:
o = organizator_cehokoliv(o)
if o is None: return None
return p.autor == o
@register.filter
def ma_garanta(p: Problem, o: Osoba | Organizator | User | AnonymousUser | Resitel | Prijemce) -> bool | None:
o = organizator_cehokoliv(o)
if o is None: return None
return p.garant == o
@register.filter
def ma_opravovatele(p: Problem, o: Osoba | Organizator | User | AnonymousUser | Resitel | Prijemce) -> bool | None:
o = organizator_cehokoliv(o)
if o is None: return None
return p.opravovatele.contains(o)

View file

@ -3,7 +3,7 @@ import re
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import permission_required, user_passes_test from django.contrib.auth.decorators import permission_required, user_passes_test
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser, User
from django.db import transaction from django.db import transaction
import soustredeni.models import soustredeni.models
@ -182,3 +182,46 @@ def merge_osoby(cilova, zdrojova):
cilova.save() cilova.save()
input("Potvrdit transakci osob (^C pro zrušení) ") input("Potvrdit transakci osob (^C pro zrušení) ")
def osoba_uzivatele(u: User | AnonymousUser) -> Osoba | None:
if u.is_anonymous: return None
try:
return u.osoba
except User.osoba.RelatedObjectDoesNotExist:
return None
def resitel_osoby(o: Osoba) -> Resitel | None:
try:
return o.resitel
except Osoba.resitel.RelatedObjectDoesNotExist:
return None
def resitel_uzivatele(u: User | AnonymousUser) -> Resitel | None:
o = osoba_uzivatele(u)
if o is None: return None
return resitel_osoby(o)
def resitel_cehokoliv(r: User | AnonymousUser | Osoba | Organizator | Resitel | Prijemce) -> Organizator | None:
if isinstance(r, User): r = resitel_uzivatele(r)
if isinstance(r, Osoba): r = resitel_osoby(r)
if isinstance(r, Resitel) or isinstance(r, Prijemce): r = resitel_osoby(r.osoba)
assert isinstance(r, Resitel) or r is None
return r
def organizator_osoby(o: Osoba) -> Organizator | None:
try:
return o.org
except Osoba.org.RelatedObjectDoesNotExist:
return None
def organizator_uzivatele(u: User | AnonymousUser) -> Organizator | None:
o = osoba_uzivatele(u)
if o is None: return None
return organizator_osoby(o)
def organizator_cehokoliv(o: User | AnonymousUser | Osoba | Organizator | Resitel | Prijemce) -> Organizator | None:
if isinstance(o, User): o = organizator_uzivatele(o)
if isinstance(o, Osoba): o = organizator_osoby(o)
if isinstance(o, Resitel) or isinstance(o, Prijemce): o = organizator_osoby(o.osoba)
assert isinstance(o, Organizator) or o is None
return o