diff --git a/openslides/motion/forms.py b/openslides/motion/forms.py
index 9f35e4bab..028328837 100644
--- a/openslides/motion/forms.py
+++ b/openslides/motion/forms.py
@@ -19,6 +19,9 @@ from .models import Motion
class BaseMotionForm(forms.ModelForm, CssClassMixin):
+ """
+ Form to automaticly save the version data for a motion.
+ """
class Meta:
model = Motion
fields = ()
@@ -38,12 +41,20 @@ class BaseMotionForm(forms.ModelForm, CssClassMixin):
widget=forms.Textarea(), required=False, label=_("Reason"))
-class MotionCreateForm(BaseMotionForm):
- pass
+class MotionSubmitterMixin(forms.ModelForm):
+ submitter = MultiplePersonFormField(label=_("Submitter"))
-class MotionUpdateForm(BaseMotionForm):
- pass
+class MotionSupporterMixin(forms.ModelForm):
+ supporter = MultiplePersonFormField(required=False, label=_("Supporters"))
+
+
+
+
+class MotionTrivialChangesMixin(object):
+ trivial_change = forms.BooleanField(
+ required=False, label=_("Trivial change"),
+ help_text=_("Trivial changes don't create a new version."))
class ConfigForm(forms.Form, CssClassMixin):
diff --git a/openslides/motion/models.py b/openslides/motion/models.py
index 6b68bda19..19afe043e 100644
--- a/openslides/motion/models.py
+++ b/openslides/motion/models.py
@@ -31,49 +31,21 @@ from openslides.projector.models import SlideMixin
from openslides.agenda.models import Item
-RELATION = (
- (1, _('Submitter')),
- (2, _('Supporter')))
-
-
-class RelatedPersonsManager(models.Manager):
- """
- Manager for MotionRelatedPersons.
-
- Returns a custom manager with gives a specific queryset for one type of
- persons.
- """
- def __init__(self, relation, *args, **kwargs):
- super(RelatedPersonsManager, self).__init__(*args, **kwargs)
- for key, value in RELATION:
- if key == relation:
- self.relation = key
- break
- else:
- raise ValueError('Unknown relation with id %d' % relation)
-
- def get_query_set(self):
- return (super(RelatedPersonsManager, self).get_query_set()
- .filter(relation=self.relation))
-
-
-class MotionRelatedPersons(models.Model):
- """
- Saves the all persons related to a motion.
-
- relation = 1: submitter
- relation = 2: supporter
-
- The custom manager submitter and supporter return a queryset with the
- specific persons.
- """
- submitter = RelatedPersonsManager(relation=1)
- supporter = RelatedPersonsManager(relation=2)
- objects = models.Manager()
-
+# TODO: Save submitter and supporter in the same table
+class MotionSubmitter(models.Model):
person = PersonField()
- relation = models.IntegerField(default=1, choices=RELATION)
- motion = models.ForeignKey('Motion', related_name="persons")
+ motion = models.ForeignKey('Motion', related_name="submitter")
+
+ def __unicode__(self):
+ return unicode(self.person)
+
+
+class MotionSupporter(models.Model):
+ person = PersonField()
+ motion = models.ForeignKey('Motion', related_name="supporter")
+
+ def __unicode__(self):
+ return unicode(self.person)
class Motion(SlideMixin, models.Model):
@@ -198,20 +170,6 @@ class Motion(SlideMixin, models.Model):
reason = property(get_reason, set_reason)
- @property
- def submitter(self):
- """
- Return a queryset with all submitter of this motion.
- """
- return MotionRelatedPersons.submitter.filter(motion=self)
-
- @property
- def supporter(self):
- """
- Returns a queryset with all supporter of this motion.
- """
- return MotionRelatedPersons.supporter.filter(motion=self)
-
@property
def new_version(self):
"""
@@ -292,9 +250,15 @@ class MotionVersion(models.Model):
note = models.TextField(null=True, blank=True)
def __unicode__(self):
- return "%s Version %s" % (self.motion, self.get_version_number())
+ return "%s Version %s" % (self.motion, self.version_number)
- def get_version_number(self):
+ def get_absolute_url(self, link='detail'):
+ if link == 'view' or link == 'detail':
+ return reverse('motion_version_detail', args=[str(self.motion.id),
+ str(self.version_number)])
+
+ @property
+ def version_number(self):
if self.pk is None:
return 'new'
return (MotionVersion.objects.filter(motion=self.motion)
diff --git a/openslides/motion/templates/motion/motion_detail.html b/openslides/motion/templates/motion/motion_detail.html
index 9cd880936..07f048750 100644
--- a/openslides/motion/templates/motion/motion_detail.html
+++ b/openslides/motion/templates/motion/motion_detail.html
@@ -4,9 +4,21 @@
{% load i18n %}
{% load staticfiles %}
-{% block title %}{{ block.super }} – {% trans "Motion" %} "{{ version.title }}"{% endblock %}
+{% block title %}{{ block.super }} – {% trans "Motion" %} "{{ motion.title }}"{% endblock %}
{% block content %}
-
Titel: {{ object.title }}
-Text: {{ object.text }}
+Titel: {{ motion.title }}
+Text: {{ motion.text }}
+Reason: {{ motion.reason }}
+Submitter: {% for submitter in motion.submitter.all %}{{ submitter.person }} {% endfor %}
+
+
+{% for motion_version in motion.versions.all %}
+ {% if motion_version.id == motion.version.id %}
+ - {{ motion_version }}
+ {% else %}
+ - {{ motion_version }}
+ {% endif %}
+{% endfor %}
+
{% endblock %}
diff --git a/openslides/motion/templates/motion/motion_list.html b/openslides/motion/templates/motion/motion_list.html
index 32118ff73..9cb2e5506 100644
--- a/openslides/motion/templates/motion/motion_list.html
+++ b/openslides/motion/templates/motion/motion_list.html
@@ -8,9 +8,9 @@
{% block content %}
{% trans "Motions" %}
-
+
{% for motion in motion_list %}
- - {{ motion }}
+ - {{ motion }}
{% endfor %}
-
+
{% endblock %}
diff --git a/openslides/motion/views.py b/openslides/motion/views.py
index 3121c3efd..c46697f20 100644
--- a/openslides/motion/views.py
+++ b/openslides/motion/views.py
@@ -17,6 +17,7 @@ from django.db import transaction
from django.db.models import Model
from django.utils.translation import ugettext as _, ugettext_lazy
from django.views.generic.detail import SingleObjectMixin
+from django.http import Http404
from openslides.utils.pdf import stylesheet
from openslides.utils.views import (
@@ -26,8 +27,10 @@ from openslides.utils.template import Tab
from openslides.utils.utils import html_strong
from openslides.projector.api import get_active_slide
from openslides.projector.projector import Widget, SLIDE
-from .models import Motion
-from .forms import MotionCreateForm, MotionUpdateForm
+from openslides.config.models import config
+from .models import Motion, MotionSubmitter
+from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
+ MotionTrivialChangesMixin)
from django.views.generic.edit import ModelFormMixin
@@ -55,7 +58,10 @@ class MotionDetailView(DetailView):
object = super(MotionDetailView, self).get_object()
version_id = self.kwargs.get('version_id', None)
if version_id is not None:
- object.version = int(version_id) -1
+ try:
+ object.version = int(version_id) -1
+ except IndexError:
+ raise Http404
return object
motion_detail = MotionDetailView.as_view()
@@ -66,9 +72,28 @@ class MotionMixin(object):
Mixin to add save the version-data to the motion-object
"""
def manipulate_object(self, form):
+ super(MotionMixin, self).manipulate_object(form)
for attr in ['title', 'text', 'reason']:
setattr(self.object, attr, form.cleaned_data[attr])
+ def post_save(self, form):
+ super(MotionMixin, self).post_save(form)
+ # TODO: only delete and save neccessary submitters
+ self.object.submitter.all().delete()
+ MotionSubmitter.objects.bulk_create(
+ [MotionSubmitter(motion=self.object, person=person)
+ for person in form.cleaned_data['submitter']])
+
+ def get_form_class(self):
+ form_classes = [BaseMotionForm]
+ if config['motion_allow_trivial_change']:
+ form_classes.append(MotionTrivialChangesMixin)
+ if self.request.user.has_perm('motion.can_manage_motion'):
+ form_classes.append(MotionSubmitterMixin)
+ if config['motion_min_supporters'] > 0:
+ form_classes.append(MotionSupporterMixin)
+ return type('MotionForm', tuple(form_classes), {})
+
class MotionCreateView(MotionMixin, CreateView):
"""
@@ -76,7 +101,6 @@ class MotionCreateView(MotionMixin, CreateView):
"""
permission_required = 'motion.can_create_motion'
model = Motion
- form_class = MotionCreateForm
motion_create = MotionCreateView.as_view()
@@ -85,7 +109,21 @@ class MotionUpdateView(MotionMixin, UpdateView):
"""
Update a motion.
"""
+ # TODO: set permissions
model = Motion
- form_class = MotionUpdateForm
+ apply_url = ''
motion_edit = MotionUpdateView.as_view()
+
+
+def register_tab(request):
+ """
+ Register the projector tab.
+ """
+ selected = request.path.startswith('/motion/')
+ return Tab(
+ title=_('Motions'),
+ url=reverse('motion_list'),
+ permission=request.user.has_perm('motion.can_see_motion'),
+ selected=selected,
+ )
diff --git a/openslides/utils/templatetags/tags.py b/openslides/utils/templatetags/tags.py
index 96809af10..dfa8e02f2 100644
--- a/openslides/utils/templatetags/tags.py
+++ b/openslides/utils/templatetags/tags.py
@@ -35,6 +35,7 @@ def active(request, pattern):
@register.simple_tag
def model_url(object, link='view'):
+ # TODO: Rename to object_url
return object.get_absolute_url(link)
diff --git a/openslides/utils/views.py b/openslides/utils/views.py
index c13087592..412ddac88 100644
--- a/openslides/utils/views.py
+++ b/openslides/utils/views.py
@@ -113,7 +113,7 @@ class SuccessUrlMixin(object):
if 'apply' in self.request.POST:
return reverse(self.get_apply_url(), args=[self.object.id])
if self.success_url:
- url = reverse(success_url)
+ url = reverse(self.success_url)
else:
try:
url = self.object.get_absolute_url()
@@ -230,12 +230,15 @@ class ModelFormMixin(object):
self.object = form.save(commit=False)
self.manipulate_object(form)
self.object.save()
- form.save_m2m()
+ self.post_save(form)
return HttpResponseRedirect(self.get_success_url())
def manipulate_object(self, form):
pass
+ def post_save(self, form):
+ form.save_m2m()
+
class UpdateView(PermissionMixin, SuccessUrlMixin, ExtraContextMixin,
ModelFormMixin, _UpdateView):