Skip to content

Commit 796cc0c

Browse files
authored
Merge pull request #130 from eadwinCode/pagination_refactor
fix(pagination): Code refactor
2 parents bca5ef7 + d693541 commit 796cc0c

File tree

12 files changed

+414
-288
lines changed

12 files changed

+414
-288
lines changed

ninja_extra/main.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
from importlib import import_module
2-
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union
2+
from typing import (
3+
Any,
4+
Callable,
5+
Dict,
6+
List,
7+
Optional,
8+
Sequence,
9+
Tuple,
10+
Type,
11+
Union,
12+
cast,
13+
)
314

415
from django.core.exceptions import ImproperlyConfigured
516
from django.http import HttpRequest, HttpResponse
617
from django.urls import URLPattern, URLResolver
7-
from django.utils.module_loading import module_has_submodule
18+
from django.utils.module_loading import import_string, module_has_submodule
819
from ninja import NinjaAPI
920
from ninja.constants import NOT_SET
1021
from ninja.openapi.docs import DocsBase, Swagger
@@ -94,9 +105,14 @@ def urls(self) -> Tuple[List[Union[URLResolver, URLPattern]], str, str]:
94105
)
95106

96107
def register_controllers(
97-
self, *controllers: Union[Type[ControllerBase], Type]
108+
self, *controllers: Union[Type[ControllerBase], Type, str]
98109
) -> None:
99110
for controller in controllers:
111+
if isinstance(controller, str):
112+
controller = cast(
113+
Union[Type[ControllerBase], Type], import_string(controller)
114+
)
115+
100116
if not issubclass(controller, ControllerBase):
101117
raise ImproperlyConfigured(
102118
f"{controller.__class__.__name__} class is not a controller"

ninja_extra/ordering.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
from asgiref.sync import sync_to_async
2020
from django.db.models import QuerySet
21-
from ninja import Field, Query, Schema
21+
from django.http import HttpRequest
22+
from ninja import Field, P, Query, Schema
2223
from ninja.constants import NOT_SET
2324
from ninja.signature import is_async
2425
from pydantic import BaseModel
@@ -65,14 +66,24 @@ def __init__(
6566
) -> None:
6667
super().__init__(pass_parameter=pass_parameter)
6768
self.ordering_fields = ordering_fields or "__all__"
69+
self.Input = self.create_input(ordering_fields) # type:ignore
70+
71+
def create_input(self, ordering_fields: Optional[List[str]]) -> Type[Input]:
72+
if ordering_fields:
73+
74+
class DynamicInput(Ordering.Input):
75+
ordering: Query[Optional[str], P(default=",".join(ordering_fields))] # type:ignore[type-arg,valid-type]
76+
77+
return DynamicInput
78+
return Ordering.Input
6879

6980
def ordering_queryset(
7081
self, items: Union[QuerySet, List], ordering_input: Input
7182
) -> Union[QuerySet, List]:
72-
ordering = self.get_ordering(items, ordering_input.ordering)
73-
if ordering:
83+
ordering_ = self.get_ordering(items, ordering_input.ordering)
84+
if ordering_:
7485
if isinstance(items, QuerySet): # type:ignore
75-
return items.order_by(*ordering)
86+
return items.order_by(*ordering_)
7687
elif isinstance(items, list) and items:
7788

7889
def multisort(xs: List, specs: List[Tuple[str, bool]]) -> List:
@@ -85,7 +96,7 @@ def multisort(xs: List, specs: List[Tuple[str, bool]]) -> List:
8596
items,
8697
[
8798
(o[int(o.startswith("-")) :], o.startswith("-"))
88-
for o in ordering
99+
for o in ordering_
89100
],
90101
)
91102
return items
@@ -201,49 +212,51 @@ def __init__(
201212
self.view_func = view_func
202213

203214
orderator_view = self.get_view_function()
204-
_ninja_contribute_args: List[Tuple] = getattr(
205-
self.view_func, "_ninja_contribute_args", []
206-
)
207-
orderator_view._ninja_contribute_args = ( # type:ignore[attr-defined]
208-
_ninja_contribute_args
209-
)
215+
self.as_view = wraps(view_func)(orderator_view)
210216
add_ninja_contribute_args(
211-
orderator_view,
217+
self.as_view,
212218
(
213219
self.orderator_kwargs_name,
214220
self.orderator.Input,
215221
self.orderator.InputSource,
216222
),
217223
)
218224
orderator_view.orderator_operation = self # type:ignore[attr-defined]
219-
self.as_view = wraps(view_func)(orderator_view)
220225

221226
@property
222227
def view_func_has_kwargs(self) -> bool: # pragma: no cover
223228
return self.orderator.pass_parameter is not None
224229

225230
def get_view_function(self) -> Callable:
226-
def as_view(controller: "ControllerBase", *args: Any, **kw: Any) -> Any:
231+
def as_view(
232+
request_or_controller: Union["ControllerBase", HttpRequest],
233+
*args: Any,
234+
**kw: Any,
235+
) -> Any:
227236
func_kwargs = dict(**kw)
228237
ordering_params = func_kwargs.pop(self.orderator_kwargs_name)
229238
if self.orderator.pass_parameter:
230239
func_kwargs[self.orderator.pass_parameter] = ordering_params
231240

232-
items = self.view_func(controller, *args, **func_kwargs)
241+
items = self.view_func(request_or_controller, *args, **func_kwargs)
233242
return self.orderator.ordering_queryset(items, ordering_params)
234243

235244
return as_view
236245

237246

238247
class AsyncOrderatorOperation(OrderatorOperation):
239248
def get_view_function(self) -> Callable:
240-
async def as_view(controller: "ControllerBase", *args: Any, **kw: Any) -> Any:
249+
async def as_view(
250+
request_or_controller: Union["ControllerBase", HttpRequest],
251+
*args: Any,
252+
**kw: Any,
253+
) -> Any:
241254
func_kwargs = dict(**kw)
242255
ordering_params = func_kwargs.pop(self.orderator_kwargs_name)
243256
if self.orderator.pass_parameter:
244257
func_kwargs[self.orderator.pass_parameter] = ordering_params
245258

246-
items = await self.view_func(controller, *args, **func_kwargs)
259+
items = await self.view_func(request_or_controller, *args, **func_kwargs)
247260
ordering_queryset = cast(
248261
Callable, sync_to_async(self.orderator.ordering_queryset)
249262
)

0 commit comments

Comments
 (0)