From e9a0b1cc9dd6bc6b96ac7a3daea0edeae4052963 Mon Sep 17 00:00:00 2001 From: Peyman Karimi Date: Fri, 18 Mar 2022 12:26:32 +0100 Subject: [PATCH 1/3] NEW: request paramenter + custom response added. --- README.md | 17 +++++++++++++++++ djangorestframework_fsm/viewset_mixins.py | 13 +++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c175d22..bae6b31 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,23 @@ class ArticleViewSet( save_after_transition = False ``` +### Access to `request` inside transitions + +If `request` parameter is defined as one of transition callable parameters, then request object will be passed to the transition callable. + +### Customized response + +To have customied response, add transition name to `return_result_of` attribute and return your desired response from your transittion callable. + +```python +class ArticleViewSet( + get_drf_fsm_mixin(Article), + viewsets.ModelViewSet, +): + queryset = Article.objects.all() + return_result_of = ["foo_transition"] +``` + ### Permissions Custom permissions should be defined on the model's transition method diff --git a/djangorestframework_fsm/viewset_mixins.py b/djangorestframework_fsm/viewset_mixins.py index 964db37..380de46 100644 --- a/djangorestframework_fsm/viewset_mixins.py +++ b/djangorestframework_fsm/viewset_mixins.py @@ -26,10 +26,15 @@ def transition_action(self, request, *args, **kwargs): else: transition_kwargs = {} - if 'by' in inspect.signature(transition_method).parameters.keys() and 'by' not in transition_kwargs: + signature = inspect.signature(transition_method) + + if 'by' in signature.parameters and 'by' not in transition_kwargs: transition_kwargs['by'] = self.request.user - transition_method(**transition_kwargs) + if 'request' in signature.parameters and 'request' not in transition_kwargs: + transition_kwargs['request'] = self.request + + result = transition_method(**transition_kwargs) if self.save_after_transition: instance.save() @@ -39,6 +44,9 @@ def transition_action(self, request, *args, **kwargs): # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} + if transition_name in self.return_result_of: + return Response(result) + serializer = self.get_serializer(instance) return Response(serializer.data) @@ -59,6 +67,7 @@ def get_drf_fsm_mixin(Model, fieldname='state'): class Mixin(object): save_after_transition = True + return_result_of = [] @action(methods=['GET'], detail=True, url_name='possible-transitions', url_path='possible-transitions') def possible_transitions(self, request, *args, **kwargs): From 3a41c6f00d0c6292f6490b4c180844254dad4550 Mon Sep 17 00:00:00 2001 From: Peyman Karimi Date: Tue, 12 Apr 2022 11:09:54 +0200 Subject: [PATCH 2/3] NEW: Excluded transitions added. --- README.md | 12 ++++++++++++ djangorestframework_fsm/viewset_mixins.py | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bae6b31..86fd3ae 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,18 @@ class ArticleViewSet( If `request` parameter is defined as one of transition callable parameters, then request object will be passed to the transition callable. +### Excluded transitions +To exclude some transitions to be exposed, add transition name to `excluded_transitions` attribute. + +```python +class ArticleViewSet( + get_drf_fsm_mixin(Article), + viewsets.ModelViewSet, +): + queryset = Article.objects.all() + excluded_transitions = ["foo_transition"] +``` + ### Customized response To have customied response, add transition name to `return_result_of` attribute and return your desired response from your transittion callable. diff --git a/djangorestframework_fsm/viewset_mixins.py b/djangorestframework_fsm/viewset_mixins.py index 380de46..5886b0c 100644 --- a/djangorestframework_fsm/viewset_mixins.py +++ b/djangorestframework_fsm/viewset_mixins.py @@ -21,6 +21,9 @@ def transition_action(self, request, *args, **kwargs): if not has_transition_perm(transition_method, self.request.user): raise exceptions.PermissionDenied + if transition_name in self.excluded_transitions: + raise exceptions.PermissionDenied + if hasattr(self, 'get_{0}_kwargs'.format(transition_name)): transition_kwargs = getattr(self, 'get_{0}_kwargs'.format(transition_name))() else: @@ -68,6 +71,7 @@ def get_drf_fsm_mixin(Model, fieldname='state'): class Mixin(object): save_after_transition = True return_result_of = [] + excluded_transitions = [] @action(methods=['GET'], detail=True, url_name='possible-transitions', url_path='possible-transitions') def possible_transitions(self, request, *args, **kwargs): @@ -77,7 +81,7 @@ def possible_transitions(self, request, *args, **kwargs): 'transitions': [ trans.name.replace('_', '-') for trans in getattr(instance, 'get_available_{}_transitions'.format(fieldname))() - if trans.has_perm(instance, request.user) + if trans.has_perm(instance, request.user) and (trans.name not in self.excluded_transitions) ] }, ) From 3d9ce712f28f3ef9a1e62bb7376d5ddcb5cc6812 Mon Sep 17 00:00:00 2001 From: Peyman Karimi Date: Mon, 30 May 2022 16:49:18 +0200 Subject: [PATCH 3/3] NEW: Public transitions added. --- README.md | 12 ++++++++++++ djangorestframework_fsm/viewset_mixins.py | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 86fd3ae..14dd126 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,18 @@ class ArticleViewSet( excluded_transitions = ["foo_transition"] ``` +### Public transitions +To have whitlisted/public transitions to be exposed, add transition name to `public_transitions` attribute. + +```python +class ArticleViewSet( + get_drf_fsm_mixin(Article), + viewsets.ModelViewSet, +): + queryset = Article.objects.all() + public_transitions = ["public_transition"] +``` + ### Customized response To have customied response, add transition name to `return_result_of` attribute and return your desired response from your transittion callable. diff --git a/djangorestframework_fsm/viewset_mixins.py b/djangorestframework_fsm/viewset_mixins.py index 5886b0c..73b1336 100644 --- a/djangorestframework_fsm/viewset_mixins.py +++ b/djangorestframework_fsm/viewset_mixins.py @@ -24,6 +24,9 @@ def transition_action(self, request, *args, **kwargs): if transition_name in self.excluded_transitions: raise exceptions.PermissionDenied + if self.public_transitions and (transition_name not in self.public_transitions): + raise exceptions.PermissionDenied + if hasattr(self, 'get_{0}_kwargs'.format(transition_name)): transition_kwargs = getattr(self, 'get_{0}_kwargs'.format(transition_name))() else: @@ -72,6 +75,7 @@ class Mixin(object): save_after_transition = True return_result_of = [] excluded_transitions = [] + public_transitions = [] @action(methods=['GET'], detail=True, url_name='possible-transitions', url_path='possible-transitions') def possible_transitions(self, request, *args, **kwargs): @@ -81,7 +85,7 @@ def possible_transitions(self, request, *args, **kwargs): 'transitions': [ trans.name.replace('_', '-') for trans in getattr(instance, 'get_available_{}_transitions'.format(fieldname))() - if trans.has_perm(instance, request.user) and (trans.name not in self.excluded_transitions) + if trans.has_perm(instance, request.user) and (trans.name not in self.excluded_transitions) and (trans.name in (self.public_transitions or [trans.name])) ] }, )