44 Any ,
55 Callable ,
66 Dict ,
7- Iterator ,
7+ Iterable ,
88 List ,
99 Optional ,
1010 Type ,
11+ Union ,
1112 cast ,
1213 no_type_check ,
1314)
1415
16+ from django .db .models import Model , QuerySet
17+ from django .http import HttpResponse
1518from injector import inject , is_decorated_with_inject
1619from ninja import NinjaAPI
1720from ninja .constants import NOT_SET
1821from ninja .operation import Operation
1922from ninja .security .base import AuthBase
2023from ninja .types import DictStrAny
2124
22- from ninja_extra .exceptions import PermissionDenied
25+ from ninja_extra .exceptions import APIException , NotFound , PermissionDenied
2326from ninja_extra .operation import PathView
2427from ninja_extra .permissions import AllowAny , BasePermission
25- from ninja_extra .shortcuts import fail_silently
28+ from ninja_extra .shortcuts import (
29+ fail_silently ,
30+ get_object_or_exception ,
31+ get_object_or_none ,
32+ )
2633from ninja_extra .types import PermissionType
2734
28- from .response import ControllerResponse , Detail , Id , Ok
35+ from .response import Detail , Id , Ok
2936from .route .route_functions import RouteFunction
3037from .router import ControllerRouter
3138
@@ -171,7 +178,7 @@ def add_api_operation(
171178 return operation
172179
173180 @classmethod
174- def get_route_functions (cls ) -> Iterator [RouteFunction ]:
181+ def get_route_functions (cls ) -> Iterable [RouteFunction ]:
175182 for method in cls .__dict__ .values ():
176183 if isinstance (method , RouteFunction ):
177184 yield method
@@ -181,7 +188,28 @@ def permission_denied(cls, permission: BasePermission) -> None:
181188 message = getattr (permission , "message" , None )
182189 raise PermissionDenied (message )
183190
184- def get_permissions (self ) -> Iterator [BasePermission ]:
191+ def get_object_or_exception (
192+ self ,
193+ klass : Union [Type [Model ], QuerySet ],
194+ error_message : str = None ,
195+ exception : Type [APIException ] = NotFound ,
196+ ** kwargs : Any ,
197+ ) -> Any :
198+ obj = get_object_or_exception (
199+ klass = klass , error_message = error_message , exception = exception , ** kwargs
200+ )
201+ self .check_object_permissions (obj )
202+ return obj
203+
204+ def get_object_or_none (
205+ self , klass : Union [Type [Model ], QuerySet ], ** kwargs : Any
206+ ) -> Optional [Any ]:
207+ obj = get_object_or_none (klass = klass , ** kwargs )
208+ if obj :
209+ self .check_object_permissions (obj )
210+ return obj
211+
212+ def _get_permissions (self ) -> Iterable [BasePermission ]:
185213 """
186214 Instantiates and returns the list of permissions that this view requires.
187215 """
@@ -197,7 +225,7 @@ def check_permissions(self) -> None:
197225 Check if the request should be permitted.
198226 Raises an appropriate exception if the request is not permitted.
199227 """
200- for permission in self .get_permissions ():
228+ for permission in self ._get_permissions ():
201229 if (
202230 self .context
203231 and self .context .request
@@ -207,12 +235,12 @@ def check_permissions(self) -> None:
207235 ):
208236 self .permission_denied (permission )
209237
210- def check_object_permissions (self , obj : Any ) -> None :
238+ def check_object_permissions (self , obj : Union [ Any , Model ] ) -> None :
211239 """
212240 Check if the request should be permitted for a given object.
213241 Raises an appropriate exception if the request is not permitted.
214242 """
215- for permission in self .get_permissions ():
243+ for permission in self ._get_permissions ():
216244 if (
217245 self .context
218246 and self .context .request
@@ -222,7 +250,11 @@ def check_object_permissions(self, obj: Any) -> None:
222250 ):
223251 self .permission_denied (permission )
224252
225- def create_response (
226- self , message : Any , status_code : int = 200
227- ) -> ControllerResponse :
228- return self .Detail (message = message , status_code = status_code )
253+ def create_response (self , message : Any , status_code : int = 200 ) -> HttpResponse :
254+ response = self .Detail (message = message , status_code = status_code )
255+ assert self .context and self .context .request and self .api
256+ return self .api .create_response (
257+ request = self .context .request ,
258+ data = response .convert_to_schema ().dict (),
259+ status = response .status_code ,
260+ )
0 commit comments