Skip to content

Commit 2967f16

Browse files
committed
Added tests for model controller
1 parent ab94ee0 commit 2967f16

File tree

10 files changed

+750
-80
lines changed

10 files changed

+750
-80
lines changed

ninja_extra/controllers/model/builder.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def generate_all_schema(self) -> None:
105105
self._config.model,
106106
name=f"{self._model_name}PatchSchema",
107107
fields=list(create_schema_fields),
108-
optional_fields="__all__",
108+
optional_fields=list(create_schema_fields),
109109
skip_registry=True,
110110
depth=self._config.schema_config.depth,
111111
)
@@ -169,7 +169,7 @@ def _register_update_endpoint(self) -> None:
169169

170170
update_item = ModelEndpointFactory.update(
171171
path=_path,
172-
lookup_field=self._model_pk_name,
172+
lookup_param=self._model_pk_name,
173173
schema_in=self._update_schema, # type: ignore[arg-type]
174174
schema_out=self._retrieve_schema, # type: ignore[arg-type]
175175
url_name=f"{self._model_pk_name}-put",
@@ -188,7 +188,7 @@ def _register_patch_endpoint(self) -> None:
188188

189189
patch_item = ModelEndpointFactory.patch(
190190
path=_path,
191-
lookup_field=self._model_pk_name,
191+
lookup_param=self._model_pk_name,
192192
schema_out=self._retrieve_schema, # type: ignore[arg-type]
193193
schema_in=self._patch_schema, # type: ignore[arg-type]
194194
url_name=f"{self._model_pk_name}-patch",
@@ -206,7 +206,7 @@ def _register_find_one_endpoint(self) -> None:
206206

207207
get_item = ModelEndpointFactory.retrieve(
208208
path=_path,
209-
lookup_field=self._model_pk_name,
209+
lookup_param=self._model_pk_name,
210210
schema_out=self._retrieve_schema, # type: ignore[arg-type]
211211
url_name=f"{self._model_pk_name}-get-item",
212212
description=f"""Get {self._model_name} item by {self._model_pk_name}""",
@@ -216,16 +216,21 @@ def _register_find_one_endpoint(self) -> None:
216216
self._add_to_controller(get_item)
217217

218218
def _register_list_endpoint(self) -> None:
219-
paginate_kwargs: t.Dict[str, t.Any] = {}
220-
221-
if self._config.pagination.paginate_by:
222-
paginate_kwargs.update(page_size=self._config.pagination.paginate_by)
219+
paginate_kwargs: t.Dict[str, t.Any] = {
220+
"pagination_class": None,
221+
"pagination_response_schema": None,
222+
}
223+
if self._config.pagination:
224+
paginate_kwargs.update(
225+
pagination_class=self._config.pagination.klass,
226+
pagination_response_schema=self._config.pagination.pagination_schema,
227+
)
228+
if self._config.pagination.paginator_kwargs:
229+
paginate_kwargs.update(self._config.pagination.paginator_kwargs)
223230

224231
list_items = ModelEndpointFactory.list(
225232
path="/",
226233
schema_out=self._retrieve_schema, # type: ignore[arg-type]
227-
pagination_class=self._config.pagination.klass,
228-
pagination_response_schema=self._config.pagination.pagination_schema,
229234
description=f"List {self._model_name} model items",
230235
url_name=f"{self._model_pk_name}-list",
231236
summary="List Items",
@@ -242,7 +247,7 @@ def _register_delete_endpoint(self) -> None:
242247

243248
delete_item = ModelEndpointFactory.delete(
244249
path=_path,
245-
lookup_field=self._model_pk_name,
250+
lookup_param=self._model_pk_name,
246251
url_name=f"{self._model_pk_name}-delete",
247252
description=f"""Delete {self._model_name} item""",
248253
summary="Delete an item",
@@ -254,7 +259,7 @@ def register_model_routes(self) -> None:
254259
for action in self._config.allowed_routes:
255260
action_registration = getattr(self, f"_register_{action}_endpoint", None)
256261

257-
if not action_registration:
262+
if not action_registration: # pragma: no cover
258263
raise Exception(
259264
f"Route `{action}` action in `class[{self._base_cls.__name__}]` "
260265
f"is not recognized as ModelController action"

ninja_extra/controllers/model/endpoints.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def create_item(
207207
**kwargs: t.Any,
208208
) -> t.Any:
209209
instance = (
210-
custom_handler(self, **kwargs)
210+
custom_handler(self, data, **kwargs)
211211
if custom_handler
212212
else self.service.create(data, **kwargs)
213213
)
@@ -220,7 +220,7 @@ def create_item(
220220
def update(
221221
cls,
222222
path: str,
223-
lookup_field: str,
223+
lookup_param: str,
224224
schema_in: t.Type[PydanticModel],
225225
schema_out: t.Type[PydanticModel],
226226
status_code: int = status.HTTP_200_OK,
@@ -270,7 +270,7 @@ def update_item(
270270
data: schema_in = Body(default=...), # type:ignore[valid-type]
271271
**kwargs: t.Any,
272272
) -> t.Any:
273-
pk = kwargs.pop(lookup_field)
273+
pk = kwargs.pop(lookup_param)
274274
obj = (
275275
object_getter(self, pk=pk, **kwargs)
276276
if object_getter
@@ -295,7 +295,7 @@ def update_item(
295295
def patch(
296296
cls,
297297
path: str,
298-
lookup_field: str,
298+
lookup_param: str,
299299
schema_in: t.Type[PydanticModel],
300300
schema_out: t.Type[PydanticModel],
301301
status_code: int = status.HTTP_200_OK,
@@ -324,7 +324,7 @@ def patch(
324324

325325
@route.patch(
326326
working_path,
327-
response={status_code: schema_in},
327+
response={status_code: schema_out},
328328
url_name=url_name,
329329
description=description,
330330
operation_id=operation_id,
@@ -342,10 +342,10 @@ def patch(
342342
@cls._path_resolver(path)
343343
def patch_item(
344344
self: "ModelControllerBase",
345-
data: schema_out = Body(default=...), # type:ignore[valid-type]
345+
data: schema_in = Body(default=...), # type:ignore[valid-type]
346346
**kwargs: t.Any,
347347
) -> t.Any:
348-
pk = kwargs.pop(lookup_field)
348+
pk = kwargs.pop(lookup_param)
349349
obj = (
350350
object_getter(self, pk=pk, **kwargs)
351351
if object_getter
@@ -368,7 +368,7 @@ def patch_item(
368368
def retrieve(
369369
cls,
370370
path: str,
371-
lookup_field: str,
371+
lookup_param: str,
372372
schema_out: t.Type[PydanticModel],
373373
status_code: int = status.HTTP_200_OK,
374374
url_name: t.Optional[str] = None,
@@ -412,7 +412,7 @@ def retrieve(
412412
)
413413
@cls._path_resolver(path)
414414
def get_item(self: "ModelControllerBase", **kwargs: t.Any) -> t.Any:
415-
pk = kwargs.pop(lookup_field)
415+
pk = kwargs.pop(lookup_param)
416416
obj = (
417417
object_getter(self, pk=pk, **kwargs)
418418
if object_getter
@@ -515,7 +515,7 @@ def list_items(self: "ModelControllerBase", **kwargs: t.Any) -> t.Any:
515515
def delete(
516516
cls,
517517
path: str,
518-
lookup_field: str,
518+
lookup_param: str,
519519
status_code: int = status.HTTP_204_NO_CONTENT,
520520
url_name: t.Optional[str] = None,
521521
description: t.Optional[str] = None,
@@ -559,7 +559,7 @@ def delete(
559559
)
560560
@cls._path_resolver(path)
561561
def delete_item(self: "ModelControllerBase", **kwargs: t.Any) -> t.Any:
562-
pk = kwargs.pop(lookup_field)
562+
pk = kwargs.pop(lookup_param)
563563
obj = (
564564
object_getter(self, pk=pk, **kwargs)
565565
if object_getter

ninja_extra/controllers/model/schemas.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, List, Optional, Set, Type, Union
1+
from typing import Any, Generic, List, Optional, Set, Type, Union
22

33
from django.db.models import Model
44
from ninja.pagination import PaginationBase
@@ -10,22 +10,26 @@
1010

1111
class ModelPagination(PydanticModel):
1212
klass: Type[PaginationBase] = PageNumberPaginationExtra
13-
paginate_by: Optional[int] = None
13+
paginator_kwargs: Optional[dict] = None
1414
pagination_schema: Type[PydanticModel] = PaginatedResponseSchema
1515

1616
@validator("klass", allow_reuse=True)
1717
def validate_klass(cls, value: Any) -> Any:
18-
if not issubclass(PaginationBase, value):
19-
raise ValueError(f"{value} is not of type `PaginationBase`")
20-
return value
18+
if isinstance(value, type) and issubclass(value, PaginationBase):
19+
return value
20+
raise ValueError(f"{value} is not of type `PaginationBase`")
2121

2222
@validator("pagination_schema", allow_reuse=True)
2323
def validate_schema(cls, value: Any) -> Any:
24-
if not issubclass(PydanticModel, value):
25-
raise ValueError(
26-
f"{value} is not a valid type. Please use a generic pydantic model."
27-
)
28-
return value
24+
if (
25+
isinstance(value, type)
26+
and issubclass(value, PydanticModel)
27+
and issubclass(value, Generic) # type:ignore[arg-type]
28+
):
29+
return value
30+
raise ValueError(
31+
f"{value} is not a valid type. Please use a generic pydantic model."
32+
)
2933

3034

3135
class ModelSchemaConfig(PydanticModel):
@@ -55,7 +59,7 @@ class ModelConfig(PydanticModel):
5559
update_schema: Optional[Type[PydanticModel]] = None
5660
patch_schema: Optional[Type[PydanticModel]] = None
5761

58-
pagination: ModelPagination = Field(default=ModelPagination())
62+
pagination: Optional[ModelPagination] = Field(default=ModelPagination())
5963
model: Type[Model]
6064

6165
schema_config: ModelSchemaConfig = Field(default=ModelSchemaConfig(exclude=set()))
@@ -82,7 +86,6 @@ def validate_model(cls, value: Any) -> Any:
8286
allow_reuse=True,
8387
)
8488
def validate_schemas(cls, value: Any) -> Any:
85-
if value:
86-
if not issubclass(value, PydanticModel):
87-
raise ValueError(f"{value} is not a valid pydantic type.")
89+
if value and not issubclass(value, PydanticModel):
90+
raise ValueError(f"{value} is not a valid pydantic type.")
8891
return value

ninja_extra/schemas/response.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -66,49 +66,6 @@ class RouteParameter(Schema):
6666
openapi_extra: Optional[Dict[str, Any]]
6767

6868

69-
# class ModelControllerSchema:
70-
# dict: Callable
71-
# config: BaseModel.Config
72-
#
73-
# def perform_create(self, **kwargs: Any) -> Any:
74-
# data = self.dict(by_alias=True)
75-
# data.update(kwargs)
76-
# model = cast(Model, self.config.model)
77-
# try:
78-
# instance = model._default_manager.create(**data)
79-
# return instance
80-
# except TypeError:
81-
# tb = traceback.format_exc()
82-
# msg = (
83-
# "Got a `TypeError` when calling `%s.%s.perform_create()`. "
84-
# "This may be because you have a writable field on the "
85-
# "serializer class that is not a valid argument to "
86-
# "`%s.%s.create()`. You may need to make the field "
87-
# "read-only, or override the %s.perform_create() method to handle "
88-
# "this correctly.\nOriginal exception was:\n %s"
89-
# % (
90-
# model.__name__,
91-
# model._default_manager.name,
92-
# model.__name__,
93-
# model._default_manager.name,
94-
# self.__class__.__name__,
95-
# tb,
96-
# )
97-
# )
98-
# raise TypeError(msg)
99-
#
100-
# def perform_update(self, instance: Model, **kwargs: Any) -> Any:
101-
# data = self.dict(exclude_none=True)
102-
# data.update(kwargs)
103-
# for attr, value in data.items():
104-
# setattr(instance, attr, value)
105-
# instance.save()
106-
# return instance
107-
#
108-
# def perform_patch(self, instance: Model, **kwargs: Any) -> Any:
109-
# return self.perform_update(instance=instance, **kwargs)
110-
111-
11269
def __getattr__(name: str) -> Any: # pragma: no cover
11370
if name in [
11471
"IdSchema",

tests/test_model_controller/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)