Added AbsoluteUrlMixin and used it in any model.

cleaned up get_absolute_url() in some models
This commit is contained in:
Oskar Hahn 2014-01-11 17:57:24 +01:00
parent 3fe9169786
commit c82ee4ce1f
11 changed files with 161 additions and 90 deletions

View File

@ -17,10 +17,11 @@ from openslides.projector.api import (get_active_slide, reset_countdown,
update_projector, update_projector_overlay) update_projector, update_projector_overlay)
from openslides.projector.models import SlideMixin from openslides.projector.models import SlideMixin
from openslides.utils.exceptions import OpenSlidesError from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person.models import PersonField from openslides.utils.person.models import PersonField
class Item(SlideMixin, MPTTModel): class Item(SlideMixin, AbsoluteUrlMixin, MPTTModel):
""" """
An Agenda Item An Agenda Item
@ -296,7 +297,7 @@ class SpeakerManager(models.Manager):
return self.create(item=item, person=person, weight=weight + 1) return self.create(item=item, person=person, weight=weight + 1)
class Speaker(models.Model): class Speaker(AbsoluteUrlMixin, models.Model):
""" """
Model for the Speaker list. Model for the Speaker list.
""" """
@ -346,10 +347,13 @@ class Speaker(models.Model):
def get_absolute_url(self, link='detail'): def get_absolute_url(self, link='detail'):
if link == 'detail': if link == 'detail':
return self.person.get_absolute_url('detail') url = self.person.get_absolute_url('detail')
if link == 'delete': elif link == 'delete':
return reverse('agenda_speaker_delete', url = reverse('agenda_speaker_delete',
args=[self.item.pk, self.pk]) args=[self.item.pk, self.pk])
else:
url = super(Speaker, self).get_absolute_url(link)
return url
def check_and_update_projector(self): def check_and_update_projector(self):
""" """

View File

@ -11,6 +11,7 @@ from openslides.poll.models import (BaseOption, BasePoll, BaseVote,
CollectInvalid, CollectVotesCast, CollectInvalid, CollectVotesCast,
PublishPollMixin) PublishPollMixin)
from openslides.projector.models import RelatedModelMixin, SlideMixin from openslides.projector.models import RelatedModelMixin, SlideMixin
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person import PersonField from openslides.utils.person import PersonField
from openslides.utils.utils import html_strong from openslides.utils.utils import html_strong
@ -37,7 +38,7 @@ class AssignmentCandidate(RelatedModelMixin, models.Model):
return self.assignment return self.assignment
class Assignment(SlideMixin, models.Model): class Assignment(SlideMixin, AbsoluteUrlMixin, models.Model):
slide_callback_name = 'assignment' slide_callback_name = 'assignment'
STATUS = ( STATUS = (
@ -68,13 +69,15 @@ class Assignment(SlideMixin, models.Model):
return self.name return self.name
def get_absolute_url(self, link='detail'): def get_absolute_url(self, link='detail'):
if link == 'detail' or link == 'view': if link == 'detail':
return reverse('assignment_detail', args=[str(self.id)]) url = reverse('assignment_detail', args=[str(self.pk)])
if link == 'update' or link == 'update': elif link == 'update':
return reverse('assignment_update', args=[str(self.id)]) url = reverse('assignment_update', args=[str(self.pk)])
if link == 'delete': elif link == 'delete':
return reverse('assignment_delete', args=[str(self.id)]) url = reverse('assignment_delete', args=[str(self.pk)])
return super(Assignment, self).get_absolute_url(link) else:
url = super(Assignment, self).get_absolute_url(link)
return url
def get_slide_context(self, **context): def get_slide_context(self, **context):
context.update({ context.update({
@ -250,7 +253,7 @@ class AssignmentOption(BaseOption):
class AssignmentPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast, class AssignmentPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast,
PublishPollMixin, BasePoll): PublishPollMixin, AbsoluteUrlMixin, BasePoll):
option_class = AssignmentOption option_class = AssignmentOption
assignment = models.ForeignKey(Assignment, related_name='poll_set') assignment = models.ForeignKey(Assignment, related_name='poll_set')
@ -259,12 +262,14 @@ class AssignmentPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast,
def __unicode__(self): def __unicode__(self):
return _("Ballot %d") % self.get_ballot() return _("Ballot %d") % self.get_ballot()
@models.permalink def get_absolute_url(self, link='update'):
def get_absolute_url(self, link='detail'): if link == 'update':
if link == 'view' or link == 'detail' or link == 'update': url = reverse('assignment_poll_view', args=[str(self.pk)])
return ('assignment_poll_view', [str(self.pk)]) elif link == 'delete':
if link == 'delete': url = reverse('assignment_poll_delete', args=[str(self.pk)])
return ('assignment_poll_delete', [str(self.pk)]) else:
url = super(AssignmentPoll, self).get_absolute_url(link)
return url
def get_assignment(self): def get_assignment(self):
return self.assignment return self.assignment

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import warnings
from django import template from django import template
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -26,16 +24,6 @@ def trans(value):
return _(value) return _(value)
@register.simple_tag
def model_url(object, link='view'):
warnings.warn("model_url is deprecated; use absolute_url instead",
DeprecationWarning)
try:
return object.get_absolute_url(link)
except ValueError:
return ''
@register.filter @register.filter
def absolute_url(model, link=None): def absolute_url(model, link=None):
""" """

View File

@ -8,10 +8,11 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.projector.models import SlideMixin from openslides.projector.models import SlideMixin
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person.models import PersonField from openslides.utils.person.models import PersonField
class Mediafile(SlideMixin, models.Model): class Mediafile(SlideMixin, AbsoluteUrlMixin, models.Model):
""" """
Class for uploaded files which can be delivered under a certain url. Class for uploaded files which can be delivered under a certain url.
""" """
@ -74,10 +75,12 @@ class Mediafile(SlideMixin, models.Model):
'update' or 'delete'. 'update' or 'delete'.
""" """
if link == 'update': if link == 'update':
return reverse('mediafile_update', kwargs={'pk': str(self.id)}) url = reverse('mediafile_update', kwargs={'pk': str(self.pk)})
if link == 'delete': elif link == 'delete':
return reverse('mediafile_delete', kwargs={'pk': str(self.id)}) url = reverse('mediafile_delete', kwargs={'pk': str(self.pk)})
return super(Mediafile, self).get_absolute_url(link) else:
url = super(Mediafile, self).get_absolute_url(link)
return url
def get_filesize(self): def get_filesize(self):
""" """

View File

@ -13,12 +13,13 @@ from openslides.poll.models import (BaseOption, BasePoll, BaseVote,
CollectInvalid, CollectVotesCast) CollectInvalid, CollectVotesCast)
from openslides.projector.models import RelatedModelMixin, SlideMixin from openslides.projector.models import RelatedModelMixin, SlideMixin
from jsonfield import JSONField from jsonfield import JSONField
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person import PersonField from openslides.utils.person import PersonField
from .exceptions import WorkflowError from .exceptions import WorkflowError
class Motion(SlideMixin, models.Model): class Motion(SlideMixin, AbsoluteUrlMixin, models.Model):
""" """
The Motion Class. The Motion Class.
@ -174,12 +175,14 @@ class Motion(SlideMixin, models.Model):
The keyword argument 'link' can be 'detail', 'update' or 'delete'. The keyword argument 'link' can be 'detail', 'update' or 'delete'.
""" """
if link == 'detail': if link == 'detail':
return reverse('motion_detail', args=[str(self.id)]) url = reverse('motion_detail', args=[str(self.pk)])
if link == 'update': elif link == 'update':
return reverse('motion_update', args=[str(self.id)]) url = reverse('motion_update', args=[str(self.pk)])
if link == 'delete': elif link == 'delete':
return reverse('motion_delete', args=[str(self.id)]) url = reverse('motion_delete', args=[str(self.pk)])
return super(Motion, self).get_absolute_url(link) else:
url = super(Motion, self).get_absolute_url(link)
return url
def version_data_changed(self, version): def version_data_changed(self, version):
""" """
@ -515,7 +518,7 @@ class Motion(SlideMixin, models.Model):
MotionLog.objects.create(motion=self, message_list=message_list, person=person) MotionLog.objects.create(motion=self, message_list=message_list, person=person)
class MotionVersion(models.Model): class MotionVersion(AbsoluteUrlMixin, models.Model):
""" """
A MotionVersion object saves some date of the motion. A MotionVersion object saves some date of the motion.
""" """
@ -558,12 +561,15 @@ class MotionVersion(models.Model):
The keyargument link can be 'detail' or 'delete'. The keyargument link can be 'detail' or 'delete'.
""" """
if link == 'view' or link == 'detail': if link == 'detail':
return reverse('motion_version_detail', args=[str(self.motion.id), url = reverse('motion_version_detail', args=[str(self.motion.pk),
str(self.version_number)]) str(self.version_number)])
if link == 'delete': elif link == 'delete':
return reverse('motion_version_delete', args=[str(self.motion.id), url = reverse('motion_version_delete', args=[str(self.motion.pk),
str(self.version_number)]) str(self.version_number)])
else:
url = super(MotionVersion, self).get_absolute_url(link)
return url
@property @property
def active(self): def active(self):
@ -602,7 +608,7 @@ class MotionSupporter(models.Model):
return unicode(self.person) return unicode(self.person)
class Category(models.Model): class Category(AbsoluteUrlMixin, models.Model):
name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name")) name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name"))
"""Name of the category.""" """Name of the category."""
@ -617,9 +623,12 @@ class Category(models.Model):
def get_absolute_url(self, link='update'): def get_absolute_url(self, link='update'):
if link == 'update': if link == 'update':
return reverse('motion_category_update', args=[str(self.id)]) url = reverse('motion_category_update', args=[str(self.pk)])
if link == 'delete': elif link == 'delete':
return reverse('motion_category_delete', args=[str(self.id)]) url = reverse('motion_category_delete', args=[str(self.pk)])
else:
url = super(Category, self).get_absolute_url(link)
return url
class Meta: class Meta:
ordering = ['prefix'] ordering = ['prefix']
@ -685,7 +694,8 @@ class MotionOption(BaseOption):
"""The VoteClass, to witch this Class links.""" """The VoteClass, to witch this Class links."""
class MotionPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast, BasePoll): class MotionPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast,
AbsoluteUrlMixin, BasePoll):
"""The Class to saves the poll results for a motion poll.""" """The Class to saves the poll results for a motion poll."""
motion = models.ForeignKey(Motion, related_name='polls') motion = models.ForeignKey(Motion, related_name='polls')
@ -718,11 +728,14 @@ class MotionPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast, BasePoll):
The keyargument 'link' can be 'update' or 'delete'. The keyargument 'link' can be 'update' or 'delete'.
""" """
if link == 'update': if link == 'update':
return reverse('motion_poll_update', args=[str(self.motion.pk), url = reverse('motion_poll_update', args=[str(self.motion.pk),
str(self.poll_number)]) str(self.poll_number)])
if link == 'delete': elif link == 'delete':
return reverse('motion_poll_delete', args=[str(self.motion.pk), url = reverse('motion_poll_delete', args=[str(self.motion.pk),
str(self.poll_number)]) str(self.poll_number)])
else:
url = super(MotionPoll, self).get_absolute_url(link)
return url
def set_options(self): def set_options(self):
"""Create the option class for this poll.""" """Create the option class for this poll."""

View File

@ -12,11 +12,12 @@ from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.config.api import config from openslides.config.api import config
from openslides.projector.models import SlideMixin from openslides.projector.models import SlideMixin
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person import Person, PersonMixin from openslides.utils.person import Person, PersonMixin
from openslides.utils.person.signals import receive_persons from openslides.utils.person.signals import receive_persons
class User(SlideMixin, PersonMixin, Person, DjangoUser): class User(SlideMixin, PersonMixin, Person, AbsoluteUrlMixin, DjangoUser):
slide_callback_name = 'user' slide_callback_name = 'user'
person_prefix = 'user' person_prefix = 'user'
@ -65,12 +66,14 @@ class User(SlideMixin, PersonMixin, Person, DjangoUser):
Return the URL to the user. Return the URL to the user.
""" """
if link == 'detail': if link == 'detail':
return reverse('user_view', args=[str(self.id)]) url = reverse('user_view', args=[str(self.pk)])
if link == 'update': elif link == 'update':
return reverse('user_edit', args=[str(self.id)]) url = reverse('user_edit', args=[str(self.pk)])
if link == 'delete': elif link == 'delete':
return reverse('user_delete', args=[str(self.id)]) url = reverse('user_delete', args=[str(self.pk)])
return super(User, self).get_absolute_url(link) else:
url = super(User, self).get_absolute_url(link)
return url
def get_slide_context(self, **context): def get_slide_context(self, **context):
# Does not call super. In this case the context would override the name # Does not call super. In this case the context would override the name
@ -109,7 +112,7 @@ class User(SlideMixin, PersonMixin, Person, DjangoUser):
return self.last_name.lower() return self.last_name.lower()
class Group(SlideMixin, PersonMixin, Person, DjangoGroup): class Group(SlideMixin, PersonMixin, Person, AbsoluteUrlMixin, DjangoGroup):
slide_callback_name = 'group' slide_callback_name = 'group'
person_prefix = 'group' person_prefix = 'group'
@ -130,12 +133,14 @@ class Group(SlideMixin, PersonMixin, Person, DjangoGroup):
Return the URL to the user group. Return the URL to the user group.
""" """
if link == 'detail': if link == 'detail':
return reverse('user_group_view', args=[str(self.pk)]) url = reverse('user_group_view', args=[str(self.pk)])
if link == 'update': elif link == 'update':
return reverse('user_group_edit', args=[str(self.pk)]) url = reverse('user_group_edit', args=[str(self.pk)])
if link == 'delete': elif link == 'delete':
return reverse('user_group_delete', args=[str(self.pk)]) url = reverse('user_group_delete', args=[str(self.pk)])
return super(Group, self).get_absolute_url(link) else:
url = super(Group, self).get_absolute_url(link)
return url
class UsersAndGroupsToPersons(object): class UsersAndGroupsToPersons(object):

View File

@ -5,6 +5,7 @@ from django.core.urlresolvers import reverse
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy, ugettext_noop from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.utils import int_or_none from openslides.utils.utils import int_or_none
@ -106,7 +107,7 @@ class SlideMixin(object):
return context return context
class ProjectorSlide(SlideMixin, models.Model): class ProjectorSlide(SlideMixin, AbsoluteUrlMixin, models.Model):
""" """
Model for Slides, only for the projector. Also called custom slides. Model for Slides, only for the projector. Also called custom slides.
""" """
@ -118,19 +119,21 @@ class ProjectorSlide(SlideMixin, models.Model):
text = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Text")) text = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Text"))
weight = models.IntegerField(default=0, verbose_name=ugettext_lazy("Weight")) weight = models.IntegerField(default=0, verbose_name=ugettext_lazy("Weight"))
def get_absolute_url(self, link='update'):
if link == 'update':
return reverse('customslide_edit', args=[str(self.pk)])
if link == 'delete':
return reverse('customslide_delete', args=[str(self.pk)])
return super(ProjectorSlide, self).get_absolute_url(link)
def __unicode__(self):
return self.title
class Meta: class Meta:
permissions = ( permissions = (
('can_manage_projector', ugettext_noop("Can manage the projector")), ('can_manage_projector', ugettext_noop("Can manage the projector")),
('can_see_projector', ugettext_noop("Can see the projector")), ('can_see_projector', ugettext_noop("Can see the projector")),
('can_see_dashboard', ugettext_noop("Can see the dashboard")), ('can_see_dashboard', ugettext_noop("Can see the dashboard")),
) )
def __unicode__(self):
return self.title
def get_absolute_url(self, link='update'):
if link == 'update':
url = reverse('customslide_edit', args=[str(self.pk)])
elif link == 'delete':
url = reverse('customslide_delete', args=[str(self.pk)])
else:
url = super(ProjectorSlide, self).get_absolute_url(link)
return url

View File

@ -16,3 +16,19 @@ class MinMaxIntegerField(models.IntegerField):
defaults = {'min_value': self.min_value, 'max_value': self.max_value} defaults = {'min_value': self.min_value, 'max_value': self.max_value}
defaults.update(kwargs) defaults.update(kwargs)
return super(MinMaxIntegerField, self).formfield(**defaults) return super(MinMaxIntegerField, self).formfield(**defaults)
class AbsoluteUrlMixin(object):
"""
Mixin that raises a ValueError if the name of an url was not found with
get_absolute_url.
The Mixin has to be placed as last OpenSlides-Mixin before the django
model class.
"""
def get_absolute_url(self, link=None):
"""
Raises a ValueError.
"""
raise ValueError('Unknown Link "%s" for model "%s"' % (link, type(self)))

View File

@ -51,9 +51,14 @@ class Person(object):
* delete * delete
You should raise an 'ValueError', if your person does not have You should raise an 'ValueError', if your person does not have
one of this links. one of this links, or use the AbsoluteURLMixin, which raises the
ValueError for you.
""" """
try:
url = super(Person, self).get_absolute_url(link)
except AttributeError:
raise ValueError('This person object has no url.') raise ValueError('This person object has no url.')
return url
class Persons(object): class Persons(object):

View File

@ -141,7 +141,8 @@ class UrlMixin(object):
value = self.object.get_absolute_url(use_absolute_url_link) value = self.object.get_absolute_url(use_absolute_url_link)
except AttributeError: except AttributeError:
raise ImproperlyConfigured( raise ImproperlyConfigured(
'No url to redirect to. See openslides.utils.views.UrlMixin for more details.') 'No url to redirect to. See openslides.utils.views.UrlMixin '
'for more details.')
return value return value
def get_url_name_args(self): def get_url_name_args(self):

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.test import TestCase
class MyModel(AbsoluteUrlMixin):
""""
Model for testing
"""
def get_absolute_url(self, link='default'):
if link == 'default' or link == 'known':
url = 'my url'
else:
url = super(MyModel, self).get_absolute_url(link)
return url
class TestAbsoluteUrlMixin(TestCase):
def test_get_absolute_url(self):
my_object = MyModel()
self.assertEqual(my_object.get_absolute_url(), 'my url')
self.assertEqual(my_object.get_absolute_url('known'), 'my url')
self.assertRaisesMessage(
ValueError,
'Unknown Link "unknown" for model "<class \'tests.utils.test_models.MyModel\'>"',
my_object.get_absolute_url, 'unknown')