From 2614a1cb2f89e3c9eaabcbefd40cdc409091ab52 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 11 Mar 2013 20:17:19 +0100 Subject: [PATCH 1/8] Categories for Motions --- openslides/motion/models.py | 18 ++++++++++++------ openslides/motion/urls.py | 18 +++++++++++++++++- openslides/motion/views.py | 24 +++++++++++++++++++++++- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/openslides/motion/models.py b/openslides/motion/models.py index f8de1544d..2446747c6 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -65,7 +65,9 @@ class Motion(SlideMixin, models.Model): unique=True) """A string as human readable identifier for the motion.""" - # category = models.ForeignKey('Category', null=True, blank=True) + category = models.ForeignKey('Category', null=True, blank=True) + """ForeignKey to one category of motions.""" + # TODO: proposal #master = models.ForeignKey('self', null=True, blank=True) @@ -523,12 +525,16 @@ class MotionSupporter(models.Model): return unicode(self.person) -## class Category(models.Model): - ## name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name")) - ## prefix = models.CharField(max_length=32, verbose_name=ugettext_lazy("Category prefix")) +class Category(models.Model): + name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name")) + prefix = models.CharField(max_length=32, verbose_name=ugettext_lazy("Category prefix")) - ## def __unicode__(self): - ## return self.name + def __unicode__(self): + return self.name + + def get_absolute_url(self, link='update'): + if link == 'update' or link == 'edit': + return reverse('motion_category_update', args=[str(self.id)]) ## class Comment(models.Model): diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py index a2b6b49e2..06bccb7b2 100644 --- a/openslides/motion/urls.py +++ b/openslides/motion/urls.py @@ -19,8 +19,9 @@ urlpatterns = patterns('openslides.motion.views', name='motion_list', ), - url(r'^create/$', + url(r'^new/$', 'motion_create', + # TODO: rename to motion_create name='motion_new', ), @@ -103,4 +104,19 @@ urlpatterns = patterns('openslides.motion.views', 'motion_detail_pdf', name='motion_detail_pdf', ), + + url(r'^category/$', + 'category_list', + name='motion_category_list', + ), + + url(r'^category/new/$', + 'category_create', + name='motion_category_create', + ), + + url(r'^category/(?P\d+)/edit/$', + 'category_update', + name='motion_category_update', + ), ) diff --git a/openslides/motion/views.py b/openslides/motion/views.py index da7d27dd4..1e1541d7c 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -32,7 +32,8 @@ from openslides.projector.projector import Widget, SLIDE from openslides.config.models import config from openslides.agenda.models import Item -from .models import Motion, MotionSubmitter, MotionSupporter, MotionPoll, MotionVersion, State, WorkflowError +from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll, + MotionVersion, State, WorkflowError, Category) from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, MotionDisableVersioningMixin, ConfigForm) from .pdf import motions_to_pdf, motion_to_pdf @@ -473,6 +474,27 @@ motion_list_pdf = MotionPDFView.as_view(print_all_motions=True) motion_detail_pdf = MotionPDFView.as_view(print_all_motions=False) +class CategoryListView(ListView): + permission_required = 'motion.can_manage_motion' + model = Category + +category_list = CategoryListView.as_view() + + +class CategoryCreateView(CreateView): + permission_required = 'motion.can_manage_motion' + model = Category + +category_create = CategoryCreateView.as_view() + + +class CategoryUpdateView(UpdateView): + permission_required = 'motion.can_manage_motion' + model = Category + +category_update = CategoryUpdateView.as_view() + + class Config(FormView): """The View for the config tab.""" permission_required = 'config.can_manage_config' From bc7be271315b76585691fc0758d6c697bff8868c Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 11 Mar 2013 20:41:02 +0100 Subject: [PATCH 2/8] Add CategoryFormField to the MotionForm --- openslides/motion/forms.py | 8 +++++++- openslides/motion/views.py | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/openslides/motion/forms.py b/openslides/motion/forms.py index 139d4205e..1ddac7b97 100644 --- a/openslides/motion/forms.py +++ b/openslides/motion/forms.py @@ -15,7 +15,7 @@ from django.utils.translation import ugettext as _ from openslides.utils.forms import CssClassMixin from openslides.utils.person import PersonFormField, MultiplePersonFormField -from .models import Motion, Workflow +from .models import Motion, Workflow, Category class BaseMotionForm(forms.ModelForm, CssClassMixin): @@ -90,6 +90,12 @@ class MotionDisableVersioningMixin(forms.ModelForm): last_version will be used.""" +class MotionCategoryMixin(forms.ModelForm): + """Mixin to let the user choose the category for the motion.""" + + category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False) + + class ConfigForm(CssClassMixin, forms.Form): """Form for the configuration tab of OpenSlides.""" motion_min_supporters = forms.IntegerField( diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 1e1541d7c..6e6c979bd 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -35,7 +35,7 @@ from openslides.agenda.models import Item from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll, MotionVersion, State, WorkflowError, Category) from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, - MotionDisableVersioningMixin, ConfigForm) + MotionDisableVersioningMixin, ConfigForm, MotionCategoryMixin) from .pdf import motions_to_pdf, motion_to_pdf @@ -124,6 +124,7 @@ class MotionMixin(object): form_classes = [BaseMotionForm] if self.request.user.has_perm('motion.can_manage_motion'): form_classes.append(MotionSubmitterMixin) + form_classes.append(MotionCategoryMixin) if config['motion_min_supporters'] > 0: form_classes.append(MotionSupporterMixin) if self.object: From f411040c3aa05c3662372d867b79ea97f259bfe2 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 11 Mar 2013 20:43:23 +0100 Subject: [PATCH 3/8] Append missing files --- .../templates/motion/category_form.html | 33 +++++++++++++++++++ .../templates/motion/category_list.html | 16 +++++++++ 2 files changed, 49 insertions(+) create mode 100644 openslides/motion/templates/motion/category_form.html create mode 100644 openslides/motion/templates/motion/category_list.html diff --git a/openslides/motion/templates/motion/category_form.html b/openslides/motion/templates/motion/category_form.html new file mode 100644 index 000000000..5114c9a0a --- /dev/null +++ b/openslides/motion/templates/motion/category_form.html @@ -0,0 +1,33 @@ +{% extends "base.html" %} + +{% load tags %} +{% load i18n %} + +{% block title %} + {{ block.super }} – + {% if motion %} + {% trans "Edit category" %} + {% else %} + {% trans "New category" %} + {% endif %} +{% endblock %} + +{% block content %} +

+ {% if motion %} + {% trans "Edit category" %} + {% else %} + {% trans "New category" %} + {% endif %} +

+
{% csrf_token %} + {% include "form.html" %} +

+ {% include "formbuttons_saveapply.html" %} + + {% trans 'Cancel' %} + +

+ * {% trans "required" %} +
+{% endblock %} diff --git a/openslides/motion/templates/motion/category_list.html b/openslides/motion/templates/motion/category_list.html new file mode 100644 index 000000000..175cf2854 --- /dev/null +++ b/openslides/motion/templates/motion/category_list.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% load tags %} +{% load i18n %} + +{% block title %}{{ block.super }} – {% trans "Motions" %}{% endblock %} + +{% block content %} +

{% trans "Categories" %}

+ {% for category in category_list %} +

{{ category }}

+ {% empty %} +

No Categories

+ {% endfor %} + +{% endblock %} From 31ba70efd10fa937cbb00c18d441f3d48c07a5df Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 11 Mar 2013 21:38:07 +0100 Subject: [PATCH 4/8] Category Delete View --- openslides/motion/models.py | 2 ++ openslides/motion/urls.py | 5 +++++ openslides/motion/views.py | 8 ++++++++ openslides/utils/views.py | 3 ++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/openslides/motion/models.py b/openslides/motion/models.py index 2446747c6..023326f2a 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -535,6 +535,8 @@ class Category(models.Model): def get_absolute_url(self, link='update'): if link == 'update' or link == 'edit': return reverse('motion_category_update', args=[str(self.id)]) + if link == 'delete': + return reverse('motion_category_delete', args=[str(self.id)]) ## class Comment(models.Model): diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py index 06bccb7b2..1fd507ad1 100644 --- a/openslides/motion/urls.py +++ b/openslides/motion/urls.py @@ -119,4 +119,9 @@ urlpatterns = patterns('openslides.motion.views', 'category_update', name='motion_category_update', ), + + url(r'^category/(?P\d+)/del/$', + 'category_delete', + name='motion_category_delete', + ), ) diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 6e6c979bd..d7a760855 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -496,6 +496,14 @@ class CategoryUpdateView(UpdateView): category_update = CategoryUpdateView.as_view() +class CategoryDeleteView(DeleteView): + permission_required = 'motion.can_manage_motion' + model = Category + success_url_name = 'motion_category_list' + +category_delete = CategoryDeleteView.as_view() + + class Config(FormView): """The View for the config tab.""" permission_required = 'config.can_manage_config' diff --git a/openslides/utils/views.py b/openslides/utils/views.py index 928e56767..00bc6b9fa 100644 --- a/openslides/utils/views.py +++ b/openslides/utils/views.py @@ -304,7 +304,8 @@ class DeleteView(SingleObjectMixin, QuestionMixin, RedirectView): return super(DeleteView, self).get(request, *args, **kwargs) def get_redirect_url(self, **kwargs): - if self.request.method == 'GET' and self.question_url_name is None: + if self.question_url_name is None and (self.request.method == 'GET' or + self.get_answer() == 'no'): return self.object.get_absolute_url() else: return super(DeleteView, self).get_redirect_url(**kwargs) From 9cd69f59e0e08cc7bc2bcf8ad3956d94d8fd08e8 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 12 Mar 2013 22:03:56 +0100 Subject: [PATCH 5/8] Motion Identifier --- openslides/motion/__init__.py | 1 + openslides/motion/models.py | 46 ++++++++++++++++++- .../templates/motion/motion_detail.html | 4 +- openslides/motion/urls.py | 5 ++ openslides/motion/views.py | 26 ++++++++++- 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/openslides/motion/__init__.py b/openslides/motion/__init__.py index ea23517a7..e296be3ce 100644 --- a/openslides/motion/__init__.py +++ b/openslides/motion/__init__.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # -*- coding: utf-8 -*- """ openslides.motion diff --git a/openslides/motion/models.py b/openslides/motion/models.py index 023326f2a..0e61d9b09 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -16,7 +16,7 @@ from datetime import datetime from django.core.urlresolvers import reverse -from django.db import models +from django.db import models, IntegrityError from django.db.models import Max from django.dispatch import receiver from django.utils import formats @@ -65,6 +65,12 @@ class Motion(SlideMixin, models.Model): unique=True) """A string as human readable identifier for the motion.""" + identifier_number = models.IntegerField(null=True) + """Counts the number of the motion in one category. + + Needed to find the next free motion-identifier. + """ + category = models.ForeignKey('Category', null=True, blank=True) """ForeignKey to one category of motions.""" @@ -170,6 +176,29 @@ class Motion(SlideMixin, models.Model): if link == 'delete': return reverse('motion_delete', args=[str(self.id)]) + def set_identifier(self): + # TODO: into the config-tab + config['motion_identifier'] = ('manuell', 'category', 'all')[0] + + number = Motion.objects.all().aggregate(Max('identifier_number'))['identifier_number__max'] or 0 + if self.category is not None: + prefix = self.category.prefix + ' ' + else: + prefix = '' + + while True: + number += 1 + self.identifier = '%s%d' % (prefix, number) + try: + self.save() + except IntegrityError: + continue + else: + self.number = number + self.save() + break + + def get_title(self): """Get the title of the motion. @@ -346,6 +375,18 @@ class Motion(SlideMixin, models.Model): else: raise WorkflowError('You can not create a poll in state %s.' % self.state.name) + def set_state(self, state): + """Set the state of the motion. + + State can be the id of a state object or a state object. + """ + if type(state) is int: + state = State.objects.get(pk=state) + + if state.set_identifier: + self.set_identifier() + self.state = state + def reset_state(self): """Set the state to the default state. If the motion is new, it chooses the default workflow from config.""" if self.state: @@ -692,6 +733,9 @@ class State(models.Model): dont_set_new_version_active = models.BooleanField(default=False) """If true, new versions are not automaticly set active.""" + set_identifier = models.BooleanField(default=False) + """If true, the motion get a identifier if the state change to this one.""" + def __unicode__(self): """Returns the name of the state.""" return self.name diff --git a/openslides/motion/templates/motion/motion_detail.html b/openslides/motion/templates/motion/motion_detail.html index a9de961b6..c9a8b63aa 100644 --- a/openslides/motion/templates/motion/motion_detail.html +++ b/openslides/motion/templates/motion/motion_detail.html @@ -11,8 +11,8 @@ {{ motion.title }}
- {% if motion.number != None %} - {% trans "Motion" %} {{ motion.number }}, + {% if motion.identifier != None %} + {% trans "Motion" %} {{ motion.identifier }}, {% else %} [{% trans "no number" %}], {% endif %} diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py index 1fd507ad1..577073c38 100644 --- a/openslides/motion/urls.py +++ b/openslides/motion/urls.py @@ -40,6 +40,11 @@ urlpatterns = patterns('openslides.motion.views', name='motion_delete', ), + url(r'^(?P\d+)/set_identifier', + 'set_identifier', + name='motion_set_identifier', + ), + url(r'^(?P\d+)/version/(?P\d+)/$', 'motion_detail', name='motion_version_detail', diff --git a/openslides/motion/views.py b/openslides/motion/views.py index d7a760855..6d4d40cc8 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -230,6 +230,30 @@ class VersionRejectView(GetVersionMixin, SingleObjectMixin, QuestionMixin, Redir version_reject = VersionRejectView.as_view() +class SetIdentifierView(SingleObjectMixin, RedirectView): + """Set the identifier of the motion. + + See motion.set_identifier for more informations + """ + permission_required = 'motion.can_manage_motion' + model = Motion + url_name = 'motion_detail' + + def get(self, request, *args, **kwargs): + """Set self.object to a motion.""" + self.object = self.get_object() + return super(SetIdentifierView, self).get(request, *args, **kwargs) + + def pre_redirect(self, request, *args, **kwargs): + """Set the identifier.""" + self.object.set_identifier() + + def get_url_name_args(self): + return [self.object.id] + +set_identifier = SetIdentifierView.as_view() + + class SupportView(SingleObjectMixin, QuestionMixin, RedirectView): """View to support or unsupport a motion. @@ -401,7 +425,7 @@ class MotionSetStateView(SingleObjectMixin, RedirectView): if self.reset: self.object.reset_state() else: - self.object.state = State.objects.get(pk=kwargs['state']) + self.object.set_state(int(kwargs['state'])) except WorkflowError, e: # TODO: Is a WorkflowError still possible here? messages.error(request, e) else: From 304887e8f3be77db92e6a9fb72c11e8c6f1938ba Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 12 Mar 2013 22:13:17 +0100 Subject: [PATCH 6/8] Changed comlex workflow automaticly set the identifier --- openslides/motion/models.py | 9 ++++++--- openslides/motion/signals.py | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/openslides/motion/models.py b/openslides/motion/models.py index d975db7c8..73d18d63c 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -383,7 +383,7 @@ class Motion(SlideMixin, models.Model): if type(state) is int: state = State.objects.get(pk=state) - if state.set_identifier: + if not state.dont_set_identifier: self.set_identifier() self.state = state @@ -734,8 +734,11 @@ class State(models.Model): dont_set_new_version_active = models.BooleanField(default=False) """If true, new versions are not automaticly set active.""" - set_identifier = models.BooleanField(default=False) - """If true, the motion get a identifier if the state change to this one.""" + dont_set_identifier = models.BooleanField(default=False) + """Decides if the motion gets an identifier. + + If true, the motion does not get an identifier if the state change to + this one, else it does.""" def __unicode__(self): """Returns the name of the state.""" diff --git a/openslides/motion/signals.py b/openslides/motion/signals.py index 526a56783..ff662ddf1 100644 --- a/openslides/motion/signals.py +++ b/openslides/motion/signals.py @@ -61,7 +61,8 @@ def create_builtin_workflows(sender, **kwargs): state_2_1 = State.objects.create(name=ugettext_noop('published'), workflow=workflow_2, allow_support=True, - allow_submitter_edit=True) + allow_submitter_edit=True, + dont_set_identifier=True) state_2_2 = State.objects.create(name=ugettext_noop('permitted'), workflow=workflow_2, action_word=ugettext_noop('Permit'), From b2c888b151693a040c80aeb1df9240453139e6ba Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 12 Mar 2013 23:35:08 +0100 Subject: [PATCH 7/8] set identifier --- openslides/motion/forms.py | 6 +++++ openslides/motion/models.py | 22 +++++++++++++------ .../templates/motion/motion_detail.html | 2 +- openslides/motion/views.py | 15 ++++++++++++- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/openslides/motion/forms.py b/openslides/motion/forms.py index 1ddac7b97..7b81d6524 100644 --- a/openslides/motion/forms.py +++ b/openslides/motion/forms.py @@ -96,6 +96,12 @@ class MotionCategoryMixin(forms.ModelForm): category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False) +class MotionIdentifierMixin(forms.ModelForm): + """Mixin to let the user choose the identifier for the motion.""" + + identifier = forms.CharField(required=False) + + class ConfigForm(CssClassMixin, forms.Form): """Form for the configuration tab of OpenSlides.""" motion_min_supporters = forms.IntegerField( diff --git a/openslides/motion/models.py b/openslides/motion/models.py index 73d18d63c..a1b13b950 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -37,6 +37,10 @@ from openslides.agenda.models import Item from .exceptions import MotionError, WorkflowError +# TODO: into the config-tab +config['motion_identifier'] = ('manually', 'per_category', 'serially_numbered')[0] + + class Motion(SlideMixin, models.Model): """The Motion Class. @@ -177,14 +181,19 @@ class Motion(SlideMixin, models.Model): return reverse('motion_delete', args=[str(self.id)]) def set_identifier(self): - # TODO: into the config-tab - config['motion_identifier'] = ('manuell', 'category', 'all')[0] - - number = Motion.objects.all().aggregate(Max('identifier_number'))['identifier_number__max'] or 0 - if self.category is not None: - prefix = self.category.prefix + ' ' + if config['motion_identifier'] == 'manually': + # Do not set an identifier. + return + elif config['motion_identifier'] == 'per_category': + motions = Motion.objects.filter(category=self.category) else: + motions = Motion.objects.all() + + number = motions.aggregate(Max('identifier_number'))['identifier_number__max'] or 0 + if self.category is None: prefix = '' + else: + prefix = self.category.prefix + ' ' while True: number += 1 @@ -198,7 +207,6 @@ class Motion(SlideMixin, models.Model): self.save() break - def get_title(self): """Get the title of the motion. diff --git a/openslides/motion/templates/motion/motion_detail.html b/openslides/motion/templates/motion/motion_detail.html index c9a8b63aa..12d26fba3 100644 --- a/openslides/motion/templates/motion/motion_detail.html +++ b/openslides/motion/templates/motion/motion_detail.html @@ -8,7 +8,7 @@ {% block content %}

- {{ motion.title }} + {{ motion.title }} {{ motion.category }}
{% if motion.identifier != None %} diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 6d4d40cc8..8af3fef2c 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -35,7 +35,8 @@ from openslides.agenda.models import Item from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll, MotionVersion, State, WorkflowError, Category) from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, - MotionDisableVersioningMixin, ConfigForm, MotionCategoryMixin) + MotionDisableVersioningMixin, ConfigForm, MotionCategoryMixin, + MotionIdentifierMixin) from .pdf import motions_to_pdf, motion_to_pdf @@ -98,6 +99,16 @@ class MotionMixin(object): except KeyError: pass + try: + self.object.category = form.cleaned_data['category'] + except KeyError: + pass + + try: + self.object.identifier = form.cleaned_data['identifier'] + except KeyError: + pass + def post_save(self, form): """Save the submitter an the supporter so the motion.""" super(MotionMixin, self).post_save(form) @@ -127,6 +138,8 @@ class MotionMixin(object): form_classes.append(MotionCategoryMixin) if config['motion_min_supporters'] > 0: form_classes.append(MotionSupporterMixin) + if config['motion_identifier'] == 'manually': + form_classes.append(MotionIdentifierMixin) if self.object: if config['motion_allow_disable_versioning'] and self.object.state.versioning: form_classes.append(MotionDisableVersioningMixin) From 71b9bd0a08a208e168e2d707fd4cb7c258d0d717 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 12 Mar 2013 23:54:37 +0100 Subject: [PATCH 8/8] dont set identifier prefix, if it is empty --- openslides/motion/models.py | 12 +++++++++--- openslides/motion/urls.py | 2 +- openslides/motion/views.py | 10 +++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/openslides/motion/models.py b/openslides/motion/models.py index a1b13b950..e4cf800b4 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -38,7 +38,7 @@ from .exceptions import MotionError, WorkflowError # TODO: into the config-tab -config['motion_identifier'] = ('manually', 'per_category', 'serially_numbered')[0] +config['motion_identifier'] = ('manually', 'per_category', 'serially_numbered')[2] class Motion(SlideMixin, models.Model): @@ -190,7 +190,7 @@ class Motion(SlideMixin, models.Model): motions = Motion.objects.all() number = motions.aggregate(Max('identifier_number'))['identifier_number__max'] or 0 - if self.category is None: + if self.category is None or not self.category.prefix: prefix = '' else: prefix = self.category.prefix + ' ' @@ -577,7 +577,13 @@ class MotionSupporter(models.Model): class Category(models.Model): name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name")) - prefix = models.CharField(max_length=32, verbose_name=ugettext_lazy("Category prefix")) + """Name of the category.""" + + prefix = models.CharField(blank=True, max_length=32, verbose_name=ugettext_lazy("Category prefix")) + """Prefix of the category. + + Used to build the identifier of a motion. + """ def __unicode__(self): return self.name diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py index 577073c38..85de6fbfc 100644 --- a/openslides/motion/urls.py +++ b/openslides/motion/urls.py @@ -40,7 +40,7 @@ urlpatterns = patterns('openslides.motion.views', name='motion_delete', ), - url(r'^(?P\d+)/set_identifier', + url(r'^(?P\d+)/set_identifier/', 'set_identifier', name='motion_set_identifier', ), diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 8af3fef2c..d397f8b78 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -131,15 +131,19 @@ class MotionMixin(object): will be mixed in dependence of some config values. See motion.forms for more information on the mixins. """ + form_classes = [] + + if (self.request.user.has_perm('motion.can_manage_motion') and + config['motion_identifier'] == 'manually'): + form_classes.append(MotionIdentifierMixin) + + form_classes.append(BaseMotionForm) - form_classes = [BaseMotionForm] if self.request.user.has_perm('motion.can_manage_motion'): form_classes.append(MotionSubmitterMixin) form_classes.append(MotionCategoryMixin) if config['motion_min_supporters'] > 0: form_classes.append(MotionSupporterMixin) - if config['motion_identifier'] == 'manually': - form_classes.append(MotionIdentifierMixin) if self.object: if config['motion_allow_disable_versioning'] and self.object.state.versioning: form_classes.append(MotionDisableVersioningMixin)