Browse Source

Merge remote branch 'origin/master' into Petr

Conflicts:
	seminar/admin.py
remotes/origin/feincms
Bc. Petr Pecha 10 years ago
parent
commit
0fa9bbe76e
  1. 25
      mamweb/settings_common.py
  2. BIN
      mamweb/static/favicon.ico
  3. 1
      mamweb/templates/admin/base_site.html
  4. 1
      mamweb/templates/base.html
  5. 3
      requirements.txt
  6. 215
      seminar/admin.py
  7. 4
      seminar/autocomplete_light_registry.py
  8. 18
      seminar/migrations/0012_remove_soustredeni_ucastnici.py
  9. 36
      seminar/migrations/0013_soustredeni_ucastnici_through_model.py
  10. 50
      seminar/migrations/0014_uprava_poznamek.py
  11. 64
      seminar/models.py
  12. 2
      seminar/urls.py
  13. 6
      seminar/views.py

25
mamweb/settings_common.py

@ -49,9 +49,11 @@ AUTHENTICATION_BACKENDS = (
) )
TEMPLATE_LOADERS = ( TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader', ('django.template.loaders.cached.Loader', (
'django.template.loaders.app_directories.Loader', 'django.template.loaders.filesystem.Loader',
'django.template.loaders.eggs.Loader' 'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader'
)),
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
@ -95,17 +97,22 @@ INSTALLED_APPS = (
'solo', 'solo',
'ckeditor', 'ckeditor',
'taggit', 'taggit',
'autocomplete_light',
# MaMweb # MaMweb
'mamweb', 'mamweb',
'seminar', 'seminar',
# Prvni: # Admin upravy:
'autocomplete_light',
'admin_tools', # 'material',
'admin_tools.theming', # 'material.admin',
'admin_tools.menu', # 'admin_tools',
'admin_tools.dashboard', # 'admin_tools.theming',
# 'admin_tools.menu',
# 'admin_tools.dashboard',
'flat',
'django.contrib.admin', 'django.contrib.admin',
) )

BIN
mamweb/static/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

1
mamweb/templates/admin/base_site.html

@ -2,6 +2,7 @@
{% load staticfiles %} {% load staticfiles %}
{% block extrahead %} {% block extrahead %}
<link rel="shortcut icon" href="{% static 'favicon.ico' %}" type="image/x-icon">
<script src="{% static 'js/jquery-1.11.1.js' %}"></script> <script src="{% static 'js/jquery-1.11.1.js' %}"></script>
{% include 'autocomplete_light/static.html' %} {% include 'autocomplete_light/static.html' %}
{% endblock %} {% endblock %}

1
mamweb/templates/base.html

@ -4,6 +4,7 @@
<head> <head>
<title>{% block title %}Seminář M&amp;M{% endblock title %}</title> <title>{% block title %}Seminář M&amp;M{% endblock title %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="{% static 'favicon.ico' %}" type="image/x-icon">
{% render_block "css" %} {% render_block "css" %}
<link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet"> <link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet">
<link href="{% static 'css/bootstrap.css' %}" rel="stylesheet"> <link href="{% static 'css/bootstrap.css' %}" rel="stylesheet">

3
requirements.txt

@ -17,9 +17,10 @@ django-sekizai==0.8.1
django-countries==3.2 django-countries==3.2
django-solo==1.1.0 django-solo==1.1.0
django-ckeditor==4.4.7 django-ckeditor==4.4.7
django-admin-tools==0.5.2 django-flat-theme==0.9.3
django-taggit==0.14.0 django-taggit==0.14.0
django-autocomplete-light==2.1.1 django-autocomplete-light==2.1.1
# django-admin-tools==0.5.2
# debug tools/extensions # debug tools/extensions

215
seminar/admin.py

@ -1,31 +1,115 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.contrib import admin from django.contrib import admin
from django import forms from django import forms
from django.forms import widgets
import reversion import reversion
from solo.admin import SingletonModelAdmin from solo.admin import SingletonModelAdmin
from ckeditor.widgets import CKEditorWidget from ckeditor.widgets import CKEditorWidget
from django.db.models import Count
from django.db import models
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici
import autocomplete_light import autocomplete_light
### Nastaveni
### Globální nastavení
admin.site.register(Nastaveni, SingletonModelAdmin) admin.site.register(Nastaveni, SingletonModelAdmin)
### Skola
class SkolaAdmin(reversion.VersionAdmin): ### INLINES
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']}),
]
list_display = ['nazev', 'aesop_id', 'mesto', 'ulice', 'stat', 'je_zs', 'je_ss']
list_filter = ['stat', 'je_zs', 'je_ss']
search_fields = ['nazev', 'mesto', 'ulice']
admin.site.register(Skola, SkolaAdmin) class ResitelInline(admin.TabularInline):
model = Resitel
fields = ['jmeno', 'prijmeni', 'skola', 'mesto', 'rok_maturity', ]
readonly_fields = ['jmeno', 'prijmeni', 'skola', 'mesto', 'rok_maturity', ]
extra = 0
def has_add_permission(self, req): return False
class CisloInline(admin.TabularInline):
model = Cislo
fields = ['cislo', 'datum_vydani', 'datum_deadline', 'verejne_db', 'poznamka']
readonly_fields = ['cislo']
extra = 0
formfield_overrides = {
models.TextField: {'widget': forms.TextInput},
}
def has_add_permission(self, req): return False
class PrilohaReseniInline(admin.StackedInline):
model = PrilohaReseni
fields = ['timestamp', 'soubor', 'poznamka']
readonly_fields = ['timestamp']
formfield_overrides = {
models.TextField: {'widget': forms.TextInput},
}
extra = 0
class ReseniKProblemuInline(admin.TabularInline):
form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['resitel'], fields=['resitel'])
model = Reseni
fields = ['resitel', 'forma', 'body', 'cislo_body', 'timestamp', 'poznamka']
readonly_fields = ['timestamp']
extra = 0
formfield_overrides = {
models.TextField: {'widget': forms.TextInput},
}
def get_queryset(self, request):
qs = super(ReseniKProblemuInline, self).get_queryset(request)
return qs.select_related('problem', 'cislo_body', 'resitel')
# Potenciální DB HOG (cislo_body se dotazovalo na cisla pri kazdem zobrazeni jejich selectu ...)
def formfield_for_dbfield(self, db_field, **kwargs):
formfield = super(ReseniKProblemuInline, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'cislo_body':
# dirty trick so queryset is evaluated and cached in .choices
formfield.choices = formfield.choices
return formfield
class ReseniKResiteliInline(admin.TabularInline):
model = Reseni
fields = ['problem', 'forma', 'body', 'cislo_body', 'timestamp', 'poznamka']
readonly_fields = ['timestamp', 'problem']
extra = 0
formfield_overrides = {
models.TextField: {'widget': forms.TextInput},
}
def has_add_permission(self, req): return False
def get_queryset(self, request):
qs = super(ReseniKResiteliInline, self).get_queryset(request)
return qs.select_related('problem', 'cislo_body', 'resitel')
# Potenciální DB HOG (cislo_body se dotazovalo na cisla pri kazdem zobrazeni jejich selectu ...)
def formfield_for_dbfield(self, db_field, **kwargs):
formfield = super(ReseniKResiteliInline, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'cislo_body':
# dirty trick so queryset is evaluated and cached in .choices
formfield.choices = formfield.choices
return formfield
class Soustredeni_UcastniciInline(admin.TabularInline):
form = autocomplete_light.modelform_factory(Soustredeni_Ucastnici, autocomplete_fields=['resitel'], fields=['resitel'])
model = Soustredeni_Ucastnici
fields = ['resitel', 'poznamka', ]
extra = 0
formfield_overrides = {
models.TextField: {'widget': forms.TextInput},
}
def get_queryset(self, request):
qs = super(Soustredeni_UcastniciInline, self).get_queryset(request)
return qs.select_related('resitel', 'soustredeni')
### Resitel ### Resitel
class ResitelAdmin(reversion.VersionAdmin): class ResitelAdmin(reversion.VersionAdmin):
@ -37,33 +121,55 @@ class ResitelAdmin(reversion.VersionAdmin):
(u'Osobní údaje', {'fields': ['pohlavi_muz', 'datum_narozeni', 'email', 'telefon']}), (u'Osobní údaje', {'fields': ['pohlavi_muz', 'datum_narozeni', 'email', 'telefon']}),
(u'Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}), (u'Adresa', {'fields': ['ulice', 'mesto', 'psc', 'stat']}),
] ]
list_display = ['jmeno', 'prijmeni', 'user', 'pohlavi_muz', 'skola', 'rok_maturity'] list_display = ['jmeno', 'prijmeni', 'user', 'pohlavi_muz', 'skola', 'rok_maturity', 'pocet_reseni']
list_filter = ['pohlavi_muz', 'rok_maturity', 'zasilat'] list_filter = ['pohlavi_muz', 'rok_maturity', 'zasilat']
search_fields = ['jmeno', 'prijmeni', 'ulice', 'user', 'mesto', 'email'] search_fields = ['jmeno', 'prijmeni', 'ulice', 'user', 'mesto', 'email']
inlines = [ReseniKResiteliInline]
def get_queryset(self, request):
qs = super(ResitelAdmin, self).get_queryset(request)
return qs.select_related('skola', 'user').annotate(pocet_reseni=Count('reseni'))
def pocet_reseni(self, obj):
return obj.pocet_reseni
admin.site.register(Resitel, ResitelAdmin) admin.site.register(Resitel, ResitelAdmin)
### Skola
class SkolaAdmin(reversion.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']}),
(None, {'fields': ['poznamka']}),
]
list_display = ['nazev', 'aesop_id', 'mesto', 'ulice', 'stat', 'je_zs', 'je_ss']
list_filter = ['stat', 'je_zs', 'je_ss']
search_fields = ['nazev', 'mesto', 'ulice']
inlines = [ResitelInline]
admin.site.register(Skola, SkolaAdmin)
### Cislo ### Cislo
class CisloAdmin(reversion.VersionAdmin): class CisloAdmin(reversion.VersionAdmin):
fieldsets = [ fieldsets = [
(None, {'fields': ['cislo', 'rocnik', 'verejne_db']}), (None, {'fields': ['cislo', 'rocnik', 'verejne_db', 'poznamka']}),
(u'Data', {'fields': ['datum_vydani', 'datum_deadline']}), (u'Data', {'fields': ['datum_vydani', 'datum_deadline']}),
] ]
list_display = ['kod', 'rocnik', 'cislo', 'datum_vydani', 'datum_deadline', 'verejne'] list_display = ['kod', 'rocnik', 'cislo', 'datum_vydani', 'datum_deadline', 'verejne']
list_filter = ['rocnik'] list_filter = ['rocnik']
view_on_site = Cislo.verejne_url view_on_site = Cislo.verejne_url
def get_queryset(self, request):
qs = super(CisloAdmin, self).get_queryset(request)
return qs.select_related('rocnik')
admin.site.register(Cislo, CisloAdmin) admin.site.register(Cislo, CisloAdmin)
class CisloInline(admin.StackedInline):
model = Cislo
fields = ['cislo', 'datum_vydani', 'datum_deadline', 'verejne_db']
readonly_fields = ['cislo']
extra = 0
### Rocnik ### Rocnik
class RocnikAdmin(reversion.VersionAdmin): class RocnikAdmin(reversion.VersionAdmin):
@ -78,55 +184,50 @@ admin.site.register(Rocnik, RocnikAdmin)
### PrilohaReseni ### PrilohaReseni
# NOTE: Nemá pravděpodobně smysl používat
class PrilohaReseniAdmin(reversion.VersionAdmin): # class PrilohaReseniAdmin(reversion.VersionAdmin):
readonly_fields = ['timestamp', 'reseni'] # readonly_fields = ['timestamp', 'reseni']
fieldsets = [ # fieldsets = [
(None, {'fields': ['reseni', 'soubor', 'timestamp']}), # (None, {'fields': ['reseni', 'soubor', 'timestamp']}),
(u'Poznámky', {'fields': ['poznamka']}), # (u'Poznámky', {'fields': ['poznamka']}),
] # ]
list_display = ['reseni', 'soubor', 'timestamp'] # list_display = ['reseni', 'soubor', 'timestamp']
list_filter = ['reseni', 'timestamp'] # list_filter = ['reseni', 'timestamp']
search_fields = [] # search_fields = []
#
admin.site.register(PrilohaReseni, PrilohaReseniAdmin) # admin.site.register(PrilohaReseni, PrilohaReseniAdmin)
class PrilohaReseniInline(admin.StackedInline):
model = PrilohaReseni
fields = ['timestamp', 'soubor', 'poznamka']
readonly_fields = ['timestamp']
extra = 1
### Reseni ### Reseni
class ReseniAdmin(reversion.VersionAdmin): class ReseniAdmin(reversion.VersionAdmin):
form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['problem'], fields=['problem']) form = autocomplete_light.modelform_factory(Reseni, autocomplete_fields=['problem', 'resitel'], fields=['problem', 'resitel'])
fieldsets = [ fieldsets = [
(None, {'fields': ['problem', 'resitel', 'forma', 'body', 'cislo_body', 'timestamp']}), (None, {'fields': ['problem', 'resitel', 'forma', 'body', 'cislo_body', 'timestamp']}),
(u'Poznámky', {'fields': ['poznamka']}), (u'Poznámky', {'fields': ['poznamka']}),
] ]
readonly_fields = ['timestamp'] readonly_fields = ['timestamp']
list_display = ['problem', 'resitel', 'forma', 'body', 'timestamp'] list_display = ['problem', 'resitel', 'forma', 'body', 'timestamp', 'cislo_body']
list_filter = ['body', 'timestamp', 'forma'] list_filter = ['body', 'timestamp', 'forma']
search_fields = [] search_fields = []
inlines = [PrilohaReseniInline] inlines = [PrilohaReseniInline]
admin.site.register(Reseni, ReseniAdmin) def get_queryset(self, request):
qs = super(ReseniAdmin, self).get_queryset(request)
return qs.select_related('resitel', 'problem', 'cislo_body')
class ReseniInline(admin.TabularInline): admin.site.register(Reseni, ReseniAdmin)
model = Reseni
fields = ['resitel', 'forma', 'body', 'cislo_body', 'timestamp', 'poznamka']
readonly_fields = ['poznamka', 'resitel', 'timestamp', 'cislo_body', 'resitel', 'forma']
extra = 0
### Problem ### Problem
from autocomplete_light.contrib.taggit_field import TaggitField, TaggitWidget
#TODO: Autocomplete autor/opravovatel #TODO: Autocomplete autor/opravovatel
class ProblemAdminForm(forms.ModelForm): class ProblemAdminForm(forms.ModelForm):
text_problemu = forms.CharField(widget=CKEditorWidget()) text_problemu = forms.CharField(widget=CKEditorWidget())
text_problemu_org = forms.CharField(widget=CKEditorWidget()) text_problemu_org = forms.CharField(widget=CKEditorWidget())
zamereni = TaggitField(widget=TaggitWidget('TagAutocomplete'))
class Meta: class Meta:
model = Problem model = Problem
exclude = [] exclude = []
@ -135,17 +236,24 @@ class ProblemAdmin(reversion.VersionAdmin):
form = ProblemAdminForm form = ProblemAdminForm
fieldsets = [ fieldsets = [
(None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp']}), (None, {'fields': ['nazev', 'typ', 'stav', 'autor', 'zamereni', 'body', 'timestamp']}),
(u'Vydání', {'fields': ['cislo_zadani', 'kod', 'cislo_reseni', 'opravovatel']}), (u'Vydání', {'fields': ['cislo_zadani', 'kod', 'cislo_reseni', 'opravovatel', 'text_problemu']}),
(u'Texty', {'fields': ['text_problemu', 'text_problemu_org']}), (None, {'fields': ['text_problemu_org']}),
] ]
readonly_fields = ['timestamp'] readonly_fields = ['timestamp']
list_display = ['nazev', 'typ', 'kod', 'stav', 'autor', 'opravovatel', 'verejne', 'cislo_zadani'] list_display = ['nazev', 'typ', 'kod', 'stav', 'autor', 'opravovatel', 'verejne', 'cislo_zadani', 'pocet_reseni']
list_select_related = True list_select_related = True
list_filter = ['typ', 'stav', 'timestamp'] list_filter = ['typ', 'stav', 'timestamp']
search_fields = ['nazev', 'kod', 'text_problemu_org', 'text_problemu'] search_fields = ['nazev', 'kod', 'text_problemu_org', 'text_problemu']
inlines = [ReseniInline] inlines = [ReseniKProblemuInline]
view_on_site = Problem.verejne_url view_on_site = Problem.verejne_url
def get_queryset(self, request):
qs = super(ProblemAdmin, self).get_queryset(request)
return qs.select_related('autor', 'opravovatel', 'cislo_zadani', 'cislo_reseni').annotate(pocet_reseni=Count('reseni'))
def pocet_reseni(self, obj):
return obj.pocet_reseni
admin.site.register(Problem, ProblemAdmin) admin.site.register(Problem, ProblemAdmin)
@ -157,8 +265,9 @@ class SoustredeniAdmin(reversion.VersionAdmin):
(u'Data', {'fields': ['datum_zacatku', 'datum_konce']}), (u'Data', {'fields': ['datum_zacatku', 'datum_konce']}),
] ]
list_display = ['rocnik', 'misto', 'datum_zacatku', 'verejne'] list_display = ['rocnik', 'misto', 'datum_zacatku', 'verejne']
inlines = [Soustredeni_UcastniciInline]
list_filter = ['rocnik'] list_filter = ['rocnik']
view_on_site = Soustredeni.verejne_url view_on_site = Soustredeni.verejne_url
# TODO: UcastNaSoustredeni jako inline
admin.site.register(Soustredeni, SoustredeniAdmin) admin.site.register(Soustredeni, SoustredeniAdmin)

4
seminar/autocomplete_light_registry.py

@ -3,6 +3,10 @@
import autocomplete_light import autocomplete_light
from models import Skola, Resitel, Problem from models import Skola, Resitel, Problem
from taggit.models import Tag
autocomplete_light.register(Tag)
class SkolaAutocomplete(autocomplete_light.AutocompleteModelBase): class SkolaAutocomplete(autocomplete_light.AutocompleteModelBase):

18
seminar/migrations/0012_remove_soustredeni_ucastnici.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0011_alter_timestamp_def'),
]
operations = [
migrations.RemoveField(
model_name='soustredeni',
name='ucastnici',
),
]

36
seminar/migrations/0013_soustredeni_ucastnici_through_model.py

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0012_remove_soustredeni_ucastnici'),
]
operations = [
migrations.CreateModel(
name='Soustredeni_Ucastnici',
fields=[
('id', models.AutoField(serialize=False, primary_key=True)),
('poznamka', models.CharField(default=b'', help_text='Neve\u0159ejn\xe1 pozn\xe1mka k \xfa\u010dasti (plain text)', max_length=64, verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)),
('resitel', models.ForeignKey(verbose_name='\u0159e\u0161itel', to='seminar.Resitel')),
('soustredeni', models.ForeignKey(verbose_name='soust\u0159ed\u011bn\xed', to='seminar.Soustredeni')),
],
options={
'ordering': ['soustredeni', 'resitel'],
'db_table': 'seminar_soustredeni_ucastnici',
'verbose_name': '\xda\u010dast na soust\u0159ed\u011bn\xed',
'verbose_name_plural': '\xda\u010dasti na soust\u0159ed\u011bn\xed',
},
bases=(models.Model,),
),
migrations.AddField(
model_name='soustredeni',
name='ucastnici',
field=models.ManyToManyField(help_text='Seznam \xfa\u010dastn\xedk\u016f soust\u0159ed\u011bn\xed', to='seminar.Resitel', verbose_name='\xfa\u010dastn\xedci soust\u0159ed\u011bn\xed', through='seminar.Soustredeni_Ucastnici'),
preserve_default=True,
),
]

50
seminar/migrations/0014_uprava_poznamek.py

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0013_soustredeni_ucastnici_through_model'),
]
operations = [
migrations.AlterModelOptions(
name='problem',
options={'ordering': ['nazev'], 'verbose_name': 'Probl\xe9m', 'verbose_name_plural': 'Probl\xe9my'},
),
migrations.AlterModelOptions(
name='reseni',
options={'ordering': ['problem_id', 'resitel_id'], 'verbose_name': '\u0158e\u0161en\xed', 'verbose_name_plural': '\u0158e\u0161en\xed'},
),
migrations.AlterModelOptions(
name='skola',
options={'ordering': ['mesto', 'nazev'], 'verbose_name': '\u0160kola', 'verbose_name_plural': '\u0160koly'},
),
migrations.AddField(
model_name='cislo',
name='poznamka',
field=models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k \u010d\xedslu (plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='problem',
name='text_problemu_org',
field=models.TextField(verbose_name='neve\u0159ejn\xe9 zad\xe1n\xed a organiz\xe1torsk\xe9 a pozn\xe1mky', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='reseni',
name='poznamka',
field=models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k \u0159e\u0161en\xed (plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='soustredeni_ucastnici',
name='poznamka',
field=models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k \xfa\u010dasti (plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True),
preserve_default=True,
),
]

64
seminar/models.py

@ -10,6 +10,8 @@ from django.utils.encoding import python_2_unicode_compatible
from django.utils.encoding import force_unicode from django.utils.encoding import force_unicode
from django.utils.text import slugify from django.utils.text import slugify
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.cache import cache
from django_countries.fields import CountryField from django_countries.fields import CountryField
from solo.models import SingletonModel from solo.models import SingletonModel
@ -19,7 +21,6 @@ import reversion
from seminar.utils import roman from seminar.utils import roman
# TODO společná báze (admin url, url, veřejné, ...)
class SeminarModelBase(models.Model): class SeminarModelBase(models.Model):
class Meta: class Meta:
@ -54,6 +55,7 @@ class Skola(SeminarModelBase):
db_table = 'seminar_skoly' db_table = 'seminar_skoly'
verbose_name = u'Škola' verbose_name = u'Škola'
verbose_name_plural = u'Školy' verbose_name_plural = u'Školy'
ordering = ['mesto', 'nazev']
# Interní ID # Interní ID
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -229,6 +231,16 @@ class Rocnik(SeminarModelBase):
def verejne_url(self): def verejne_url(self):
return reverse('seminar_rocnik', kwargs={'pk': self.id}) return reverse('seminar_rocnik', kwargs={'pk': self.id})
@classmethod
def cached_rocnik(cls, r_id):
name = 'rocnik_%s' % (r_id, )
c = cache.get(name)
if c is None:
c = cls.objects.get(id=r_id)
cache.set(name, c, 300)
return c
@reversion.register(ignore_duplicate_revisions=True) @reversion.register(ignore_duplicate_revisions=True)
@python_2_unicode_compatible @python_2_unicode_compatible
@ -256,12 +268,17 @@ class Cislo(SeminarModelBase):
verejne_db = models.BooleanField(u'číslo zveřejněno', db_column='verejne', default=False) verejne_db = models.BooleanField(u'číslo zveřejněno', db_column='verejne', default=False)
poznamka = models.TextField(u'neveřejná poznámka', blank=True,
help_text=u'Neveřejná poznámka k číslu (plain text)')
def kod(self): def kod(self):
return u'%s.%s' % (self.rocnik.rocnik, self.cislo) return u'%s.%s' % (self.rocnik.rocnik, self.cislo)
kod.short_description = u'Kód čísla' kod.short_description = u'Kód čísla'
def __str__(self): def __str__(self):
return force_unicode(u'%s' % (self.kod(),)) # Potenciální DB HOG, pokud by se ročník neckešoval
r = Rocnik.cached_rocnik(self.rocnik_id)
return force_unicode(u'%s.%s' % (r.rocnik, self.cislo, ))
def verejne(self): def verejne(self):
return self.verejne_db return self.verejne_db
@ -294,6 +311,7 @@ class Problem(SeminarModelBase):
db_table = 'seminar_problemy' db_table = 'seminar_problemy'
verbose_name = u'Problém' verbose_name = u'Problém'
verbose_name_plural = u'Problémy' verbose_name_plural = u'Problémy'
ordering = ['nazev']
# Interní ID # Interní ID
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -327,7 +345,7 @@ class Problem(SeminarModelBase):
zamereni = TaggableManager(verbose_name=u'zaměření', help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True) zamereni = TaggableManager(verbose_name=u'zaměření', help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True)
text_problemu_org = models.TextField(u'organizátorský (neveřejný) text', blank=True) text_problemu_org = models.TextField(u'neveřejné zadání a organizátorské a poznámky', blank=True)
text_problemu = models.TextField(u'veřejný text zadání a řešení', blank=True) text_problemu = models.TextField(u'veřejný text zadání a řešení', blank=True)
@ -354,7 +372,7 @@ class Problem(SeminarModelBase):
u'"DOZ:xxx" (MAMOPER.MM_DOZ), "ZAD:rocnik.cislo.uloha.typ" (MAMOPER.MM_ZADANIA), "ULOHA:xxx" (MAMOPER.MM_ULOHY)')) u'"DOZ:xxx" (MAMOPER.MM_DOZ), "ZAD:rocnik.cislo.uloha.typ" (MAMOPER.MM_ZADANIA), "ULOHA:xxx" (MAMOPER.MM_ULOHY)'))
def __str__(self): def __str__(self):
return force_unicode(u'%s (%s)' % (self.nazev, self.stav)) return force_unicode(u'%s' % (self.nazev, ))
def kod_v_rocniku(self): def kod_v_rocniku(self):
if self.typ == self.TYP_ULOHA: if self.typ == self.TYP_ULOHA:
@ -379,7 +397,7 @@ class Reseni(SeminarModelBase):
db_table = 'seminar_reseni' db_table = 'seminar_reseni'
verbose_name = u'Řešení' verbose_name = u'Řešení'
verbose_name_plural = u'Řešení' verbose_name_plural = u'Řešení'
ordering = ['problem', 'resitel'] ordering = ['problem_id', 'resitel_id']
# Interní ID # Interní ID
id = models.AutoField(primary_key = True) id = models.AutoField(primary_key = True)
@ -405,10 +423,11 @@ class Reseni(SeminarModelBase):
forma = models.CharField(u'forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, default=FORMA_PAPIR) forma = models.CharField(u'forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, default=FORMA_PAPIR)
poznamka = models.TextField(u'neveřejná poznámka', blank=True, poznamka = models.TextField(u'neveřejná poznámka', blank=True,
help_text=u'Neveřejná poznámka k řešení (plain text, editace v detailu řešení)') help_text=u'Neveřejná poznámka k řešení (plain text)')
def __str__(self): def __str__(self):
return force_unicode(u"%s: %s (%sb)" % (self.resitel.plne_jmeno(), self.problem.nazev, self.body)) return force_unicode(u"%s: %s (%sb)" % (self.resitel.plne_jmeno(), self.problem.nazev, self.body))
# NOTE: Potenciální DB HOG (bez select_related)
# PrilohaReseni method # PrilohaReseni method
@ -418,7 +437,7 @@ def generate_filename(self, filename):
fname = "%s_%s" % ( fname = "%s_%s" % (
timezone.now().strftime('%Y-%m-%d-%H:%M'), timezone.now().strftime('%Y-%m-%d-%H:%M'),
clean) clean)
return os.path.join(settings.SEMINAR_RESENI_DIRNAME, datedir, fname) return os.path.join(settings.SEMINAR_RESENI_DIR, datedir, fname)
@reversion.register(ignore_duplicate_revisions=True) @reversion.register(ignore_duplicate_revisions=True)
@ -474,10 +493,10 @@ class Soustredeni(SeminarModelBase):
help_text=u'Místo (název obce, volitelně též objektu') help_text=u'Místo (název obce, volitelně též objektu')
ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci soustředění', ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci soustředění',
help_text=u'Seznam účastníků soustředění', db_table='seminar_soustredeni_ucastnici') help_text=u'Seznam účastníků soustředění', through='Soustredeni_Ucastnici')
def __str__(self): def __str__(self):
return force_unicode(u'%s (%s)' % (self.misto, self.datum_zacatek)) return force_unicode(u'%s (%s)' % (self.misto, self.datum_zacatku))
def verejne(self): def verejne(self):
return self.verejne_db return self.verejne_db
@ -487,6 +506,30 @@ class Soustredeni(SeminarModelBase):
return reverse('seminar_soustredeni', kwargs={'pk': self.id}) return reverse('seminar_soustredeni', kwargs={'pk': self.id})
@python_2_unicode_compatible
class Soustredeni_Ucastnici(models.Model):
class Meta:
db_table = 'seminar_soustredeni_ucastnici'
verbose_name = u'Účast na soustředění'
verbose_name_plural = u'Účasti na soustředění'
ordering = ['soustredeni', 'resitel']
# Interní ID
id = models.AutoField(primary_key = True)
resitel = models.ForeignKey(Resitel, verbose_name=u'řešitel')
soustredeni = models.ForeignKey(Soustredeni, verbose_name=u'soustředění')
poznamka = models.TextField(u'neveřejná poznámka', blank=True,
help_text=u'Neveřejná poznámka k účasti (plain text)')
def __str__(self):
return force_unicode(u'%s na %s' % (self.resitel, self.soustredeni, ))
# NOTE: Poteciální DB HOG bez select_related
@python_2_unicode_compatible @python_2_unicode_compatible
class VysledkyBase(SeminarModelBase): class VysledkyBase(SeminarModelBase):
@ -507,6 +550,7 @@ class VysledkyBase(SeminarModelBase):
def __str__(self): def __str__(self):
return force_unicode(u"%s: %sb (%s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo))) return force_unicode(u"%s: %sb (%s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo)))
# NOTE: DB HOG (ale nepouzivany)
@python_2_unicode_compatible @python_2_unicode_compatible
class VysledkyZaCislo(VysledkyBase): class VysledkyZaCislo(VysledkyBase):
@ -517,6 +561,7 @@ class VysledkyZaCislo(VysledkyBase):
managed = False managed = False
def __str__(self): def __str__(self):
# NOTE: DB HOG (ale nepouzivany)
return force_unicode(u"%s: %sb (za %s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo))) return force_unicode(u"%s: %sb (za %s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo)))
@ -531,6 +576,7 @@ class VysledkyKCislu(VysledkyBase):
body_celkem = models.IntegerField(u'body celkem do čísla', db_column='body_celkem') body_celkem = models.IntegerField(u'body celkem do čísla', db_column='body_celkem')
def __str__(self): def __str__(self):
# NOTE: DB HOG (ale nepouzivany)
return force_unicode(u"%s: %sb / %sb (do %s)" % (self.resitel.plne_jmeno(), self.body, self.body_celkem, str(self.cislo))) return force_unicode(u"%s: %sb / %sb (do %s)" % (self.resitel.plne_jmeno(), self.body, self.body_celkem, str(self.cislo)))

2
seminar/urls.py

@ -5,6 +5,8 @@ urlpatterns = patterns('',
url(r'^rocnik/(?P<pk>\d+)/$', views.RocnikView.as_view(), name='seminar_rocnik'), url(r'^rocnik/(?P<pk>\d+)/$', views.RocnikView.as_view(), name='seminar_rocnik'),
url(r'^cislo/(?P<pk>\d+)/$', views.CisloView.as_view(), name='seminar_cislo'), url(r'^cislo/(?P<pk>\d+)/$', views.CisloView.as_view(), name='seminar_cislo'),
url(r'^problem/(?P<pk>\d+)/$', views.ProblemView.as_view(), name='seminar_problem'), url(r'^problem/(?P<pk>\d+)/$', views.ProblemView.as_view(), name='seminar_problem'),
url(r'^soustredeni/(?P<pk>\d+)/$', views.SoustredeniView.as_view(), name='seminar_soustredeni'),
url(r'^zadani/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'), url(r'^zadani/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
url(r'^aesop-export/mam-rocnik-(?P<prvni_rok>\d+)\.csv$', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'), url(r'^aesop-export/mam-rocnik-(?P<prvni_rok>\d+)\.csv$', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'),

6
seminar/views.py

@ -2,7 +2,7 @@ from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.views import generic from django.views import generic
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik, Soustredeni
def AktualniZadaniView(request): def AktualniZadaniView(request):
@ -16,6 +16,10 @@ class RocnikView(generic.DetailView):
model = Rocnik model = Rocnik
template_name = 'seminar/rocnik.html' template_name = 'seminar/rocnik.html'
class SoustredeniView(generic.DetailView):
model = Soustredeni
template_name = 'seminar/soustredeni.html'
class ProblemView(generic.DetailView): class ProblemView(generic.DetailView):
model = Problem model = Problem
template_name = 'seminar/problem.html' template_name = 'seminar/problem.html'

Loading…
Cancel
Save