From 69c13371ca87e03d9c31f578128aba9a465491e6 Mon Sep 17 00:00:00 2001 From: Benjamin Balder Bach Date: Fri, 13 Jun 2025 19:32:21 +0200 Subject: [PATCH 1/3] Option to disable exception handling I would prefer that it's disabled by default, but I leave that to the maintainer :) --- django_modal_actions/mixins.py | 69 +++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/django_modal_actions/mixins.py b/django_modal_actions/mixins.py index 8567299..944b83e 100644 --- a/django_modal_actions/mixins.py +++ b/django_modal_actions/mixins.py @@ -15,6 +15,11 @@ class ModalActionMixin: change_form_template: str = "admin/django_modal_actions/change_form.html" change_list_template: str = "admin/django_modal_actions/change_list.html" + # This option returns exception names values directly in the browser. + # If you want exceptions to occur server-side, switch to False. + # TODO: Consider to disable this as default + modal_action_exception_handling = True + def get_urls(self) -> List[path]: urls: List[path] = super().get_urls() custom_urls = [ @@ -96,35 +101,47 @@ def get_modal_content( def execute_modal_action( self, request: HttpRequest, action: str, object_id: Optional[str] = None + ) -> JsonResponse: + if self.modal_action_exception_handling: + try: + return self.do_execute_modal_action( + self, request: HttpRequest, action: str, object_id: Optional[str] = None + ) + except Exception as e: + return JsonResponse({"success": False, "errors": {"__all__": [str(e)]}}) + else: + return self.do_execute_modal_action( + self, request: HttpRequest, action: str, object_id: Optional[str] = None + ) + + def do_execute_modal_action( + self, request: HttpRequest, action: str, object_id: Optional[str] = None ) -> JsonResponse: action_func: Callable = getattr(self, action) form_class: Optional[Type] = getattr(action_func, "form_class", None) - try: - if object_id: - obj = self.get_object(request, object_id) - queryset_or_obj = obj - else: - selected_ids = json.loads(request.POST.get("selected_ids", "[]")) - queryset_or_obj = self.model.objects.filter(pk__in=selected_ids) - - if not self.has_action_permission( - request, action, obj if object_id else None - ): - return JsonResponse( - {"success": False, "errors": {"__all__": ["Permission denied"]}} - ) - if form_class: - form = form_class(request.POST, request.FILES) - if form.is_valid(): - response = action_func(request, queryset_or_obj, form.cleaned_data) - self.message_user(request, str(response), messages.SUCCESS) - return JsonResponse({"success": True}) - return JsonResponse({"success": False, "errors": form.errors}) - response = action_func(request, queryset_or_obj) - self.message_user(request, str(response), messages.SUCCESS) - return JsonResponse({"success": True}) - except Exception as e: - return JsonResponse({"success": False, "errors": {"__all__": [str(e)]}}) + if object_id: + obj = self.get_object(request, object_id) + queryset_or_obj = obj + else: + selected_ids = json.loads(request.POST.get("selected_ids", "[]")) + queryset_or_obj = self.model.objects.filter(pk__in=selected_ids) + + if not self.has_action_permission( + request, action, obj if object_id else None + ): + return JsonResponse( + {"success": False, "errors": {"__all__": ["Permission denied"]}} + ) + if form_class: + form = form_class(request.POST, request.FILES) + if form.is_valid(): + response = action_func(request, queryset_or_obj, form.cleaned_data) + self.message_user(request, str(response), messages.SUCCESS) + return JsonResponse({"success": True}) + return JsonResponse({"success": False, "errors": form.errors}) + response = action_func(request, queryset_or_obj) + self.message_user(request, str(response), messages.SUCCESS) + return JsonResponse({"success": True}) def get_modal_action_buttons(self, obj=None) -> str: buttons: List[str] = [] From ac0e3ed620d0ca6d67b4bdd5525b89fc81546cb3 Mon Sep 17 00:00:00 2001 From: Benjamin Balder Bach Date: Fri, 13 Jun 2025 23:14:29 +0200 Subject: [PATCH 2/3] Fix copy-paste errors --- django_modal_actions/mixins.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/django_modal_actions/mixins.py b/django_modal_actions/mixins.py index 944b83e..ad1aa86 100644 --- a/django_modal_actions/mixins.py +++ b/django_modal_actions/mixins.py @@ -104,15 +104,11 @@ def execute_modal_action( ) -> JsonResponse: if self.modal_action_exception_handling: try: - return self.do_execute_modal_action( - self, request: HttpRequest, action: str, object_id: Optional[str] = None - ) + return self.do_execute_modal_action(request, action, object_id=object_id) except Exception as e: return JsonResponse({"success": False, "errors": {"__all__": [str(e)]}}) else: - return self.do_execute_modal_action( - self, request: HttpRequest, action: str, object_id: Optional[str] = None - ) + return self.do_execute_modal_action(request, action, object_id=object_id) def do_execute_modal_action( self, request: HttpRequest, action: str, object_id: Optional[str] = None From 54d7fe60f974c3334595a2f802aa3601b09b0a12 Mon Sep 17 00:00:00 2001 From: bbb Date: Fri, 13 Jun 2025 23:16:16 +0200 Subject: [PATCH 3/3] lint --- django_modal_actions/mixins.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/django_modal_actions/mixins.py b/django_modal_actions/mixins.py index ad1aa86..a2754c5 100644 --- a/django_modal_actions/mixins.py +++ b/django_modal_actions/mixins.py @@ -104,12 +104,14 @@ def execute_modal_action( ) -> JsonResponse: if self.modal_action_exception_handling: try: - return self.do_execute_modal_action(request, action, object_id=object_id) + return self.do_execute_modal_action( + request, action, object_id=object_id + ) except Exception as e: return JsonResponse({"success": False, "errors": {"__all__": [str(e)]}}) else: return self.do_execute_modal_action(request, action, object_id=object_id) - + def do_execute_modal_action( self, request: HttpRequest, action: str, object_id: Optional[str] = None ) -> JsonResponse: @@ -122,9 +124,7 @@ def do_execute_modal_action( selected_ids = json.loads(request.POST.get("selected_ids", "[]")) queryset_or_obj = self.model.objects.filter(pk__in=selected_ids) - if not self.has_action_permission( - request, action, obj if object_id else None - ): + if not self.has_action_permission(request, action, obj if object_id else None): return JsonResponse( {"success": False, "errors": {"__all__": ["Permission denied"]}} )