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). - Full text search integration (with Haystack and Whoosh).
- New start script with new command line options. - New start script with new command line options.
- Fixed keyerror on user settings view. - Fixed keyerror on user settings view.
- New message on success of many actions like creating or editing objects. - 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. - Added feature to config app to return the default value for a key.
- Cleaned up OpenSlides utils views. - Cleaned up OpenSlides utils views.
- Used flake8 instead of pep8 for style check, sort all import statements with isort. - Used flake8 instead of pep8 for style check, sort all import statements with isort.
- Added Portuguese translation (Thanks to Marco A.G.Pinto). - Added Portuguese translation (Thanks to Marco A.G.Pinto).

View File

@ -270,20 +270,29 @@ class ItemDelete(DeleteView):
self.item_delete_answer_options = options self.item_delete_answer_options = options
return options return options
def pre_post_redirect(self, request, *args, **kwargs): def on_clicked_yes(self):
# TODO: rewrite this method with on_case_all and on_case_yes """
if self.get_answer() == 'all': Deletes the item but not its children.
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) self.object.delete(with_children=False)
messages.success(
request, def on_clicked_all(self):
_("Item %s was successfully deleted.") """
% html_strong(self.object)) 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): 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.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, Spacer from reportlab.platypus import SimpleDocTemplate, Spacer
from .exceptions import OpenSlidesError
from .pdf import firstPage, laterPages from .pdf import firstPage, laterPages
from .signals import template_manipulation from .signals import template_manipulation
from .utils import html_strong from .utils import html_strong
@ -400,14 +401,18 @@ class QuestionView(RedirectView):
""" """
Calls the method for the answer the user clicked. Calls the method for the answer the user clicked.
The method name is on_clicked_ANSWER where ANSWER is the key from the The method name is on_clicked_ANSWER where ANSWER is the key from
clicked answer. See get_answer_options. If this method is not defined, the clicked answer. See get_answer_options. Prints an error
raises a NotImplementedError. message, if no valid answer was given. If this method is not
defined, nothing happens, else it is called and the success message
If the method returns True, then the success message is printed to the is printed to the user.
user.
""" """
method_name = 'on_clicked_%s' % self.get_answer() try:
answer = self.get_answer()
except OpenSlidesError as error:
messages.error(self.request, error)
else:
method_name = 'on_clicked_%s' % answer
method = getattr(self, method_name, None) method = getattr(self, method_name, None)
if method is None: if method is None:
pass pass
@ -419,13 +424,15 @@ class QuestionView(RedirectView):
""" """
Returns the key of the clicked answer. Returns the key of the clicked answer.
Raises ImproperlyConfigured, if the answer is not one of Raises OpenSlidesError if the answer is not one of get_answer_options.
get_answer_options.
""" """
for option_key, option_name in self.get_answer_options(): for option_key, option_name in self.get_answer_options():
if option_key in self.request.POST: if option_key in self.request.POST:
return option_key answer = option_key
raise ImproperlyConfigured('%s is not a valid answer' % self.request.POST) break
else:
raise OpenSlidesError(ugettext_lazy('You did not send a valid answer.'))
return answer
def get_final_message(self): def get_final_message(self):
""" """
@ -493,18 +500,26 @@ class DeleteView(SingleObjectMixin, QuestionView):
def get_redirect_url(self, **kwargs): def get_redirect_url(self, **kwargs):
""" """
Returns the url on which the delete dialog is shown and the url after 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 view as default. The attributes question_url_name or question_url can
define other urls. define other urls.
""" """
if self.request.method == 'GET' or self.get_answer() == 'no': 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, url = self.get_url(self.question_url_name, self.question_url,
args=self.get_url_name_args()) args=self.get_url_name_args())
else: else:
url = self.get_url(self.success_url_name, self.success_url, url = self.get_url(self.success_url_name, self.success_url,
args=self.get_url_name_args()) args=self.get_url_name_args())
else:
url = self.get_url(self.question_url_name, self.question_url,
args=self.get_url_name_args())
return url return url
def get_question_message(self): def get_question_message(self):

View File

@ -222,6 +222,13 @@ class ViewTest(TestCase):
query = Item.objects.filter(pk__in=[item1.pk, item2.pk]) query = Item.objects.filter(pk__in=[item1.pk, item2.pk])
self.assertFalse(query) 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): class ConfigTest(TestCase):
def setUp(self): def setUp(self):