django-ninja-aio-crud 2.3.2__py3-none-any.whl → 2.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_ninja_aio_crud-2.3.2.dist-info → django_ninja_aio_crud-2.5.0.dist-info}/METADATA +31 -6
- {django_ninja_aio_crud-2.3.2.dist-info → django_ninja_aio_crud-2.5.0.dist-info}/RECORD +10 -8
- ninja_aio/__init__.py +1 -1
- ninja_aio/helpers/query.py +2 -2
- ninja_aio/models/__init__.py +4 -0
- ninja_aio/models/serializers.py +888 -0
- ninja_aio/{models.py → models/utils.py} +75 -670
- ninja_aio/views/api.py +44 -19
- {django_ninja_aio_crud-2.3.2.dist-info → django_ninja_aio_crud-2.5.0.dist-info}/WHEEL +0 -0
- {django_ninja_aio_crud-2.3.2.dist-info → django_ninja_aio_crud-2.5.0.dist-info}/licenses/LICENSE +0 -0
ninja_aio/views/api.py
CHANGED
|
@@ -17,7 +17,8 @@ from ninja_aio.schemas import (
|
|
|
17
17
|
)
|
|
18
18
|
from ninja_aio.helpers.api import ManyToManyAPI
|
|
19
19
|
from ninja_aio.types import ModelSerializerMeta, VIEW_TYPES
|
|
20
|
-
from ninja_aio.decorators import unique_view, decorate_view
|
|
20
|
+
from ninja_aio.decorators import unique_view, decorate_view, aatomic
|
|
21
|
+
from ninja_aio.models import serializers
|
|
21
22
|
|
|
22
23
|
ERROR_CODES = frozenset({400, 401, 404})
|
|
23
24
|
|
|
@@ -221,6 +222,7 @@ class APIViewSet(API):
|
|
|
221
222
|
"""
|
|
222
223
|
|
|
223
224
|
model: ModelSerializer | Model
|
|
225
|
+
serializer_class: serializers.Serializer | None = None
|
|
224
226
|
schema_in: Schema | None = None
|
|
225
227
|
schema_out: Schema | None = None
|
|
226
228
|
schema_update: Schema | None = None
|
|
@@ -239,6 +241,8 @@ class APIViewSet(API):
|
|
|
239
241
|
m2m_relations: list[M2MRelationSchema] = []
|
|
240
242
|
m2m_auth: list | None = NOT_SET
|
|
241
243
|
extra_decorators: DecoratorsSchema = DecoratorsSchema()
|
|
244
|
+
model_verbose_name: str = ""
|
|
245
|
+
model_verbose_name_plural: str = ""
|
|
242
246
|
|
|
243
247
|
def __init__(
|
|
244
248
|
self,
|
|
@@ -251,14 +255,20 @@ class APIViewSet(API):
|
|
|
251
255
|
self.error_codes = ERROR_CODES
|
|
252
256
|
self.model = model or self.model
|
|
253
257
|
self.model_util = (
|
|
254
|
-
ModelUtil(self.model)
|
|
258
|
+
ModelUtil(self.model, serializer_class=self.serializer_class)
|
|
255
259
|
if not isinstance(self.model, ModelSerializerMeta)
|
|
256
260
|
else self.model.util
|
|
257
261
|
)
|
|
258
262
|
self.schema_out, self.schema_in, self.schema_update = self.get_schemas()
|
|
259
263
|
self.path_schema = self._generate_path_schema()
|
|
260
264
|
self.filters_schema = self._generate_filters_schema()
|
|
261
|
-
self.model_verbose_name =
|
|
265
|
+
self.model_verbose_name = (
|
|
266
|
+
self.model_verbose_name or self.model._meta.verbose_name.capitalize()
|
|
267
|
+
)
|
|
268
|
+
self.model_verbose_name_plural = (
|
|
269
|
+
self.model_verbose_name_plural
|
|
270
|
+
or self.model._meta.verbose_name_plural.capitalize()
|
|
271
|
+
)
|
|
262
272
|
self.router_tag = self.router_tag or self.model_verbose_name
|
|
263
273
|
self.router_tags = self.router_tags or tags or [self.router_tag]
|
|
264
274
|
self.router = Router(tags=self.router_tags)
|
|
@@ -355,16 +365,31 @@ class APIViewSet(API):
|
|
|
355
365
|
Compute and return (schema_out, schema_in, schema_update).
|
|
356
366
|
|
|
357
367
|
- If model is a ModelSerializer (ModelSerializerMeta), auto-generate read/create/update schemas.
|
|
358
|
-
- Otherwise,
|
|
359
|
-
"""
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
368
|
+
- Otherwise, use existing schemas or generate from serializer_class if provided.
|
|
369
|
+
"""
|
|
370
|
+
# ModelSerializer case: prefer explicitly set schemas, otherwise generate from the model
|
|
371
|
+
if isinstance(self.model, ModelSerializerMeta):
|
|
372
|
+
return (
|
|
373
|
+
self.schema_out or self.model.generate_read_s(),
|
|
374
|
+
self.schema_in or self.model.generate_create_s(),
|
|
375
|
+
self.schema_update or self.model.generate_update_s(),
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Non-ModelSerializer: start from provided schemas
|
|
379
|
+
schema_out, schema_in, schema_update = (
|
|
380
|
+
self.schema_out,
|
|
381
|
+
self.schema_in,
|
|
382
|
+
self.schema_update,
|
|
366
383
|
)
|
|
367
384
|
|
|
385
|
+
# If a serializer_class is available, generate from it
|
|
386
|
+
if self.serializer_class:
|
|
387
|
+
schema_in = schema_in or self.serializer_class.generate_create_s()
|
|
388
|
+
schema_out = schema_out or self.serializer_class.generate_read_s()
|
|
389
|
+
schema_update = schema_update or self.serializer_class.generate_update_s()
|
|
390
|
+
|
|
391
|
+
return (schema_out, schema_in, schema_update)
|
|
392
|
+
|
|
368
393
|
async def query_params_handler(
|
|
369
394
|
self, queryset: QuerySet[ModelSerializer], filters: dict
|
|
370
395
|
):
|
|
@@ -383,11 +408,11 @@ class APIViewSet(API):
|
|
|
383
408
|
@self.router.post(
|
|
384
409
|
self.path,
|
|
385
410
|
auth=self.post_view_auth(),
|
|
386
|
-
summary=f"Create {self.
|
|
411
|
+
summary=f"Create {self.model_verbose_name}",
|
|
387
412
|
description=self.create_docs,
|
|
388
413
|
response={201: self.schema_out, self.error_codes: GenericMessageSchema},
|
|
389
414
|
)
|
|
390
|
-
@decorate_view(unique_view(self), *self.extra_decorators.create)
|
|
415
|
+
@decorate_view(aatomic, unique_view(self), *self.extra_decorators.create)
|
|
391
416
|
async def create(request: HttpRequest, data: self.schema_in): # type: ignore
|
|
392
417
|
return 201, await self.model_util.create_s(request, data, self.schema_out)
|
|
393
418
|
|
|
@@ -401,7 +426,7 @@ class APIViewSet(API):
|
|
|
401
426
|
@self.router.get(
|
|
402
427
|
self.get_path,
|
|
403
428
|
auth=self.get_view_auth(),
|
|
404
|
-
summary=f"List {self.
|
|
429
|
+
summary=f"List {self.model_verbose_name_plural}",
|
|
405
430
|
description=self.list_docs,
|
|
406
431
|
response={
|
|
407
432
|
200: List[self.schema_out],
|
|
@@ -436,7 +461,7 @@ class APIViewSet(API):
|
|
|
436
461
|
@self.router.get(
|
|
437
462
|
self.get_path_retrieve,
|
|
438
463
|
auth=self.get_view_auth(),
|
|
439
|
-
summary=f"Retrieve {self.
|
|
464
|
+
summary=f"Retrieve {self.model_verbose_name}",
|
|
440
465
|
description=self.retrieve_docs,
|
|
441
466
|
response={200: self.schema_out, self.error_codes: GenericMessageSchema},
|
|
442
467
|
)
|
|
@@ -461,11 +486,11 @@ class APIViewSet(API):
|
|
|
461
486
|
@self.router.patch(
|
|
462
487
|
self.path_retrieve,
|
|
463
488
|
auth=self.patch_view_auth(),
|
|
464
|
-
summary=f"Update {self.
|
|
489
|
+
summary=f"Update {self.model_verbose_name}",
|
|
465
490
|
description=self.update_docs,
|
|
466
491
|
response={200: self.schema_out, self.error_codes: GenericMessageSchema},
|
|
467
492
|
)
|
|
468
|
-
@decorate_view(unique_view(self), *self.extra_decorators.update)
|
|
493
|
+
@decorate_view(aatomic, unique_view(self), *self.extra_decorators.update)
|
|
469
494
|
async def update(
|
|
470
495
|
request: HttpRequest,
|
|
471
496
|
data: self.schema_update, # type: ignore
|
|
@@ -485,11 +510,11 @@ class APIViewSet(API):
|
|
|
485
510
|
@self.router.delete(
|
|
486
511
|
self.path_retrieve,
|
|
487
512
|
auth=self.delete_view_auth(),
|
|
488
|
-
summary=f"Delete {self.
|
|
513
|
+
summary=f"Delete {self.model_verbose_name}",
|
|
489
514
|
description=self.delete_docs,
|
|
490
515
|
response={204: None, self.error_codes: GenericMessageSchema},
|
|
491
516
|
)
|
|
492
|
-
@decorate_view(unique_view(self), *self.extra_decorators.delete)
|
|
517
|
+
@decorate_view(aatomic, unique_view(self), *self.extra_decorators.delete)
|
|
493
518
|
async def delete(request: HttpRequest, pk: Path[self.path_schema]): # type: ignore
|
|
494
519
|
return 204, await self.model_util.delete_s(request, self._get_pk(pk))
|
|
495
520
|
|
|
File without changes
|
{django_ninja_aio_crud-2.3.2.dist-info → django_ninja_aio_crud-2.5.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|