diff --git a/galerie/admin.py b/galerie/admin.py index 2b270163..c663287e 100644 --- a/galerie/admin.py +++ b/galerie/admin.py @@ -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.http import HttpResponseRedirect from django import forms @@ -8,8 +8,9 @@ from django.db import models def zverejnit_fotogalerii(modeladmin, request, queryset): '''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' + queryset = queryset.filter(zobrazit=ORG) for galerie in queryset: - galerie.zobrazit = 0 + galerie.zobrazit = VZDY galerie.save() zverejnit_fotogalerii(modeladmin, request, 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): '''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' + queryset = queryset.filter(zobrazit=VZDY) for galerie in queryset: - galerie.zobrazit = 1 + galerie.zobrazit = ORG galerie.save() prepnout_fotogalerii_do_org_rezimu(modeladmin, request, Galerie.objects.filter(galerie_up = galerie)) diff --git a/galerie/migrations/0014_alter_galerie_zobrazit.py b/galerie/migrations/0014_alter_galerie_zobrazit.py new file mode 100644 index 00000000..c53393f3 --- /dev/null +++ b/galerie/migrations/0014_alter_galerie_zobrazit.py @@ -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?'), + ), + ] diff --git a/galerie/migrations/0015_alter_galerie_galerie_up.py b/galerie/migrations/0015_alter_galerie_galerie_up.py new file mode 100644 index 00000000..2033c9af --- /dev/null +++ b/galerie/migrations/0015_alter_galerie_galerie_up.py @@ -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'), + ), + ] diff --git a/galerie/migrations/0016_alter_obrazek_galerie.py b/galerie/migrations/0016_alter_obrazek_galerie.py new file mode 100644 index 00000000..8c8e57af --- /dev/null +++ b/galerie/migrations/0016_alter_obrazek_galerie.py @@ -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'), + ), + ] diff --git a/galerie/models.py b/galerie/models.py index 074b0d26..44c1120e 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -10,9 +10,11 @@ from soustredeni.models import Soustredeni VZDY=0 ORG=1 NIKDY=2 +UCASTNIK=3 VIDITELNOST = ( (VZDY, 'Vždy'), (ORG, 'Organizátorům'), + (UCASTNIK, 'Účastníkům a orgům'), (NIKDY, 'Nikdy'), ) @@ -54,7 +56,7 @@ class Obrazek(models.Model): nazev = models.CharField('Název', max_length=50, blank=True, null=True) popis = models.TextField('Popis', blank=True, null=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) poradi = models.IntegerField('Pořadí', blank=True, null=True) def __str__(self): @@ -88,7 +90,7 @@ class Galerie(models.Model): titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) 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, on_delete=models.PROTECT) poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) @@ -98,25 +100,3 @@ class Galerie(models.Model): class Meta: verbose_name = 'Galerie' verbose_name_plural = 'Galerie' - - #def link_na_preview(self): - #"""Odkaz na galerii, používá se v admin rozhranní. """ - #return 'Preview' % 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() diff --git a/galerie/static/css/galerie.css b/galerie/static/css/galerie.css index 46df8552..46e02367 100644 --- a/galerie/static/css/galerie.css +++ b/galerie/static/css/galerie.css @@ -136,6 +136,11 @@ 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 */ .galerie_predchozi_nasledujici { diff --git a/galerie/templates/galerie/Galerie.html b/galerie/templates/galerie/Galerie.html index ff8ebfe3..364d0b51 100644 --- a/galerie/templates/galerie/Galerie.html +++ b/galerie/templates/galerie/Galerie.html @@ -46,6 +46,7 @@ {% block content %} +

{% for g in cesta %} @@ -83,7 +84,7 @@ {# Popisek fotky #}
- {% if preview %} + {% if upravy_popisku %}
{% csrf_token %} @@ -133,4 +134,6 @@ {% endif %} + + {% endblock %} diff --git a/galerie/templates/galerie/GalerieNahled.html b/galerie/templates/galerie/GalerieNahled.html index 87794680..548d70ea 100644 --- a/galerie/templates/galerie/GalerieNahled.html +++ b/galerie/templates/galerie/GalerieNahled.html @@ -6,8 +6,11 @@ Galerie {{galerie.nazev}} {% block content %} - {% if galerie.zobrazit > 0 %} + {# FIXME: použít konstanty… #} + {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
+ {% elif galerie.zobrazit == 3 %} +
{% endif %}

@@ -45,37 +48,43 @@ Galerie {{galerie.nazev}} {% if podgalerie %} {% with 22 as max_delka_nazvu %}
- {% for galerie in podgalerie %} - max_delka_nazvu %} - title="{{ galerie.nazev }}" - {% endif %} - class="podgalerie_nahled"> - {% if galerie.titulni_obrazek %} - {% with galerie.titulni_obrazek.obrazek_maly as obrazek %} - - {% endwith %} + {% for pgalerie in podgalerie %} + max_delka_nazvu %} + title="{{ pgalerie.nazev }}" {% endif %} - {% endwith %} {% endif %} {% endif %} - {% if user.je_org and galerie.zobrazit > 0 %} + {% if user.je_org %}
- Vytvořit novou podgalerii + {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %} + Vytvořit novou podgalerii, upravit galerii v adminu + {% else %} + Jestli chceš změnit pořadí podgalerií nebo přidat novou, nastav zobrazení jen pro orgy v adminu. + {% endif %}
{% endif %} @@ -120,8 +129,10 @@ Galerie {{galerie.nazev}} {% endif %} {% endif %} - {% if galerie.zobrazit > 0 %} + {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
{# mam-org-only #} + {% elif galerie.zobrazit == 2 %} +

{# mam-resitel-only #} {% endif %} {% endblock content %} diff --git a/galerie/templates/galerie/base.html b/galerie/templates/galerie/base.html index 032f16b2..0c449914 100644 --- a/galerie/templates/galerie/base.html +++ b/galerie/templates/galerie/base.html @@ -2,5 +2,5 @@ {% load static %} {% block custom_css %} - + {% endblock %} diff --git a/galerie/utils.py b/galerie/utils.py new file mode 100644 index 00000000..352e197b --- /dev/null +++ b/galerie/utils.py @@ -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 diff --git a/galerie/views.py b/galerie/views.py index cf9ade8b..fa2a15e9 100644 --- a/galerie/views.py +++ b/galerie/views.py @@ -1,22 +1,41 @@ 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.template import RequestContext 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 galerie.forms import KomentarForm, NewGalerieForm -def zobrazit(galerie, request): - preview = False - if galerie.zobrazit >= 1: - if request.user.je_org: - preview = True; +import logging +logger = logging.getLogger(__name__) + +def galerie_ke_zobrazeni(soustredeni: Soustredeni | None, request: HttpRequest) -> tuple[int]: + 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: - raise Http404 - return preview + return (VZDY,) + 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): @@ -31,19 +50,19 @@ def cesta_od_korene(g): def nahled(request, pk, soustredeni): """Zobrazeni nahledu vsech fotek ve skupine.""" 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') - if not request.user.je_org: - podgalerie = podgalerie.filter(zobrazit__lt=1) + podgalerie = podgalerie.filter(zobrazit__in=galerie_ke_zobrazeni(soustredeni, request)) - obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') - preview = zobrazit(galerie, request) + obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') + 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 = [] if galerie.galerie_up: - sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') - if not request.user.je_org: - sourozenci = sourozenci.filter(zobrazit__lt=1) + sourozenci = galerie.galerie_up.galerie_set.filter(zobrazit__in=galerie_ke_zobrazeni(soustredeni, request)).order_by('poradi') predchozi = None nasledujici = None @@ -62,7 +81,6 @@ def nahled(request, pk, soustredeni): {'galerie' : galerie, 'podgalerie' : podgalerie, 'obrazky' : obrazky, - 'preview' : preview, 'cesta': cesta, 'sourozenci': sourozenci, 'predchozi': predchozi, @@ -78,9 +96,41 @@ def detail(request, pk, fotka, soustredeni): NAHLEDU = 1 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) + + # 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 = 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 if request.method == 'POST': @@ -90,49 +140,6 @@ def detail(request, pk, fotka, soustredeni): obrazek.save() else: 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. vyska = obrazek.obrazek_stredni.height @@ -151,9 +158,9 @@ def detail(request, pk, fotka, soustredeni): 'obrazek' : obrazek, 'vyska' : vyska, 'sirka' : sirka, - 'obrazky_predchozi' : obrazky_predchozi, - 'obrazky_dalsi' : obrazky_dalsi, - 'preview' : preview, + 'obrazky_predchozi' : predchozi_obrazky, + 'obrazky_dalsi' : nasledujici_obrazky, + 'upravy_popisku' : dovolit_upravy_popisku(galerie, request), 'form' : form, 'cesta': cesta_od_korene(galerie), }) @@ -179,7 +186,7 @@ def new_galerie(request, galerie, soustredeni): gal = Galerie() gal.nazev = form.cleaned_data['nazev'] #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 a nadrazene soustredeni nechej volne, pokud je to hlavni galerie, tak nadrazena galerie neexistuje, diff --git a/personalni/utils.py b/personalni/utils.py index 02e541da..f3c796e6 100644 --- a/personalni/utils.py +++ b/personalni/utils.py @@ -3,7 +3,7 @@ import re from django.contrib.auth import get_user_model 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 import soustredeni.models @@ -182,3 +182,23 @@ def merge_osoby(cilova, zdrojova): cilova.save() 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) + +# TODO: organizator_osoby, organizator_uzivatele