diff --git a/proposals/admin.py b/proposals/admin.py index a6eb6c6..da03187 100644 --- a/proposals/admin.py +++ b/proposals/admin.py @@ -8,7 +8,7 @@ class TalkAdmin(admin.ModelAdmin): # (it is easy to obtain incoherent data due to site framework) def has_add_permission(self, request): return False - # Filter for 'on site' topics and event + # Filter for 'on site' topics, tracks and events def get_form(self, request, obj=None, **kwargs): form = super(TalkAdmin, self).get_form(request, obj, **kwargs) # in fact, obj should never be none as 'add' button is disabled @@ -18,8 +18,17 @@ class TalkAdmin(admin.ModelAdmin): form.base_fields['event'].queryset = Event.objects.filter(site=obj.site) return form + +class TopicAdmin(admin.ModelAdmin): + # Filter for 'on site' tracks + def get_form(self, request, obj=None, **kwargs): + form = super().get_form(request, obj, **kwargs) + if obj: + form.base_fields['track'].queryset = Track.objects.filter(site=obj.site) + return form + admin.site.register(Conference) -admin.site.register(Topic) +admin.site.register(Topic, TopicAdmin) admin.site.register(Track) admin.site.register(Talk, TalkAdmin) admin.site.register(Event) diff --git a/proposals/forms.py b/proposals/forms.py index dc49a6a..e905cc9 100644 --- a/proposals/forms.py +++ b/proposals/forms.py @@ -102,24 +102,22 @@ class SpeakerFilterForm(forms.Form): self.fields['topic'].choices = topics.values_list('slug', 'name') -class TopicCreateForm(forms.ModelForm): +class TopicForm(forms.ModelForm): def __init__(self, *args, **kwargs): - self.site_id = kwargs.pop('site_id') - super(TopicCreateForm, self).__init__(*args, **kwargs) + self.site = kwargs.pop('site') + super().__init__(*args, **kwargs) + self.fields['track'].queryset = Track.objects.filter(site=self.site) class Meta: model = Topic - fields = ['name', 'description', 'reviewers'] + fields = ['name', 'description', 'reviewers', 'track'] widgets = {'reviewers': Select2TagWidget()} def clean_name(self): name = self.cleaned_data['name'] - if name != self.instance.name and Topic.objects.filter(site__id=self.site_id, name=name).exists(): + if self.instance and name != self.instance.name and Topic.objects.filter(site=self.site, name=name).exists(): raise self.instance.unique_error_message(self._meta.model, ['name']) return name -TopicUpdateForm = modelform_factory(Topic, fields=['reviewers'], - widgets={'reviewers': Select2TagWidget()}) - ConferenceForm = modelform_factory(Conference, fields=['home']) diff --git a/proposals/migrations/0012_topic_track.py b/proposals/migrations/0012_topic_track.py new file mode 100644 index 0000000..431ff69 --- /dev/null +++ b/proposals/migrations/0012_topic_track.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-09-22 09:46 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0011_auto_20160921_2236'), + ] + + operations = [ + migrations.AddField( + model_name='topic', + name='track', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='proposals.Track', verbose_name='Destination track'), + ), + ] diff --git a/proposals/models.py b/proposals/models.py index 830b3c1..d7cb8ec 100644 --- a/proposals/models.py +++ b/proposals/models.py @@ -25,26 +25,6 @@ class Conference(models.Model): return str(self.site) -class Topic(PonyConfModel): - - site = models.ForeignKey(Site, on_delete=models.CASCADE) - - name = models.CharField(max_length=128, verbose_name=_('Name')) - slug = AutoSlugField(populate_from='name', unique=True) - description = models.TextField(blank=True, verbose_name=_('Description')) - - reviewers = models.ManyToManyField(User, blank=True, verbose_name=_('Reviewers')) - - class Meta: - unique_together = ('site', 'name') - - def __str__(self): - return self.name - - def get_absolute_url(self): - return reverse('list-talks') + '?topic=%s' % self.slug - - class Track(PonyConfModel): site = models.ForeignKey(Site, on_delete=models.CASCADE) @@ -60,6 +40,27 @@ class Track(PonyConfModel): return self.name +class Topic(PonyConfModel): + + site = models.ForeignKey(Site, on_delete=models.CASCADE) + + name = models.CharField(max_length=128, verbose_name=_('Name')) + slug = AutoSlugField(populate_from='name', unique=True) + description = models.TextField(blank=True, verbose_name=_('Description')) + track = models.ForeignKey(Track, blank=True, null=True, verbose_name=_('Destination track')) + + reviewers = models.ManyToManyField(User, blank=True, verbose_name=_('Reviewers')) + + class Meta: + unique_together = ('site', 'name') + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse('list-talks') + '?topic=%s' % self.slug + + class Event(models.Model): site = models.ForeignKey(Site, on_delete=models.CASCADE) diff --git a/proposals/templates/proposals/talk_detail.html b/proposals/templates/proposals/talk_detail.html index b40db2c..a0b58c7 100644 --- a/proposals/templates/proposals/talk_detail.html +++ b/proposals/templates/proposals/talk_detail.html @@ -48,7 +48,18 @@
{% if talk.track %}{{ talk.track }}{% else %}{% trans "No assigned yet." %}{% endif %}
+{% if talk.track %} +{{ talk.track }}
+{% else %} +{% trans "No assigned yet." %}
+{% for topic in talk.topics.distinct %} + {% if forloop.first %}{% endif %} + {% if topic.track %} + {% trans "Assign to" %} {{ topic.track }} + {% endif %} + {% if forloop.last %}
{% endif %} +{% endfor %} +{% endif %} {% endif %} diff --git a/proposals/urls.py b/proposals/urls.py index a5361ad..13851d2 100644 --- a/proposals/urls.py +++ b/proposals/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ url(r'^talk/details/(?P