Add error message if a invalid answer was send via POST to a QuestionView. Fix #940.

This commit is contained in:
Norman Jäckel 2013-10-24 18:48:16 +02:00
parent 947a976b86
commit b2afa77e25
4 changed files with 71 additions and 40 deletions

View File

@ -22,8 +22,8 @@ Other:
- Full text search integration (with Haystack and Whoosh).
- New start script with new command line options.
- Fixed keyerror on user settings view.
- New message on success of many actions like creating or editing objects.
- Added Feature to config app to return the default value for a key.
- New messages on success or error of many actions like creating or editing objects.
- Added feature to config app to return the default value for a key.
- Cleaned up OpenSlides utils views.
- Used flake8 instead of pep8 for style check, sort all import statements with isort.
- Added Portuguese translation (Thanks to Marco A.G.Pinto).
@ -60,7 +60,7 @@ Version 1.4.1 (2013-07-29)
Version 1.4 (2013-07-10)
========================
========================
[https://github.com/OpenSlides/OpenSlides/issues?milestone=7]
Agenda:
@ -121,7 +121,7 @@ Version 1.3.1 (2013-01-09)
==========================
[http://dev.openslides.org/milestone/1.3.1]
- Fixed unwanted automatical language switching on projector view if more than
- Fixed unwanted automatical language switching on projector view if more than
one browser languages send projector request to OpenSlides (#434)

View File

@ -270,20 +270,29 @@ class ItemDelete(DeleteView):
self.item_delete_answer_options = options
return options
def pre_post_redirect(self, request, *args, **kwargs):
# TODO: rewrite this method with on_case_all and on_case_yes
if self.get_answer() == 'all':
self.object.delete(with_children=True)
messages.success(
request,
_("Item %s and his children were successfully deleted.")
% html_strong(self.object))
elif self.get_answer() == 'yes':
self.object.delete(with_children=False)
messages.success(
request,
_("Item %s was successfully deleted.")
% html_strong(self.object))
def on_clicked_yes(self):
"""
Deletes the item but not its children.
"""
self.object.delete(with_children=False)
def on_clicked_all(self):
"""
Deletes the item and its children.
"""
self.object.delete(with_children=True)
def get_final_message(self):
"""
Prints the success message to the user.
"""
# OpenSlidesError (invalid answer) should never be raised here because
# this method should only be called if the answer is 'yes' or 'all'.
if self.get_answer() == 'yes':
message = _('Item %s was successfully deleted.') % html_strong(self.object)
else:
message = _('Item %s and its children were successfully deleted.') % html_strong(self.object)
return message
class CreateRelatedAgendaItemView(SingleObjectMixin, RedirectView):

View File

@ -33,6 +33,7 @@ from django.views.generic.detail import SingleObjectMixin
from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, Spacer
from .exceptions import OpenSlidesError
from .pdf import firstPage, laterPages
from .signals import template_manipulation
from .utils import html_strong
@ -400,32 +401,38 @@ class QuestionView(RedirectView):
"""
Calls the method for the answer the user clicked.
The method name is on_clicked_ANSWER where ANSWER is the key from the
clicked answer. See get_answer_options. If this method is not defined,
raises a NotImplementedError.
If the method returns True, then the success message is printed to the
user.
The method name is on_clicked_ANSWER where ANSWER is the key from
the clicked answer. See get_answer_options. Prints an error
message, if no valid answer was given. If this method is not
defined, nothing happens, else it is called and the success message
is printed to the user.
"""
method_name = 'on_clicked_%s' % self.get_answer()
method = getattr(self, method_name, None)
if method is None:
pass
try:
answer = self.get_answer()
except OpenSlidesError as error:
messages.error(self.request, error)
else:
method()
self.create_final_message()
method_name = 'on_clicked_%s' % answer
method = getattr(self, method_name, None)
if method is None:
pass
else:
method()
self.create_final_message()
def get_answer(self):
"""
Returns the key of the clicked answer.
Raises ImproperlyConfigured, if the answer is not one of
get_answer_options.
Raises OpenSlidesError if the answer is not one of get_answer_options.
"""
for option_key, option_name in self.get_answer_options():
if option_key in self.request.POST:
return option_key
raise ImproperlyConfigured('%s is not a valid answer' % self.request.POST)
answer = option_key
break
else:
raise OpenSlidesError(ugettext_lazy('You did not send a valid answer.'))
return answer
def get_final_message(self):
"""
@ -493,17 +500,25 @@ class DeleteView(SingleObjectMixin, QuestionView):
def get_redirect_url(self, **kwargs):
"""
Returns the url on which the delete dialog is shown and the url after
the deleten.
the deleting.
On GET-requests and on aborted POST-requests, redirect to the detail
On GET-requests and on aborted or failed POST-requests, redirects to the detail
view as default. The attributes question_url_name or question_url can
define other urls.
"""
if self.request.method == 'GET' or self.get_answer() == 'no':
url = self.get_url(self.question_url_name, self.question_url,
args=self.get_url_name_args())
if self.request.method == 'POST':
try:
answer = self.get_answer()
except OpenSlidesError:
answer = 'no'
if answer == 'no':
url = self.get_url(self.question_url_name, self.question_url,
args=self.get_url_name_args())
else:
url = self.get_url(self.success_url_name, self.success_url,
args=self.get_url_name_args())
else:
url = self.get_url(self.success_url_name, self.success_url,
url = self.get_url(self.question_url_name, self.question_url,
args=self.get_url_name_args())
return url

View File

@ -222,6 +222,13 @@ class ViewTest(TestCase):
query = Item.objects.filter(pk__in=[item1.pk, item2.pk])
self.assertFalse(query)
def test_delete_item_with_wrong_answer(self):
response = self.adminClient.post(
'/agenda/%s/del/' % self.item1.pk,
{'unknown_answer_aicipohc1Eeph2chaeng': 1})
self.assertRedirects(response, '/agenda/')
self.assertTrue(Item.objects.filter(pk=self.item1.pk).exists())
class ConfigTest(TestCase):
def setUp(self):