Merge pull request #1172 from ostcar/get_absolut_url_mixin

Added AbsoluteUrlMixin and used it in any model.
This commit is contained in:
Oskar Hahn 2014-01-12 01:02:14 -08:00
commit 03c59303d7
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)
from openslides.projector.models import SlideMixin
from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person.models import PersonField
class Item(SlideMixin, MPTTModel):
class Item(SlideMixin, AbsoluteUrlMixin, MPTTModel):
"""
An Agenda Item
@ -296,7 +297,7 @@ class SpeakerManager(models.Manager):
return self.create(item=item, person=person, weight=weight + 1)
class Speaker(models.Model):
class Speaker(AbsoluteUrlMixin, models.Model):
"""
Model for the Speaker list.
"""
@ -346,10 +347,13 @@ class Speaker(models.Model):
def get_absolute_url(self, link='detail'):
if link == 'detail':
return self.person.get_absolute_url('detail')
if link == 'delete':
return reverse('agenda_speaker_delete',
args=[self.item.pk, self.pk])
url = self.person.get_absolute_url('detail')
elif link == 'delete':
url = reverse('agenda_speaker_delete',
args=[self.item.pk, self.pk])
else:
url = super(Speaker, self).get_absolute_url(link)
return url
def check_and_update_projector(self):
"""

View File

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

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
import warnings
from django import template
from django.utils.translation import ugettext as _
@ -26,16 +24,6 @@ def trans(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
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 openslides.projector.models import SlideMixin
from openslides.utils.models import AbsoluteUrlMixin
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.
"""
@ -74,10 +75,12 @@ class Mediafile(SlideMixin, models.Model):
'update' or 'delete'.
"""
if link == 'update':
return reverse('mediafile_update', kwargs={'pk': str(self.id)})
if link == 'delete':
return reverse('mediafile_delete', kwargs={'pk': str(self.id)})
return super(Mediafile, self).get_absolute_url(link)
url = reverse('mediafile_update', kwargs={'pk': str(self.pk)})
elif link == 'delete':
url = reverse('mediafile_delete', kwargs={'pk': str(self.pk)})
else:
url = super(Mediafile, self).get_absolute_url(link)
return url
def get_filesize(self):
"""

View File

@ -13,12 +13,13 @@ from openslides.poll.models import (BaseOption, BasePoll, BaseVote,
CollectInvalid, CollectVotesCast)
from openslides.projector.models import RelatedModelMixin, SlideMixin
from jsonfield import JSONField
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person import PersonField
from .exceptions import WorkflowError
class Motion(SlideMixin, models.Model):
class Motion(SlideMixin, AbsoluteUrlMixin, models.Model):
"""
The Motion Class.
@ -174,12 +175,14 @@ class Motion(SlideMixin, models.Model):
The keyword argument 'link' can be 'detail', 'update' or 'delete'.
"""
if link == 'detail':
return reverse('motion_detail', args=[str(self.id)])
if link == 'update':
return reverse('motion_update', args=[str(self.id)])
if link == 'delete':
return reverse('motion_delete', args=[str(self.id)])
return super(Motion, self).get_absolute_url(link)
url = reverse('motion_detail', args=[str(self.pk)])
elif link == 'update':
url = reverse('motion_update', args=[str(self.pk)])
elif link == 'delete':
url = reverse('motion_delete', args=[str(self.pk)])
else:
url = super(Motion, self).get_absolute_url(link)
return url
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)
class MotionVersion(models.Model):
class MotionVersion(AbsoluteUrlMixin, models.Model):
"""
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'.
"""
if link == 'view' or link == 'detail':
return reverse('motion_version_detail', args=[str(self.motion.id),
str(self.version_number)])
if link == 'delete':
return reverse('motion_version_delete', args=[str(self.motion.id),
str(self.version_number)])
if link == 'detail':
url = reverse('motion_version_detail', args=[str(self.motion.pk),
str(self.version_number)])
elif link == 'delete':
url = reverse('motion_version_delete', args=[str(self.motion.pk),
str(self.version_number)])
else:
url = super(MotionVersion, self).get_absolute_url(link)
return url
@property
def active(self):
@ -602,7 +608,7 @@ class MotionSupporter(models.Model):
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 of the category."""
@ -617,9 +623,12 @@ class Category(models.Model):
def get_absolute_url(self, link='update'):
if link == 'update':
return reverse('motion_category_update', args=[str(self.id)])
if link == 'delete':
return reverse('motion_category_delete', args=[str(self.id)])
url = reverse('motion_category_update', args=[str(self.pk)])
elif link == 'delete':
url = reverse('motion_category_delete', args=[str(self.pk)])
else:
url = super(Category, self).get_absolute_url(link)
return url
class Meta:
ordering = ['prefix']
@ -685,7 +694,8 @@ class MotionOption(BaseOption):
"""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."""
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'.
"""
if link == 'update':
return reverse('motion_poll_update', args=[str(self.motion.pk),
str(self.poll_number)])
if link == 'delete':
return reverse('motion_poll_delete', args=[str(self.motion.pk),
str(self.poll_number)])
url = reverse('motion_poll_update', args=[str(self.motion.pk),
str(self.poll_number)])
elif link == 'delete':
url = reverse('motion_poll_delete', args=[str(self.motion.pk),
str(self.poll_number)])
else:
url = super(MotionPoll, self).get_absolute_url(link)
return url
def set_options(self):
"""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.projector.models import SlideMixin
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.person import Person, PersonMixin
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'
person_prefix = 'user'
@ -65,12 +66,14 @@ class User(SlideMixin, PersonMixin, Person, DjangoUser):
Return the URL to the user.
"""
if link == 'detail':
return reverse('user_view', args=[str(self.id)])
if link == 'update':
return reverse('user_edit', args=[str(self.id)])
if link == 'delete':
return reverse('user_delete', args=[str(self.id)])
return super(User, self).get_absolute_url(link)
url = reverse('user_view', args=[str(self.pk)])
elif link == 'update':
url = reverse('user_edit', args=[str(self.pk)])
elif link == 'delete':
url = reverse('user_delete', args=[str(self.pk)])
else:
url = super(User, self).get_absolute_url(link)
return url
def get_slide_context(self, **context):
# 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()
class Group(SlideMixin, PersonMixin, Person, DjangoGroup):
class Group(SlideMixin, PersonMixin, Person, AbsoluteUrlMixin, DjangoGroup):
slide_callback_name = 'group'
person_prefix = 'group'
@ -130,12 +133,14 @@ class Group(SlideMixin, PersonMixin, Person, DjangoGroup):
Return the URL to the user group.
"""
if link == 'detail':
return reverse('user_group_view', args=[str(self.pk)])
if link == 'update':
return reverse('user_group_edit', args=[str(self.pk)])
if link == 'delete':
return reverse('user_group_delete', args=[str(self.pk)])
return super(Group, self).get_absolute_url(link)
url = reverse('user_group_view', args=[str(self.pk)])
elif link == 'update':
url = reverse('user_group_edit', args=[str(self.pk)])
elif link == 'delete':
url = reverse('user_group_delete', args=[str(self.pk)])
else:
url = super(Group, self).get_absolute_url(link)
return url
class UsersAndGroupsToPersons(object):

View File

@ -5,6 +5,7 @@ from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.utils import int_or_none
@ -106,7 +107,7 @@ class SlideMixin(object):
return context
class ProjectorSlide(SlideMixin, models.Model):
class ProjectorSlide(SlideMixin, AbsoluteUrlMixin, models.Model):
"""
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"))
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:
permissions = (
('can_manage_projector', ugettext_noop("Can manage the projector")),
('can_see_projector', ugettext_noop("Can see the projector")),
('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.update(kwargs)
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
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.
"""
raise ValueError('This person object has no url.')
try:
url = super(Person, self).get_absolute_url(link)
except AttributeError:
raise ValueError('This person object has no url.')
return url
class Persons(object):

View File

@ -141,7 +141,8 @@ class UrlMixin(object):
value = self.object.get_absolute_url(use_absolute_url_link)
except AttributeError:
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
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')