clean up the projector App

This commit is contained in:
Oskar Hahn 2012-07-07 14:01:40 +02:00
parent eb3adcd8ca
commit 15621b7702
8 changed files with 203 additions and 164 deletions

View File

@ -17,6 +17,9 @@ from openslides.projector.projector import SLIDE, Slide, Widget
def split_sid(sid): def split_sid(sid):
"""
Slit a SID in the model-part and in the model-id
"""
try: try:
data = sid.split('-') data = sid.split('-')
except AttributeError: except AttributeError:
@ -34,6 +37,11 @@ def split_sid(sid):
def get_slide_from_sid(sid, element=False): def get_slide_from_sid(sid, element=False):
"""
Return the Slide for an given sid.
If element== False, return the slide-dict,
else, return the object.
"""
try: try:
key, id = split_sid(sid) key, id = split_sid(sid)
except TypeError: except TypeError:
@ -56,10 +64,10 @@ def get_slide_from_sid(sid, element=False):
def get_active_slide(only_sid=False): def get_active_slide(only_sid=False):
""" """
Returns the active slide. If no slide is active, or it can not find an Item, Returns the active slide. If no slide is active, or it can not find an Item,
it raise an error return None
if only_sid is True, returns only the id of this item. Returns None if not Item if only_sid is True, returns only the id of this item. Returns None if not
is active. Does not Raise Item.DoesNotExist Item is active.
""" """
sid = config["presentation"] sid = config["presentation"]
@ -69,12 +77,18 @@ def get_active_slide(only_sid=False):
def set_active_slide(sid, argument=None): def set_active_slide(sid, argument=None):
"""
Set the active Slide.
"""
config["presentation"] = sid config["presentation"] = sid
config['presentation_argument'] = argument config['presentation_argument'] = argument
def register_slidemodel(model, model_name=None, control_template=None, weight=0): def register_slidemodel(model, model_name=None, control_template=None,
#TODO: Warn if there already is a slide with this prefix weight=0):
"""
Register a Model as a slide.
"""
if model_name is None: if model_name is None:
model_name = model.prefix model_name = model.prefix
@ -94,7 +108,9 @@ def register_slidemodel(model, model_name=None, control_template=None, weight=0)
def register_slidefunc(key, func, control_template=None, weight=0, name=''): def register_slidefunc(key, func, control_template=None, weight=0, name=''):
#TODO: Warn if there already is a slide with this prefix """
Register a function for as a slide.
"""
if control_template is None: if control_template is None:
control_template = 'projector/default_control_slidefunc.html' control_template = 'projector/default_control_slidefunc.html'
category = func.__module__.split('.')[0] category = func.__module__.split('.')[0]
@ -110,6 +126,10 @@ def register_slidefunc(key, func, control_template=None, weight=0, name=''):
def projector_message_set(message, sid=None): def projector_message_set(message, sid=None):
"""
Set the overlay-message.
if sid is set, only show the message on the sid-slide.
"""
from models import ProjectorOverlay from models import ProjectorOverlay
config['projector_message'] = message config['projector_message'] = message
try: try:
@ -121,4 +141,7 @@ def projector_message_set(message, sid=None):
def projector_message_delete(): def projector_message_delete():
"""
Delete the overlay-message.
"""
config['projector_message'] = '' config['projector_message'] = ''

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
openslides.projector.models openslides.projector.models
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
Models for the projector app. Models for the projector app.
@ -12,22 +12,25 @@
from django.db import models from django.db import models
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import ugettext as _, ugettext_noop
from openslides.config.signals import default_config_value from openslides.config.signals import default_config_value
from api import register_slidemodel from openslides.projector.api import register_slidemodel
from projector import SlideMixin from openslides.projector.projector import SlideMixin
from openslides.config.models import config
from config.models import config
from utils.translation_ext import ugettext as _
class ProjectorSlide(models.Model, SlideMixin): class ProjectorSlide(models.Model, SlideMixin):
"""
Model for Slides, only for the projector. Also called custom slides.
"""
prefix = 'ProjectorSlide' prefix = 'ProjectorSlide'
title = models.CharField(max_length=256, verbose_name=_("Title")) title = models.CharField(max_length=256, verbose_name=_("Title"))
text = models.TextField(null=True, blank=True, verbose_name=_("Text")) text = models.TextField(null=True, blank=True, verbose_name=_("Text"))
#weight = models.IntegerField(default=0, verbose_name=_("Weight"))
def slide(self): def slide(self):
return { return {
@ -46,12 +49,19 @@ class ProjectorSlide(models.Model, SlideMixin):
class Meta: class Meta:
permissions = ( permissions = (
('can_manage_projector', _("Can manage the projector", fixstr=True)), ('can_manage_projector', ugettext_noop("Can manage the projector")),
('can_see_projector', _("Can see projector", fixstr=True)), ('can_see_projector', ugettext_noop("Can see projector")),
) )
register_slidemodel(ProjectorSlide,
control_template='projector/control_customslide.html')
class ProjectorOverlay(models.Model): class ProjectorOverlay(models.Model):
"""
Save information for a overlay.
"""
active = models.BooleanField(verbose_name=_('Active')) active = models.BooleanField(verbose_name=_('Active'))
def_name = models.CharField(max_length=64) def_name = models.CharField(max_length=64)
sid = models.CharField(max_length=64, null=True, blank=True) sid = models.CharField(max_length=64, null=True, blank=True)
@ -62,9 +72,6 @@ class ProjectorOverlay(models.Model):
return self.def_name return self.def_name
register_slidemodel(ProjectorSlide, control_template='projector/control_customslide.html')
@receiver(default_config_value, dispatch_uid="projector_default_config") @receiver(default_config_value, dispatch_uid="projector_default_config")
def default_config(sender, key, **kwargs): def default_config(sender, key, **kwargs):
return { return {

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
openslides.projector.projector openslides.projector.projector
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Slide functions for the projector app. Slide functions for the projector app.
@ -29,7 +29,7 @@ class SlideMixin(object):
def slide(self): def slide(self):
""" """
Return a map with all Data for a Slide Return a map with all Data for the Slide.
""" """
return { return {
'slide': self, 'slide': self,
@ -47,19 +47,22 @@ class SlideMixin(object):
@property @property
def active(self): def active(self):
""" """
Return True, if the the slide is the active one. Return True, if the the slide is the active slide.
""" """
from api import get_active_slide from api import get_active_slide
return True if get_active_slide(only_sid=True) == self.sid else False return get_active_slide(only_sid=True) == self.sid
def set_active(self): def set_active(self):
""" """
Appoint this item as the active one. Appoint this item as the active slide.
""" """
config["presentation"] = "%s-%d" % (self.prefix, self.id) set_active_slide(self.sid)
class Slide(object): class Slide(object):
"""
Represents a Slide for the projector. Can be a modelinstanz, or a function.
"""
def __init__(self, model_slide=False, func=None, model=None, category=None, def __init__(self, model_slide=False, func=None, model=None, category=None,
key=None, model_name='', control_template='', weight=0, name=''): key=None, model_name='', control_template='', weight=0, name=''):
""" """
@ -82,10 +85,16 @@ class Slide(object):
@property @property
def active(self): def active(self):
"""
Return True if the Slide is active, else: False.
"""
from api import get_active_slide from api import get_active_slide
return get_active_slide(True) == self.key return get_active_slide(True) == self.key
def get_items(self): def get_items(self):
"""
If the Slide is a Slide from a Model, return all Objects.
"""
try: try:
return self.model.objects.all() return self.model.objects.all()
except AttributeError: except AttributeError:
@ -93,6 +102,9 @@ class Slide(object):
class Widget(object): class Widget(object):
"""
Class for a Widget for the Projector-Tab.
"""
def __init__(self, name, html=None, template=None, context={}): def __init__(self, name, html=None, template=None, context={}):
self.name = name self.name = name
if html is not None: if html is not None:

View File

@ -13,5 +13,3 @@
from django.dispatch import Signal from django.dispatch import Signal
projector_overlays = Signal(providing_args=['register', 'call']) projector_overlays = Signal(providing_args=['register', 'call'])
projector_control_box = Signal()

View File

@ -1,21 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.projector.tests
~~~~~~~~~~~~~~~~~~~~~~~~~~
Unit tests for the projector app.
:copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
openslides.projector.urls openslides.projector.urls
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
URL list for the projector app. URL list for the projector app.
@ -10,11 +10,8 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.conf.urls.defaults import * from django.conf.urls.defaults import patterns, url
from openslides.utils.views import CreateView
from openslides.projector.models import ProjectorSlide
from openslides.projector.views import (ControlView, ActivateView, from openslides.projector.views import (ControlView, ActivateView,
CustomSlideCreateView, CustomSlideUpdateView, CustomSlideDeleteView, CustomSlideCreateView, CustomSlideUpdateView, CustomSlideDeleteView,
CountdownEdit, ProjectorEdit, Projector, ActivateOverlay) CountdownEdit, ProjectorEdit, Projector, ActivateOverlay)
@ -104,12 +101,6 @@ urlpatterns = patterns('projector.views',
name='projector_clean', name='projector_clean',
), ),
# TODO: Merge the following lines with this one:
## url(r'^countdown/(?P<command>[^/]*)/$',
## CountdownEdit.as_view(),
## name='countdown_edit',
## ),
url(r'^countdown/reset/$', url(r'^countdown/reset/$',
CountdownEdit.as_view(), CountdownEdit.as_view(),
{'command': 'reset'}, {'command': 'reset'},

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
openslides.projector.views openslides.projector.views
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
Views for the projector app. Views for the projector app.
@ -13,41 +13,48 @@
from datetime import datetime from datetime import datetime
from time import time from time import time
from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _ from django.db.models import Q
from django.dispatch import receiver
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module from django.utils.importlib import import_module
from django.dispatch import receiver from django.utils.translation import ugettext as _
from django.db.models import Q
from django.conf import settings
from openslides.utils.template import render_block_to_string, Tab
from openslides.utils.utils import html_strong
from openslides.utils.views import (TemplateView, RedirectView, CreateView, from openslides.utils.views import (TemplateView, RedirectView, CreateView,
UpdateView, DeleteView, AjaxMixin) UpdateView, DeleteView, AjaxMixin)
from openslides.utils.template import render_block_to_string, Tab
from openslides.config.models import config from openslides.config.models import config
from openslides.projector.api import (get_active_slide, set_active_slide, from openslides.projector.api import (get_active_slide, set_active_slide,
projector_message_set, projector_message_delete, get_slide_from_sid) projector_message_set, projector_message_delete, get_slide_from_sid)
from openslides.projector.projector import SLIDE, Widget
from openslides.projector.models import ProjectorOverlay, ProjectorSlide from openslides.projector.models import ProjectorOverlay, ProjectorSlide
from openslides.projector.projector import SLIDE, Widget
from openslides.projector.signals import projector_overlays from openslides.projector.signals import projector_overlays
class ControlView(TemplateView, AjaxMixin): class ControlView(TemplateView, AjaxMixin):
"""
Overview over all possible slides, the overlays and a liveview.
"""
template_name = 'projector/control.html' template_name = 'projector/control.html'
permission_required = 'projector.can_manage_projector' permission_required = 'projector.can_manage_projector'
def get_projector_overlays(self): def get_projector_overlays(self):
overlays = [] overlays = []
for receiver, name in projector_overlays.send(sender='registerer', register=True): for receiver, name in projector_overlays.send(sender='registerer',
register=True):
if name is not None: if name is not None:
try: try:
projector_overlay = ProjectorOverlay.objects.get(def_name=name) projector_overlay = ProjectorOverlay.objects.get(
def_name=name)
except ProjectorOverlay.DoesNotExist: except ProjectorOverlay.DoesNotExist:
active = name == 'Message' active = name == 'Message'
projector_overlay = ProjectorOverlay(def_name=name, active=active) projector_overlay = ProjectorOverlay(def_name=name,
active=active)
projector_overlay.save() projector_overlay.save()
overlays.append(projector_overlay) overlays.append(projector_overlay)
return overlays return overlays
@ -57,13 +64,6 @@ class ControlView(TemplateView, AjaxMixin):
projector_message_set(request.POST['message_text']) projector_message_set(request.POST['message_text'])
elif 'message-clean' in request.POST: elif 'message-clean' in request.POST:
projector_message_delete() projector_message_delete()
else:
for overlay in self.get_projector_overlays():
if overlay.def_name in request.POST:
overlay.active = True
else:
overlay.active = False
overlay.save()
if request.is_ajax(): if request.is_ajax():
return self.ajax_get(request, *args, **kwargs) return self.ajax_get(request, *args, **kwargs)
return self.get(request, *args, **kwargs) return self.get(request, *args, **kwargs)
@ -101,87 +101,10 @@ class ControlView(TemplateView, AjaxMixin):
return context return context
class ActivateOverlay(RedirectView):
url = 'projector_control'
allow_ajax = True
@property
def overlay(self):
try:
return self._overlay
except AttributeError:
self._overlay = ProjectorOverlay.objects.get(def_name=self.kwargs['name'])
return self._overlay
def pre_redirect(self, request, *args, **kwargs):
if kwargs['activate']:
self.overlay.active = True
else:
self.overlay.active = False
self.overlay.save()
def get_ajax_context(self, **kwargs):
return {
'active': self.overlay.active,
'def_name': self.overlay.def_name,
}
class ActivateView(RedirectView):
url = 'projector_control'
allow_ajax = True
def pre_redirect(self, request, *args, **kwargs):
try:
set_active_slide(kwargs['sid'], kwargs['argument'])
except KeyError:
set_active_slide(kwargs['sid'])
config['up'] = 0
config['bigger'] = 100
class CustomSlideCreateView(CreateView):
permission_required = 'agenda.can_manage_agenda'
template_name = 'projector/new.html'
model = ProjectorSlide
context_object_name = 'customslide'
success_url = 'projector_control'
apply_url = 'customslide_edit'
def get_success_url(self):
messages.success(self.request, _("Custom slide <b>%s</b> was successfully created.") % self.request.POST['title'])
if 'apply' in self.request.POST:
return reverse(self.get_apply_url(), args=[self.object.id])
return reverse(super(CreateView, self).get_success_url())
class CustomSlideUpdateView(UpdateView):
permission_required = 'projector.can_manage_projector'
template_name = 'projector/new.html'
model = ProjectorSlide
context_object_name = 'customslide'
success_url = 'projector_control'
apply_url = 'customslide_edit'
def get_success_url(self):
messages.success(self.request, _("Custom slide <b>%s</b> was successfully modified.") % self.request.POST['title'])
if 'apply' in self.request.POST:
return ''
return reverse(super(UpdateView, self).get_success_url())
class CustomSlideDeleteView(DeleteView):
permission_required = 'projector.can_manage_projector'
model = ProjectorSlide
url = 'projector_control'
def pre_post_redirect(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.delete()
messages.success(request, _("Custom slide <b>%s</b> was successfully deleted.") % self.object)
class Projector(TemplateView, AjaxMixin): class Projector(TemplateView, AjaxMixin):
"""
The Projector-Page.
"""
permission_required = 'projector.can_see_projector' permission_required = 'projector.can_see_projector'
@property @property
@ -211,8 +134,11 @@ class Projector(TemplateView, AjaxMixin):
# Projector Overlays # Projector Overlays
if self.kwargs['sid'] is None: if self.kwargs['sid'] is None:
active_defs = ProjectorOverlay.objects.filter(active=True).filter(Q(sid=sid) | Q(sid=None)).values_list('def_name', flat=True) active_defs = ProjectorOverlay.objects.filter(active=True) \
for receiver, response in projector_overlays.send(sender=sid, register=False, call=active_defs): .filter(Q(sid=sid) | Q(sid=None)).values_list('def_name',
flat=True)
for receiver, response in projector_overlays.send(sender=sid,
register=False, call=active_defs):
if response is not None: if response is not None:
data['overlays'].append(response) data['overlays'].append(response)
self._data = data self._data = data
@ -227,8 +153,10 @@ class Projector(TemplateView, AjaxMixin):
return context return context
def get_ajax_context(self, **kwargs): def get_ajax_context(self, **kwargs):
content = render_block_to_string(self.get_template_names()[0], 'content', self.data) content = render_block_to_string(self.get_template_names()[0],
scrollcontent = render_block_to_string(self.get_template_names()[0], 'scrollcontent', self.data) 'content', self.data)
scrollcontent = render_block_to_string(self.get_template_names()[0],
'scrollcontent', self.data)
context = super(Projector, self).get_ajax_context(**kwargs) context = super(Projector, self).get_ajax_context(**kwargs)
content_hash = hash(content) content_hash = hash(content)
@ -250,8 +178,27 @@ class Projector(TemplateView, AjaxMixin):
return super(Projector, self).get(request, *args, **kwargs) return super(Projector, self).get(request, *args, **kwargs)
class ActivateView(RedirectView):
"""
Activate a Slide.
"""
permission_required = 'projector.can_manage_projector'
url = 'projector_control'
allow_ajax = True
def pre_redirect(self, request, *args, **kwargs):
try:
set_active_slide(kwargs['sid'], kwargs['argument'])
except KeyError:
set_active_slide(kwargs['sid'])
config['up'] = 0
config['bigger'] = 100
class ProjectorEdit(RedirectView): class ProjectorEdit(RedirectView):
"""
Scale or scroll the projector.
"""
permission_required = 'projector.can_manage_projector' permission_required = 'projector.can_manage_projector'
url = 'projector_control' url = 'projector_control'
allow_ajax = True allow_ajax = True
@ -273,6 +220,9 @@ class ProjectorEdit(RedirectView):
class CountdownEdit(RedirectView): class CountdownEdit(RedirectView):
"""
Start, stop or reset the countdown.
"""
permission_required = 'projector.can_manage_projector' permission_required = 'projector.can_manage_projector'
url = 'projector_control' url = 'projector_control'
allow_ajax = True allow_ajax = True
@ -293,8 +243,8 @@ class CountdownEdit(RedirectView):
start_stamp = config['countdown_start_stamp'] start_stamp = config['countdown_start_stamp']
pause_stamp = config['countdown_pause_stamp'] pause_stamp = config['countdown_pause_stamp']
now = time() now = time()
config['countdown_start_stamp'] = now - \
config['countdown_start_stamp'] = now - (pause_stamp - start_stamp) (pause_stamp - start_stamp)
else: else:
config['countdown_start_stamp'] = time() config['countdown_start_stamp'] = time()
@ -306,7 +256,8 @@ class CountdownEdit(RedirectView):
config['countdown_state'] = 'paused' config['countdown_state'] = 'paused'
elif command == 'set-default': elif command == 'set-default':
try: try:
config['countdown_time'] = int(self.request.GET['countdown_time']) config['countdown_time'] = \
int(self.request.GET['countdown_time'])
except ValueError: except ValueError:
pass pass
except AttributeError: except AttributeError:
@ -319,7 +270,74 @@ class CountdownEdit(RedirectView):
} }
class ActivateOverlay(RedirectView):
"""
Activate or deactivate an overlay.
"""
url = 'projector_control'
allow_ajax = True
permission_required = 'projector.can_manage_projector'
@property
def overlay(self):
try:
return self._overlay
except AttributeError:
self._overlay = ProjectorOverlay.objects.get(
def_name=self.kwargs['name'])
return self._overlay
def pre_redirect(self, request, *args, **kwargs):
if kwargs['activate']:
self.overlay.active = True
else:
self.overlay.active = False
self.overlay.save()
def get_ajax_context(self, **kwargs):
return {
'active': self.overlay.active,
'def_name': self.overlay.def_name,
}
class CustomSlideCreateView(CreateView):
"""
Create a custom slide.
"""
permission_required = 'agenda.can_manage_agenda'
template_name = 'projector/new.html'
model = ProjectorSlide
context_object_name = 'customslide'
success_url = 'projector_control'
apply_url = 'customslide_edit'
class CustomSlideUpdateView(UpdateView):
"""
Update a custom slide.
"""
permission_required = 'projector.can_manage_projector'
template_name = 'projector/new.html'
model = ProjectorSlide
context_object_name = 'customslide'
success_url = 'projector_control'
apply_url = 'customslide_edit'
class CustomSlideDeleteView(DeleteView):
"""
Delete a custom slide.
"""
permission_required = 'projector.can_manage_projector'
model = ProjectorSlide
url = 'projector_control'
def register_tab(request): def register_tab(request):
"""
Register the projector tab.
"""
selected = True if request.path.startswith('/projector/') else False selected = True if request.path.startswith('/projector/') else False
return Tab( return Tab(
title=_('Projector'), title=_('Projector'),
@ -330,6 +348,9 @@ def register_tab(request):
def get_widgets(request): def get_widgets(request):
"""
Return the custom slide widget.
"""
return [ return [
Widget( Widget(
name='projector', name='projector',

View File

@ -52,7 +52,7 @@ from django.views.generic.list import TemplateResponseMixin
from openslides.config.models import config from openslides.config.models import config
from openslides.utils.utils import render_to_forbitten from openslides.utils.utils import render_to_forbitten, html_strong
from openslides.utils.signals import template_manipulation from openslides.utils.signals import template_manipulation
from openslides.utils.pdf import firstPage, laterPages from openslides.utils.pdf import firstPage, laterPages
@ -164,6 +164,7 @@ class FormView(PermissionMixin, _FormView):
class UpdateView(PermissionMixin, _UpdateView): class UpdateView(PermissionMixin, _UpdateView):
def get_success_url(self): def get_success_url(self):
messages.success(self.request, self.get_success_message())
if 'apply' in self.request.POST: if 'apply' in self.request.POST:
return '' return ''
return reverse(super(UpdateView, self).get_success_url()) return reverse(super(UpdateView, self).get_success_url())
@ -177,9 +178,13 @@ class UpdateView(PermissionMixin, _UpdateView):
messages.error(self.request, _('Please check the form for errors.')) messages.error(self.request, _('Please check the form for errors.'))
return super(UpdateView, self).form_invalid(form) return super(UpdateView, self).form_invalid(form)
def get_success_message(self):
return _('%s was successfully modified.') % html_strong(self.object)
class CreateView(PermissionMixin, _CreateView): class CreateView(PermissionMixin, _CreateView):
def get_success_url(self): def get_success_url(self):
messages.success(self.request, self.get_success_message())
if 'apply' in self.request.POST: if 'apply' in self.request.POST:
return reverse(self.get_apply_url(), args=[self.object.id]) return reverse(self.get_apply_url(), args=[self.object.id])
return reverse(super(CreateView, self).get_success_url()) return reverse(super(CreateView, self).get_success_url())
@ -197,13 +202,16 @@ class CreateView(PermissionMixin, _CreateView):
messages.error(self.request, _('Please check the form for errors.')) messages.error(self.request, _('Please check the form for errors.'))
return super(CreateView, self).form_invalid(form) return super(CreateView, self).form_invalid(form)
def get_success_message(self):
return _('%s was successfully created.') % html_strong(self.object)
class DeleteView(RedirectView, SingleObjectMixin): class DeleteView(RedirectView, SingleObjectMixin):
def get_confirm_question(self): def get_confirm_question(self):
return _('Do you really want to delete <b>%s</b>?') % self.object return _('Do you really want to delete %s?') % html_strong(self.object)
def get_success_message(self): def get_success_message(self):
return _('Item <b>%s</b> was successfully deleted.') % self.object return _('%s was successfully deleted.') % html_strong(self.object)
def pre_redirect(self, request, *args, **kwargs): def pre_redirect(self, request, *args, **kwargs):
self.confirm_form(request, self.object) self.confirm_form(request, self.object)