Merge pull request #956 from normanjaeckel/Fix940
Add error message if a invalid answer was send via POST to a QuestionVie...
This commit is contained in:
commit
055f73a995
@ -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).
|
||||||
|
@ -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(
|
self.object.delete(with_children=False)
|
||||||
request,
|
|
||||||
_("Item %s and his children were successfully deleted.")
|
def on_clicked_all(self):
|
||||||
% html_strong(self.object))
|
"""
|
||||||
elif self.get_answer() == 'yes':
|
Deletes the item and its children.
|
||||||
self.object.delete(with_children=False)
|
"""
|
||||||
messages.success(
|
self.object.delete(with_children=True)
|
||||||
request,
|
|
||||||
_("Item %s was successfully deleted.")
|
def get_final_message(self):
|
||||||
% html_strong(self.object))
|
"""
|
||||||
|
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):
|
||||||
|
@ -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,32 +401,38 @@ 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:
|
||||||
method = getattr(self, method_name, None)
|
answer = self.get_answer()
|
||||||
if method is None:
|
except OpenSlidesError as error:
|
||||||
pass
|
messages.error(self.request, error)
|
||||||
else:
|
else:
|
||||||
method()
|
method_name = 'on_clicked_%s' % answer
|
||||||
self.create_final_message()
|
method = getattr(self, method_name, None)
|
||||||
|
if method is None:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
method()
|
||||||
|
self.create_final_message()
|
||||||
|
|
||||||
def get_answer(self):
|
def get_answer(self):
|
||||||
"""
|
"""
|
||||||
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,17 +500,25 @@ 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':
|
||||||
url = self.get_url(self.question_url_name, self.question_url,
|
try:
|
||||||
args=self.get_url_name_args())
|
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:
|
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())
|
args=self.get_url_name_args())
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user