Browse Source

Merge branch 'data_migrations' of gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb into data_migrations

export_seznamu_prednasek
Tomáš Domes 6 years ago
parent
commit
34f44c5c99
  1. 50
      seminar/admin.py
  2. 5
      seminar/migrations/0058_problem_to_uloha_tema_clanek.py
  3. 40
      seminar/models.py
  4. 71
      seminar/old_views.py
  5. 5
      seminar/urls.py
  6. 66
      seminar/views.py

50
seminar/admin.py

@ -18,13 +18,13 @@ from autocomplete_light import shortcuts as autocomplete_light
class UserModelChoiceField(forms.ModelChoiceField):
u"""Vlastní ModelChoiceField pro uživatele. Zobrazí kromě loginu i jméno.
"""Vlastní ModelChoiceField pro uživatele. Zobrazí kromě loginu i jméno.
"""
def label_from_instance(self, obj):
return u"{} ({})".format(obj.get_full_name(), obj.username)
return "{} ({})".format(obj.get_full_name(), obj.username)
def get_form_predvypln_autora(self, request, obj=None, *args, **kwargs):
u"""get_form fce pro Adminy. Předvyplňí přihlášeného uživatele jako autora.
"""get_form fce pro Adminy. Předvyplňí přihlášeného uživatele jako autora.
"""
form = super(self.__class__, self).get_form(request, *args, **kwargs)
form.base_fields['autor'].initial = request.user.id
@ -32,7 +32,7 @@ def get_form_predvypln_autora(self, request, obj=None, *args, **kwargs):
def make_set_action(atribut, hodnota, nazev):
u"""
"""
Pomocnik pro rychle vytvareni hromadnych admin akci ktere jen nastavuji
atribut (dany jako string) na danou hodnotu.
nazev je krátký popis akce pro admin rozhraní."""
@ -214,10 +214,10 @@ class ResitelAdmin(VersionAdmin):
fk_name = 'osoba'
fieldsets = [
(None, {'fields': ['jmeno', 'prijmeni', 'user']}),
(u'Škola', {'fields': ['skola', 'rok_maturity']}),
(u'Seminář', {'fields': ['datum_souhlasu_udaje', 'datum_souhlasu_zasilani', 'datum_prihlaseni', 'zasilat']}),
(u'Osobní údaje', {'fields': ['pohlavi_muz', 'datum_narozeni', 'email', 'telefon']}),
(u'Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
('Škola', {'fields': ['skola', 'rok_maturity']}),
('Seminář', {'fields': ['datum_souhlasu_udaje', 'datum_souhlasu_zasilani', 'datum_prihlaseni', 'zasilat']}),
('Osobní údaje', {'fields': ['pohlavi_muz', 'datum_narozeni', 'email', 'telefon']}),
('Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
]
list_display = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__user', 'osoba__pohlavi_muz', 'skola', 'rok_maturity', 'pocet_reseni']
list_filter = ['osoba__pohlavi_muz', 'rok_maturity', 'zasilat']
@ -262,8 +262,8 @@ admin.site.register(Resitel, ResitelAdmin)
class SkolaAdmin(VersionAdmin):
fieldsets = [
(None, {'fields': ['nazev', 'kratky_nazev', 'je_zs', 'je_ss']}),
(u'Interní ID', {'fields': ['aesop_id', 'izo'], 'classes': ['collapse']}),
(u'Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
('Interní ID', {'fields': ['aesop_id', 'izo'], 'classes': ['collapse']}),
('Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
(None, {'fields': ['poznamka']}),
]
list_display = ['nazev', 'aesop_id', 'mesto', 'ulice', 'stat', 'je_zs', 'je_ss']
@ -328,8 +328,8 @@ class RocnikAdmin(VersionAdmin):
inlines = [CisloInline]
view_on_site = Rocnik.verejne_url
actions = [
make_set_action('exportovat', True, u'Nastavit pro AESOP export'),
make_set_action('exportovat', False, u'Skrýt pro AESOP export'),
make_set_action('exportovat', True, 'Nastavit pro AESOP export'),
make_set_action('exportovat', False, 'Skrýt pro AESOP export'),
]
admin.site.register(Rocnik, RocnikAdmin)
@ -341,7 +341,7 @@ admin.site.register(Rocnik, RocnikAdmin)
# readonly_fields = ['timestamp', 'reseni']
# fieldsets = [
# (None, {'fields': ['reseni', 'soubor', 'timestamp']}),
# (u'Poznámky', {'fields': ['poznamka']}),
# ('Poznámky', {'fields': ['poznamka']}),
# ]
# list_display = ['reseni', 'soubor', 'timestamp']
# list_filter = ['reseni', 'timestamp']
@ -356,7 +356,7 @@ class ReseniAdmin(VersionAdmin):
#form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['problem', 'resitele'], fields=['problem', 'resitele'])
fieldsets = [
(None, {'fields': ['problem__set', 'resitele__set', 'forma', 'cas_doruceni']}),
(u'Poznámky', {'fields': ['poznamka']}),
('Poznámky', {'fields': ['poznamka']}),
]
readonly_fields = ['cas_doruceni']
list_display = [ResitelInline, 'forma', 'cas_doruceni']
@ -400,11 +400,11 @@ class PohadkaAdmin(VersionAdmin):
def get_kod_ulohy(self, obj):
return obj.uloha.kod_v_rocniku()
get_kod_ulohy.short_description = u'Kód úlohy'
get_kod_ulohy.short_description = 'Kód úlohy'
def get_rocnik(self, obj):
return obj.uloha.cislo_zadani.rocnik.rocnik
get_rocnik.short_description = u'Ročník'
get_rocnik.short_description = 'Ročník'
list_display = [
'__str__',
@ -477,7 +477,7 @@ class ProblemAdmin(VersionAdmin):
form = ProblemAdminForm
fieldsets = [
(None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp', 'import_dakos_id']}),
(u'Vydání', {'fields': ['kod', 'cislo_reseni', 'opravovatel',]}),
('Vydání', {'fields': ['kod', 'cislo_reseni', 'opravovatel',]}),
(None, {'fields': ['text_zadani', 'text_reseni', 'text_org',]}),
]
list_select_related = True
@ -506,7 +506,7 @@ class ProblemNavrhAdmin(ProblemAdmin):
#FIXME
#create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name=u'Problém (návrh)', verbose_name_plural=u'Problémy (návrhy)')
#create_modeladmin(ProblemNavrhAdmin, Problem, 'ProblemNavrh', verbose_name='Problém (návrh)', verbose_name_plural='Problémy (návrhy)')
class ProblemZadanyAdmin(ProblemAdmin):
@ -531,7 +531,7 @@ class ProblemZadanyAdmin(ProblemAdmin):
reverse("admin:seminar_cislo_change", args=(obj.cislo_zadani.pk,)),
obj.cislo_zadani
))
cislo_zadani_link.short_description = u'Číslo zadání'
cislo_zadani_link.short_description = 'Číslo zadání'
# TODO pokud se budou odkazy v adminu více používat, možná by se hodilo je
# nějak zjednodušit, např. tímto?
@ -543,7 +543,7 @@ class ProblemZadanyAdmin(ProblemAdmin):
reverse("admin:seminar_cislo_change", args=(obj.cislo_reseni.pk,)),
obj.cislo_reseni
))
cislo_reseni_link.short_description = u'Číslo řešení'
cislo_reseni_link.short_description = 'Číslo řešení'
def get_inline_instances(self, request, obj=None):
if obj and obj.typ == Problem.TYP_ULOHA:
@ -560,7 +560,7 @@ class ProblemZadanyAdmin(ProblemAdmin):
get_form = get_form_predvypln_autora
#FIXME
#create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name=u'Problém (zadaný)', verbose_name_plural=u'Problémy (zadané)')
#create_modeladmin(ProblemZadanyAdmin, Problem, 'ProblemZadany', verbose_name='Problém (zadaný)', verbose_name_plural='Problémy (zadané)')
#admin.site.register(Problem, ProblemAdmin)
@ -601,10 +601,10 @@ class SoustredeniAdmin(VersionAdmin):
list_filter = ['typ', 'rocnik']
view_on_site = Soustredeni.verejne_url
actions = [
make_set_action('verejne_db', True, u'Zveřejnit soustředění'),
make_set_action('verejne_db', False, u'Skrýt (zneveřejnit) soustředění'),
make_set_action('exportovat', True, u'Nastavit pro AESOP export'),
make_set_action('exportovat', False, u'Skrýt pro AESOP export'),
make_set_action('verejne_db', True, 'Zveřejnit soustředění'),
make_set_action('verejne_db', False, 'Skrýt (zneveřejnit) soustředění'),
make_set_action('exportovat', True, 'Nastavit pro AESOP export'),
make_set_action('exportovat', False, 'Skrýt pro AESOP export'),
]
admin.site.register(Soustredeni, SoustredeniAdmin)

5
seminar/migrations/0058_problem_to_uloha_tema_clanek.py

@ -91,8 +91,7 @@ def clanek_to_Clanek(apps,schema_editor):
elif cl.cislo_reseni_old == cl.cislo_zadani_old:
cislo = cl.cislo_zadani_old
else:
cislo = cl.cislo_zadani_old
#raise ValueError("Různá čísla zadání a řešení u článku!")
raise ValueError("Různá čísla zadání a řešení u článku! (Článek: {})".format(cl.nazev))
clnew = Clanek.objects.create(
problem_ptr = cl,
@ -132,7 +131,7 @@ def tema_to_Tema(apps, schema_editor):
elif t.cislo_reseni_old.rocnik == t.cislo_zadani_old.rocnik:
rocnik = t.cislo_zadani_old.rocnik
else:
raise ValueError("Nelze mít téma přes více ročníků!")
raise ValueError("Nelze mít téma přes více ročníků! (Téma: {}".format(t.nazev))
tnew = Tema.objects.create(
problem_ptr = t,

40
seminar/models.py

@ -115,6 +115,11 @@ class Osoba(SeminarModelBase):
],
options={'quality': 95})
# má OneToOneField nejvýše s:
# Resitel
# Prijemce
# Organizator
def plne_jmeno(self):
return '{} {}'.format(self.jmeno, self.prijmeni)
@ -314,7 +319,11 @@ class Rocnik(SeminarModelBase):
rocnik = models.IntegerField('číslo ročníku', db_index=True, unique=True)
exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False,
help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti), a to jen čísla s veřejnou výsledkovkou')
help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti),'
' a to jen čísla s veřejnou výsledkovkou')
# má OneToOneField s:
# RocnikNode
def __str__(self):
return '{} ({}/{})'.format(self.rocnik, self.prvni_rok, self.prvni_rok+1)
@ -409,6 +418,8 @@ class Cislo(SeminarModelBase):
pdf = models.FileField('pdf', upload_to=cislo_pdf_filename, null=True, blank=True,
help_text='Pdf čísla, které si mohou řešitelé stáhnout')
# má OneToOneField s:
# CisloNode
def kod(self):
return '%s.%s' % (self.rocnik.rocnik, self.cislo)
@ -560,7 +571,10 @@ class Problem(SeminarModelBase):
class Meta:
# Není abstraktní, protože se na něj jinak nedají dělat ForeignKeys.
# TODO: Udělat to polymorfní (pomocí django-polymorphic), abychom dostali po těch vazbách přímo tu úlohu/témátko vč. fieldů, které nejsou součástí modelu Problem?
# TODO: Udělat to polymorfní (pomocí django-polymorphic), abychom dostali
# po těch vazbách přímo tu úlohu/témátko vč. fieldů, které nejsou součástí
# modelu Problem?
#abstract = True
db_table = 'seminar_problemy'
verbose_name = 'Problém'
@ -678,6 +692,10 @@ class Clanek(Problem):
verbose_name_plural = 'Články'
cislo = models.ForeignKey(Cislo, verbose_name='číslo', blank=True, null=True)
# má OneToOneField s:
# ClanekNode
def kod_v_rocniku(self):
if self.stav == 'zadany':
# Nemělo by být potřeba
@ -698,9 +716,13 @@ class Text(SeminarModelBase):
do_cisla = models.TextField('text do čísla', blank=True,
help_text='Text ke zveřejnění v čísle')
# má OneToOneField s:
# Reseni (je u něj jako reseni_cele)
# obrázky mají návaznost opačným směrem (vazba z druhé strany)
class Uloha(Problem):
class Meta:
db_table = 'seminar_ulohy'
@ -720,6 +742,10 @@ class Uloha(Problem):
max_body = models.DecimalField(max_digits=8, decimal_places=1, verbose_name='maximum bodů',
blank=True, null=True)
# má OneToOneField s:
# UlohaZadaniNode
# UlohaVzorakNode
def kod_v_rocniku(self):
if self.stav == 'zadany':
name="{}.u{}".format(self.cislo_zadani.cislo,self.kod)
@ -729,7 +755,6 @@ class Uloha(Problem):
return '<Není zadaný>'
@reversion.register(ignore_duplicates=True)
class Reseni(SeminarModelBase):
@ -776,6 +801,9 @@ class Reseni(SeminarModelBase):
zverejneno = models.BooleanField('řešení zveřejněno', default=False,
help_text='Udává, zda je řešení zveřejněno')
# má OneToOneField s:
# Konfera
def __str__(self):
return "{}: {}".format(self.resitel.osoba.plne_jmeno(), self.problem.nazev)
# NOTE: Potenciální DB HOG (bez select_related)
@ -897,6 +925,9 @@ class Pohadka(SeminarModelBase):
editable=False
)
# má OneToOneField s:
# PohadkaNode
def __str__(self):
uryvek = self.text if len(self.text) < 50 else self.text[:(50-3)]+"..."
return uryvek
@ -1001,6 +1032,9 @@ class Konfera(models.Model):
help_text = 'Další materiály ke konfeře zabalené do jednoho souboru',
upload_to = generate_filename_konfera, blank=True)
# má OneToOneField s:
# KonferaNode
def __str__(self):
return "{}: ({})".format(self.nazev, self.soustredeni)

71
seminar/old_views.py

@ -0,0 +1,71 @@
# Tento soubor slouží k odkládání aktuálně nepotřebného kódu, který by
# se však v budoucnu mohl opět hodit.
###################################################################
## Prispevek byl zrusen, mozna ale bude podobny nahled na neco jineho.
#class PrispevekView(generic.DetailView):
# model = Prispevek
# template_name = 'seminar/archiv/prispevek.html'
#
# # Vlastni ziskavani objektu z databaze podle prispevku
# # pokud je prispevek neverejny zobrazi se jenom orgum
# def get_object(self, queryset=None):
# if queryset is None:
# queryset = self.get_queryset()
# problem_arg = self.kwargs.get('pk')
# prispevek_arg = self.kwargs.get('prispevek')
# queryset = queryset.filter(pk=prispevek_arg)
#
# try:
# obj = queryset.get()
# except queryset.model.DoesNotExist:
# raise Http404(_("No %(verbose_name)s found matching the query") %
# {'verbose_name': queryset.model._meta.verbose_name})
#
# if self.request.user.is_staff or obj.zverejnit:
# return obj
# else:
# raise Http404()
#
# def get_context_data(self, **kwargs):
# context = super(PrispevekView, self).get_context_data(**kwargs)
# # snaho o ziskani titulu
# titul = ''
# try:
# resitel = context['prispevek'].reseni.resitel
# cislo = context['prispevek'].reseni.cislo_body
# body = VysledkyKCisluOdjakziva.objects.get(resitel=resitel,
# cislo=cislo).body
# titul = resitel.get_titul(body)
# except:
# pass
# context['titul'] = titul
# return context
####################################################################
## Stvrzenky aktuálně nevydáváme, ale možná časem zase budeme.
#def soustredeniStvrzenkyExportView(request,soustredeni,first_num):
# first_num = int(first_num)
# soustredeni = get_object_or_404(Soustredeni,id = soustredeni)
# ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
# for (idx,u) in enumerate(ucastnici):
# u.cislo_stvrzenky = first_num+idx;
# tex = render(request,'seminar/soustredeni/ucastnici.tex', {'ucastnici': ucastnici, 'datum':soustredeni.datum_zacatku }).content
#
# tempdir = tempfile.mkdtemp()
# with open(tempdir+"/ucastnici.tex","w") as texfile:
# # Pokud TeX chce ISO Latin, tak se da encode nastavit
# texfile.write(tex.decode("utf-8").encode("utf-8"))
# shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenka.sty'),tempdir)
# shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenky.tex'),tempdir)
# subprocess.call(["cslatex","stvrzenky.tex"],cwd = tempdir)
# subprocess.call(["dvipdf","stvrzenky.dvi"],cwd = tempdir)
#
# with open(tempdir+"/stvrzenky.pdf","rb") as pdffile:
# response = HttpResponse(pdffile.read(),content_type='application/pdf')
# shutil.rmtree(tempdir)
# return response

5
seminar/urls.py

@ -45,11 +45,6 @@ urlpatterns = [
staff_member_required(views.SoustredeniMailyUcastnikuView.as_view()),
name='maily_ucastniku'
),
url(
r'^soustredeni/(?P<soustredeni>\d+)/stvrzenky/(?P<first_num>\d+)$',
staff_member_required(views.soustredeniStvrzenkyExportView),
name='soustredeni_stvrzenky'
),
url(
r'^soustredeni/(?P<soustredeni>\d+)/export_ucastniku$',
staff_member_required(views.soustredeniUcastniciExportView),

66
seminar/views.py

@ -377,47 +377,6 @@ class ProblemView(generic.DetailView):
context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni')
return context
## Prispevek byl zrusen, mozna ale bude podobny nahled na neco jineho.
#class PrispevekView(generic.DetailView):
# model = Prispevek
# template_name = 'seminar/archiv/prispevek.html'
#
# # Vlastni ziskavani objektu z databaze podle prispevku
# # pokud je prispevek neverejny zobrazi se jenom orgum
# def get_object(self, queryset=None):
# if queryset is None:
# queryset = self.get_queryset()
# problem_arg = self.kwargs.get('pk')
# prispevek_arg = self.kwargs.get('prispevek')
# queryset = queryset.filter(pk=prispevek_arg)
#
# try:
# obj = queryset.get()
# except queryset.model.DoesNotExist:
# raise Http404(_("No %(verbose_name)s found matching the query") %
# {'verbose_name': queryset.model._meta.verbose_name})
#
# if self.request.user.is_staff or obj.zverejnit:
# return obj
# else:
# raise Http404()
#
# def get_context_data(self, **kwargs):
# context = super(PrispevekView, self).get_context_data(**kwargs)
# # snaho o ziskani titulu
# titul = ''
# try:
# resitel = context['prispevek'].reseni.resitel
# cislo = context['prispevek'].reseni.cislo_body
# body = VysledkyKCisluOdjakziva.objects.get(resitel=resitel,
# cislo=cislo).body
# titul = resitel.get_titul(body)
# except:
# pass
# context['titul'] = titul
# return context
class RadekVysledkovky(object):
pass
@ -465,7 +424,6 @@ class RadekVysledkovky(object):
# #setridi problemy podle typu a poradi zadani
# problem_index = {}
# for i in range(len(problemy)):
# problem_index[problemy[i].id] = i
# #umoznuje zjistit index podle id problemu
#
# vysledky_resitele = {}
@ -665,30 +623,6 @@ class SoustredeniUcastniciView(SoustredeniUcastniciBaseView):
model = Soustredeni_Ucastnici
template_name = 'seminar/soustredeni/seznam_ucastniku.html'
def soustredeniStvrzenkyExportView(request,soustredeni,first_num):
first_num = int(first_num)
soustredeni = get_object_or_404(Soustredeni,id = soustredeni)
ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
for (idx,u) in enumerate(ucastnici):
u.cislo_stvrzenky = first_num+idx;
tex = render(request,'seminar/soustredeni/ucastnici.tex', {'ucastnici': ucastnici, 'datum':soustredeni.datum_zacatku }).content
tempdir = tempfile.mkdtemp()
with open(tempdir+"/ucastnici.tex","w") as texfile:
# Pokud TeX chce ISO Latin, tak se da encode nastavit
texfile.write(tex.decode("utf-8").encode("utf-8"))
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenka.sty'),tempdir)
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/stvrzenky.tex'),tempdir)
subprocess.call(["cslatex","stvrzenky.tex"],cwd = tempdir)
subprocess.call(["dvipdf","stvrzenky.dvi"],cwd = tempdir)
with open(tempdir+"/stvrzenky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(),content_type='application/pdf')
shutil.rmtree(tempdir)
return response
def soustredeniUcastniciExportView(request,soustredeni):
soustredeni = get_object_or_404(Soustredeni,id = soustredeni)
ucastnici = Resitel.objects.filter(soustredeni=soustredeni)

Loading…
Cancel
Save