Jonas Havelka
3 years ago
18 changed files with 364 additions and 310 deletions
@ -0,0 +1,214 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import logging |
||||
|
import os |
||||
|
|
||||
|
from django.db import models |
||||
|
from django.urls import reverse |
||||
|
from reversion import revisions as reversion |
||||
|
|
||||
|
from django.conf import settings |
||||
|
|
||||
|
from . import personalni as pm |
||||
|
|
||||
|
from .base import SeminarModelBase |
||||
|
from seminar.models import models_all as am |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Soustredeni(SeminarModelBase): |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_soustredeni' |
||||
|
verbose_name = 'Soustředění' |
||||
|
verbose_name_plural = 'Soustředění' |
||||
|
ordering = ['-rocnik__rocnik', '-datum_zacatku'] |
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
rocnik = models.ForeignKey(am.Rocnik, verbose_name='ročník', related_name='soustredeni', |
||||
|
on_delete=models.PROTECT) |
||||
|
|
||||
|
datum_zacatku = models.DateField('datum začátku', blank=True, null=True, |
||||
|
help_text='První den soustředění') |
||||
|
|
||||
|
datum_konce = models.DateField('datum konce', blank=True, null=True, |
||||
|
help_text='Poslední den soustředění') |
||||
|
|
||||
|
verejne_db = models.BooleanField('soustředění zveřejněno', db_column='verejne', default=False) |
||||
|
|
||||
|
misto = models.CharField('místo soustředění', max_length=256, blank=True, default='', |
||||
|
help_text='Místo (název obce, volitelně též objektu') |
||||
|
|
||||
|
ucastnici = models.ManyToManyField(pm.Resitel, verbose_name='účastníci soustředění', |
||||
|
help_text='Seznam účastníků soustředění', through='Soustredeni_Ucastnici') |
||||
|
|
||||
|
organizatori = models.ManyToManyField(pm.Organizator, |
||||
|
verbose_name='Organizátoři soustředění', |
||||
|
help_text='Seznam organizátorů soustředění', |
||||
|
through='Soustredeni_Organizatori') |
||||
|
|
||||
|
text = models.TextField('text k soustředění (HTML)', blank=True, default='') |
||||
|
|
||||
|
TYP_JARNI = 'jarni' |
||||
|
TYP_PODZIMNI = 'podzimni' |
||||
|
TYP_VIKEND = 'vikend' |
||||
|
TYP_CHOICES = [ |
||||
|
(TYP_JARNI, 'Jarní soustředění'), |
||||
|
(TYP_PODZIMNI, 'Podzimní soustředění'), |
||||
|
(TYP_VIKEND, 'Víkendový sraz'), |
||||
|
] |
||||
|
typ = models.CharField('typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI) |
||||
|
|
||||
|
exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False, |
||||
|
help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)') |
||||
|
|
||||
|
def __str__(self): |
||||
|
return '{} ({})'.format(self.misto, self.datum_zacatku) |
||||
|
|
||||
|
def verejne(self): |
||||
|
return self.verejne_db |
||||
|
verejne.boolean = True |
||||
|
|
||||
|
def verejne_url(self): |
||||
|
#return reverse('seminar_soustredeni', kwargs={'pk': self.id}) |
||||
|
return reverse('seminar_seznam_soustredeni') |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Soustredeni_Ucastnici(SeminarModelBase): |
||||
|
# zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_soustredeni_ucastnici' |
||||
|
verbose_name = 'Účast na soustředění' |
||||
|
verbose_name_plural = 'Účasti na soustředění' |
||||
|
ordering = ['soustredeni', 'resitel'] |
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
resitel = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) |
||||
|
|
||||
|
soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', |
||||
|
on_delete=models.PROTECT) |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka k účasti (plain text)') |
||||
|
|
||||
|
def __str__(self): |
||||
|
return '{} na {}'.format(self.resitel, self.soustredeni) |
||||
|
# NOTE: Poteciální DB HOG bez select_related |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Soustredeni_Organizatori(SeminarModelBase): |
||||
|
# zmena dedicnosti z models.Model na SeminarModelBase, potencialni vznik bugu |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_soustredeni_organizatori' |
||||
|
verbose_name = 'Účast organizátorů na soustředění' |
||||
|
verbose_name_plural = 'Účasti organizátorů na soustředění' |
||||
|
ordering = ['soustredeni', 'organizator'] |
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
organizator = models.ForeignKey(pm.Organizator, verbose_name='organizátor', |
||||
|
on_delete=models.PROTECT) |
||||
|
|
||||
|
soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', |
||||
|
on_delete=models.PROTECT) |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka k účasti organizátora (plain text)') |
||||
|
|
||||
|
def __str__(self): |
||||
|
return '{} na {}'.format(self.organizator, self.soustredeni) |
||||
|
# NOTE: Poteciální DB HOG bez select_related |
||||
|
|
||||
|
|
||||
|
# FIXME cycle import |
||||
|
|
||||
|
|
||||
|
# Django neumí jednoduše serializovat partial nebo třídu s __call__ |
||||
|
# (https://docs.djangoproject.com/en/1.8/topics/migrations/), |
||||
|
# neprojdou pak migrace. Takže rozlišení funkcí generujících názvy souboru |
||||
|
# podle adresáře řešíme takto. |
||||
|
|
||||
|
## |
||||
|
def generate_filename_konfera(self, filename): |
||||
|
return os.path.join( |
||||
|
settings.SEMINAR_KONFERY_DIR, |
||||
|
am.aux_generate_filename(self, filename) |
||||
|
) |
||||
|
|
||||
|
## |
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Konfera(am.Problem): |
||||
|
class Meta: |
||||
|
db_table = 'seminar_konfera' |
||||
|
verbose_name = 'Konfera' |
||||
|
verbose_name_plural = 'Konfery' |
||||
|
|
||||
|
anotace = models.TextField('anotace', blank=True, |
||||
|
help_text='Popis, o čem bude konfera.') |
||||
|
|
||||
|
abstrakt = models.TextField('abstrakt', blank=True, |
||||
|
help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') |
||||
|
|
||||
|
# FIXME: Umíme omezit jen na účastníky daného soustřeďka? |
||||
|
ucastnici = models.ManyToManyField(pm.Resitel, verbose_name='účastníci konfery', |
||||
|
help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') |
||||
|
|
||||
|
soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', |
||||
|
related_name='konfery', on_delete = models.SET_NULL, null=True) |
||||
|
|
||||
|
TYP_VELETRH = 'veletrh' |
||||
|
TYP_PREZENTACE = 'prezentace' |
||||
|
TYP_CHOICES = [ |
||||
|
(TYP_VELETRH, 'Veletrh (postery)'), |
||||
|
(TYP_PREZENTACE, 'Prezentace (přednáška)'), |
||||
|
] |
||||
|
typ_prezentace = models.CharField('typ prezentace', max_length=16, choices=TYP_CHOICES, |
||||
|
blank=False, default=TYP_VELETRH) |
||||
|
|
||||
|
prezentace = models.FileField('prezentace',help_text = 'Prezentace nebo fotka posteru', |
||||
|
upload_to = generate_filename_konfera, blank=True) |
||||
|
|
||||
|
materialy = models.FileField('materialy', |
||||
|
help_text = 'Další materiály ke konfeře zabalené do jednoho souboru', |
||||
|
upload_to = generate_filename_konfera, blank=True) |
||||
|
|
||||
|
def __str__(self): |
||||
|
return "{}: ({})".format(self.nazev, self.soustredeni) |
||||
|
|
||||
|
def cislo_node(self): |
||||
|
return None |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Konfery_Ucastnici(models.Model): |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_konfery_ucastnici' |
||||
|
verbose_name = 'Účast na konfeře' |
||||
|
verbose_name_plural = 'Účasti na konfeře' |
||||
|
ordering = ['konfera', 'resitel'] |
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
resitel = models.ForeignKey(pm.Resitel, verbose_name='řešitel', on_delete=models.PROTECT) |
||||
|
|
||||
|
konfera = models.ForeignKey(Konfera, verbose_name='konfera', on_delete=models.CASCADE) |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka k účasti (plain text)') |
||||
|
|
||||
|
def __str__(self): |
||||
|
return '{} na {}'.format(self.resitel, self.konfera) |
||||
|
# NOTE: Poteciální DB HOG bez select_related |
@ -0,0 +1,5 @@ |
|||||
|
""" |
||||
|
Obsahuje vše (až na přednášky) ohledně soustředění. |
||||
|
|
||||
|
TODO stvrzenky? |
||||
|
""" |
@ -0,0 +1,43 @@ |
|||||
|
from django.contrib import admin |
||||
|
from django.forms import widgets |
||||
|
from django.db import models |
||||
|
|
||||
|
from seminar.models import soustredeni as m |
||||
|
|
||||
|
|
||||
|
class SoustredeniUcastniciInline(admin.TabularInline): |
||||
|
model = m.Soustredeni_Ucastnici |
||||
|
extra = 1 |
||||
|
fields = ['resitel','poznamka'] |
||||
|
autocomplete_fields = ['resitel'] |
||||
|
ordering = ['resitel__osoba__jmeno', 'resitel__osoba__prijmeni'] |
||||
|
formfield_overrides = { |
||||
|
models.TextField: {'widget': widgets.TextInput} |
||||
|
} |
||||
|
|
||||
|
def get_queryset(self,request): |
||||
|
qs = super().get_queryset(request) |
||||
|
return qs.select_related('resitel','soustredeni') |
||||
|
|
||||
|
|
||||
|
class SoustredeniOrganizatoriInline(admin.TabularInline): |
||||
|
model = m.Soustredeni.organizatori.through |
||||
|
extra = 1 |
||||
|
fields = ['organizator','poznamka'] |
||||
|
autocomplete_fields = ['organizator'] |
||||
|
ordering = ['organizator__osoba__jmeno','organizator__prijmeni'] |
||||
|
formfield_overrides = { |
||||
|
models.TextField: {'widget': widgets.TextInput} |
||||
|
} |
||||
|
|
||||
|
def get_queryset(self,request): |
||||
|
qs = super().get_queryset(request) |
||||
|
return qs.select_related('organizator', 'soustredeni') |
||||
|
|
||||
|
|
||||
|
@admin.register(m.Soustredeni) |
||||
|
class SoustredeniAdmin(admin.ModelAdmin): |
||||
|
model = m.Soustredeni |
||||
|
inline_type = 'tabular' |
||||
|
inlines = [SoustredeniUcastniciInline, SoustredeniOrganizatoriInline] |
||||
|
|
@ -0,0 +1,5 @@ |
|||||
|
from django.apps import AppConfig |
||||
|
|
||||
|
|
||||
|
class SoustredeniConfig(AppConfig): |
||||
|
name = 'soustredeni' |
@ -0,0 +1,35 @@ |
|||||
|
from django.urls import path, include |
||||
|
from . import views |
||||
|
from seminar.utils import org_required |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path( |
||||
|
'soustredeni/probehlo/', |
||||
|
views.SoustredeniListView.as_view(), |
||||
|
name='seminar_seznam_soustredeni' |
||||
|
), |
||||
|
path( |
||||
|
'soustredeni/<int:soustredeni>/seznam_ucastniku', |
||||
|
org_required(views.SoustredeniUcastniciView.as_view()), |
||||
|
name='soustredeni_ucastnici' |
||||
|
), |
||||
|
path( |
||||
|
'soustredeni/<int:soustredeni>/maily_ucastniku', |
||||
|
org_required(views.SoustredeniMailyUcastnikuView.as_view()), |
||||
|
name='maily_ucastniku' |
||||
|
), |
||||
|
path( |
||||
|
'soustredeni/<int:soustredeni>/export_ucastniku', |
||||
|
org_required(views.soustredeniUcastniciExportView), |
||||
|
name='soustredeni_ucastnici_export' |
||||
|
), |
||||
|
path( |
||||
|
'soustredeni/<int:soustredeni>/obalky.pdf', |
||||
|
org_required(views.soustredeniObalkyView), |
||||
|
name='seminar_soustredeni_obalky' |
||||
|
), |
||||
|
path( |
||||
|
'soustredeni/<int:soustredeni>/fotogalerie/', |
||||
|
include('galerie.urls') |
||||
|
), |
||||
|
] |
@ -0,0 +1,55 @@ |
|||||
|
from django.shortcuts import get_object_or_404 |
||||
|
from django.http import HttpResponse |
||||
|
from django.views import generic |
||||
|
from seminar.models import Soustredeni, Resitel, Soustredeni_Ucastnici # Tohle je stare a chceme se toho zbavit. Pouzivejte s.ToCoChci |
||||
|
import csv |
||||
|
|
||||
|
from seminar.views import obalkyView |
||||
|
|
||||
|
|
||||
|
class SoustredeniListView(generic.ListView): |
||||
|
model = Soustredeni |
||||
|
template_name = 'soustredeni/seznam_soustredeni.html' |
||||
|
|
||||
|
|
||||
|
def soustredeniObalkyView(request, soustredeni): |
||||
|
soustredeni = get_object_or_404(Soustredeni, id=soustredeni) |
||||
|
return obalkyView(request, soustredeni.ucastnici.all()) |
||||
|
|
||||
|
|
||||
|
class SoustredeniUcastniciBaseView(generic.ListView): |
||||
|
model = Soustredeni_Ucastnici |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
soustredeni = get_object_or_404( |
||||
|
Soustredeni, |
||||
|
pk=self.kwargs["soustredeni"] |
||||
|
) |
||||
|
return Soustredeni_Ucastnici.objects.filter( |
||||
|
soustredeni=soustredeni).select_related('resitel') |
||||
|
|
||||
|
|
||||
|
class SoustredeniMailyUcastnikuView(SoustredeniUcastniciBaseView): |
||||
|
""" Seznam e-mailů řešitelů oddělených čárkami. """ |
||||
|
model = Soustredeni_Ucastnici |
||||
|
template_name = 'soustredeni/maily_ucastniku.txt' |
||||
|
|
||||
|
|
||||
|
class SoustredeniUcastniciView(SoustredeniUcastniciBaseView): |
||||
|
""" HTML tabulka účastníků pro tisk. """ |
||||
|
model = Soustredeni_Ucastnici |
||||
|
template_name = 'soustredeni/seznam_ucastniku.html' |
||||
|
|
||||
|
|
||||
|
def soustredeniUcastniciExportView(request, soustredeni): |
||||
|
soustredeni = get_object_or_404(Soustredeni, id=soustredeni) |
||||
|
ucastnici = Resitel.objects.filter(soustredeni=soustredeni) |
||||
|
response = HttpResponse(content_type='text/csv') |
||||
|
response['Content-Disposition'] = 'attachment; filename="ucastnici.csv"' |
||||
|
|
||||
|
writer = csv.writer(response) |
||||
|
writer.writerow(["jmeno", "prijmeni", "rok_maturity", "telefon", "email", "ulice", "mesto", "psc","stat"]) |
||||
|
for u in ucastnici: |
||||
|
o = u.osoba |
||||
|
writer.writerow([o.jmeno, o.prijmeni, str(u.rok_maturity), o.telefon, o.email, o.ulice, o.mesto, o.psc, o.stat.name]) |
||||
|
return response |
Loading…
Reference in new issue