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