diff --git a/seminar/admin.py b/seminar/admin.py index b86d933a..8fd5aa61 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -11,7 +11,7 @@ from django.db import models from django.contrib.auth.models import User -from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Novinky, Organizator +from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Novinky, Organizator import autocomplete_light @@ -163,6 +163,19 @@ class Soustredeni_UcastniciInline(admin.TabularInline): qs = super(Soustredeni_UcastniciInline, self).get_queryset(request) return qs.select_related('resitel', 'soustredeni') +class Soustredeni_OrganizatoriInline(admin.TabularInline): + form = autocomplete_light.modelform_factory(Soustredeni_Organizatori, autocomplete_fields=['organizator'], fields=['organizator'],) + model = Soustredeni_Organizatori + fields = ['organizator', 'poznamka', ] + extra = 0 + formfield_overrides = { + models.TextField: {'widget': forms.TextInput}, + } + + def get_queryset(self, request): + qs = super(Soustredeni_OrganizatoriInline, self).get_queryset(request) + return qs.select_related('organizator', 'soustredeni') + ### Resitel class ResitelAdmin(VersionAdmin): @@ -362,7 +375,7 @@ class SoustredeniAdmin(VersionAdmin): (u'Data', {'fields': ['datum_zacatku', 'datum_konce']}), ] list_display = ['rocnik', 'misto', 'datum_zacatku', 'typ', 'exportovat', 'verejne'] - inlines = [Soustredeni_UcastniciInline] + inlines = [Soustredeni_UcastniciInline, Soustredeni_OrganizatoriInline] list_filter = ['typ', 'rocnik'] view_on_site = Soustredeni.verejne_url actions = [ diff --git a/seminar/autocomplete_light_registry.py b/seminar/autocomplete_light_registry.py index c7762054..76b9f6ba 100644 --- a/seminar/autocomplete_light_registry.py +++ b/seminar/autocomplete_light_registry.py @@ -2,7 +2,7 @@ import autocomplete_light -from models import Skola, Resitel, Problem +from models import Skola, Resitel, Problem, Organizator from taggit.models import Tag @@ -64,6 +64,38 @@ class ResitelAutocomplete(autocomplete_light.AutocompleteModelBase): autocomplete_light.register(ResitelAutocomplete) +class OrganizatorAutocomplete(autocomplete_light.AutocompleteModelBase): + + model = Organizator + + search_fields=['user__first_name', 'user__last_name', 'prezdivka'] + + split_words = False + + limit_choices = 15 + + def choice_label(self, organizator): + return u"%s '%s' %s" % (organizator.user.first_name, + organizator.prezdivka, + organizator.user.last_name) + + attrs={ + # This will set the input placeholder attribute: + 'placeholder': u'Organizátor', + # This will set the yourlabs.Autocomplete.minimumCharacters + # options, the naming conversion is handled by jQuery + 'data-autocomplete-minimum-characters': 1, + } + + widget_attrs={ + 'data-widget-maximum-values': 15, + # Enable modern-style widget ! + 'class': 'modern-style', + } + +autocomplete_light.register(OrganizatorAutocomplete) + + class ProblemAutocomplete(autocomplete_light.AutocompleteModelBase): diff --git a/seminar/migrations/0036_add_org_to_soustredeni.py b/seminar/migrations/0036_add_org_to_soustredeni.py new file mode 100644 index 00000000..cd6a2aed --- /dev/null +++ b/seminar/migrations/0036_add_org_to_soustredeni.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', '0035_django_imagekit'), + ] + + operations = [ + migrations.CreateModel( + name='Soustredeni_Organizatori', + fields=[ + ('id', models.AutoField(serialize=False, primary_key=True)), + ('poznamka', models.TextField(help_text='Neve\u0159ejn\xe1 pozn\xe1mka k \xfa\u010dasti organiz\xe1tora (plain text)', verbose_name='neve\u0159ejn\xe1 pozn\xe1mka', blank=True)), + ('organizator', models.ForeignKey(verbose_name='organiz\xe1tor', to='seminar.Organizator')), + ('soustredeni', models.ForeignKey(verbose_name='soust\u0159ed\u011bn\xed', to='seminar.Soustredeni')), + ], + options={ + 'ordering': ['soustredeni', 'organizator'], + 'db_table': 'seminar_soustredeni_organizatori', + 'verbose_name': '\xda\u010dast organiz\xe1tor\u016f na soust\u0159ed\u011bn\xed', + 'verbose_name_plural': '\xda\u010dasti organiz\xe1tor\u016f na soust\u0159ed\u011bn\xed', + }, + bases=(models.Model,), + ), + migrations.AddField( + model_name='soustredeni', + name='organizatori', + field=models.ManyToManyField(help_text='Seznam organiz\xe1tor\u016f soust\u0159ed\u011bn\xed', to='seminar.Organizator', verbose_name='Organiz\xe1to\u0159i soust\u0159ed\u011bn\xed', through='seminar.Soustredeni_Organizatori'), + preserve_default=True, + ), + ] diff --git a/seminar/models.py b/seminar/models.py index fbb2a9d5..6674239f 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -579,6 +579,46 @@ class PrilohaReseni(SeminarModelBase): return force_unicode(self.soubor) +@reversion.register(ignore_duplicate_revisions=True) +@python_2_unicode_compatible +class Organizator(models.Model): + user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name='Osoba', + help_text = 'Vyber účet spřažený s organizátorem.') + prezdivka = models.CharField('Přezdívka', max_length = 32, + null = True, blank = True) + organizuje_od_roku = models.IntegerField('Organizuje od roku', + null = True, blank = True) + organizuje_do_roku = models.IntegerField('Organizuje do roku', + null = True, blank = True) + studuje = models.CharField('Studium aj.', max_length = 256, + null = True, blank = True, + help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', " + "'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo " + "'Přednáší na MFF'") + strucny_popis_organizatora = models.TextField('Stručný popis organizátora', + null = True, blank = True) + foto = ProcessedImageField(verbose_name='Fotografie organizátora', + upload_to='image_organizatori/velke/%Y/', null = True, blank = True, + help_text = 'Vlož fotografii organizátora o libovolné velikosti', + processors=[ + Transpose(Transpose.AUTO), + ResizeToFit(500, 500, upscale=False) + ], + options={'quality': 95}) + foto_male = ImageSpecField(source='foto', + processors=[ + ResizeToFit(200, 200, upscale=False) + ], + options={'quality': 95}) + + def __str__(self): + return str(self.user) + + class Meta: + verbose_name = 'Organizátor' + verbose_name_plural = 'Organizátoři' + + @reversion.register(ignore_duplicate_revisions=True) @python_2_unicode_compatible class Soustredeni(SeminarModelBase): @@ -608,6 +648,11 @@ class Soustredeni(SeminarModelBase): ucastnici = models.ManyToManyField(Resitel, verbose_name=u'účastníci soustředění', help_text=u'Seznam účastníků soustředění', through='Soustredeni_Ucastnici') + organizatori = models.ManyToManyField(Organizator, + verbose_name=u'Organizátoři soustředění', + help_text=u'Seznam organizátorů soustředění', + through='Soustredeni_Organizatori') + text = models.TextField(u'text k soustředění (HTML)', blank=True, default='') TYP_JARNI = 'jarni' @@ -659,6 +704,30 @@ class Soustredeni_Ucastnici(models.Model): return force_unicode(u'%s na %s' % (self.resitel, self.soustredeni, )) # NOTE: Poteciální DB HOG bez select_related +@reversion.register(ignore_duplicate_revisions=True) +@python_2_unicode_compatible +class Soustredeni_Organizatori(models.Model): + + class Meta: + db_table = 'seminar_soustredeni_organizatori' + verbose_name = u'Účast organizátorů na soustředění' + verbose_name_plural = u'Účasti organizátorů na soustředění' + ordering = ['soustredeni', 'organizator'] + + # Interní ID + id = models.AutoField(primary_key = True) + + organizator = models.ForeignKey(Organizator, verbose_name=u'organizátor') + + 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 organizátora (plain text)') + + def __str__(self): + return force_unicode(u'%s na %s' % (self.organizator, self.soustredeni, )) + # NOTE: Poteciální DB HOG bez select_related + @python_2_unicode_compatible class VysledkyBase(SeminarModelBase): @@ -778,41 +847,3 @@ class Novinky(models.Model): verbose_name_plural = 'Novinky' -@reversion.register(ignore_duplicate_revisions=True) -@python_2_unicode_compatible -class Organizator(models.Model): - user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name='Osoba', - help_text = 'Vyber účet spřažený s organizátorem.') - prezdivka = models.CharField('Přezdívka', max_length = 32, - null = True, blank = True) - organizuje_od_roku = models.IntegerField('Organizuje od roku', - null = True, blank = True) - organizuje_do_roku = models.IntegerField('Organizuje do roku', - null = True, blank = True) - studuje = models.CharField('Studium aj.', max_length = 256, - null = True, blank = True, - help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', " - "'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo " - "'Přednáší na MFF'") - strucny_popis_organizatora = models.TextField('Stručný popis organizátora', - null = True, blank = True) - foto = ProcessedImageField(verbose_name='Fotografie organizátora', - upload_to='image_organizatori/velke/%Y/', null = True, blank = True, - help_text = 'Vlož fotografii organizátora o libovolné velikosti', - processors=[ - Transpose(Transpose.AUTO), - ResizeToFit(500, 500, upscale=False) - ], - options={'quality': 95}) - foto_male = ImageSpecField(source='foto', - processors=[ - ResizeToFit(200, 200, upscale=False) - ], - options={'quality': 95}) - - def __str__(self): - return str(self.user) - - class Meta: - verbose_name = 'Organizátor' - verbose_name_plural = 'Organizátoři'