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.
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 = self.model._meta.verbose_name.capitalize()
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, return the schemas already set on the viewset (may be None).
359
- """
360
- if not isinstance(self.model, ModelSerializerMeta):
361
- return self.schema_out, self.schema_in, self.schema_update
362
- return (
363
- self.schema_out or self.model.generate_read_s(),
364
- self.schema_in or self.model.generate_create_s(),
365
- self.schema_update or self.model.generate_update_s(),
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.model._meta.verbose_name.capitalize()}",
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.model._meta.verbose_name_plural.capitalize()}",
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.model._meta.verbose_name.capitalize()}",
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.model._meta.verbose_name.capitalize()}",
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.model._meta.verbose_name.capitalize()}",
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