django-ninja-aio-crud 2.12.2__tar.gz → 2.13.0__tar.gz

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.

Potentially problematic release.


This version of django-ninja-aio-crud might be problematic. Click here for more details.

Files changed (103) hide show
  1. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/PKG-INFO +1 -1
  2. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/views/api_view_set.md +14 -0
  3. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/__init__.py +1 -1
  4. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/helpers/api.py +11 -5
  5. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/models/serializers.py +3 -4
  6. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/schemas/helpers.py +4 -1
  7. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_settings.py +1 -1
  8. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/.github/dependabot.yml +0 -0
  9. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/.github/workflows/coverage.yml +0 -0
  10. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/.github/workflows/docs.yml +0 -0
  11. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/.github/workflows/publish.yml +0 -0
  12. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/.gitignore +0 -0
  13. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/.pre-commit-config.yaml +0 -0
  14. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/LICENSE +0 -0
  15. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/README.md +0 -0
  16. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/CNAME +0 -0
  17. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/authentication.md +0 -0
  18. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/models/model_serializer.md +0 -0
  19. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/models/model_util.md +0 -0
  20. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/models/serializers.md +0 -0
  21. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/pagination.md +0 -0
  22. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/renderers/orjson_renderer.md +0 -0
  23. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/views/api_view.md +0 -0
  24. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/views/decorators.md +0 -0
  25. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/api/views/mixins.md +0 -0
  26. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/auth.md +0 -0
  27. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/contributing.md +0 -0
  28. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/extra.css +0 -0
  29. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/images/index/foo-index-create-swagger.png +0 -0
  30. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/images/index/foo-index-delete-swagger.png +0 -0
  31. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/images/index/foo-index-list-swagger.png +0 -0
  32. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/images/index/foo-index-retrieve-swagger.png +0 -0
  33. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/images/index/foo-index-swagger.png +0 -0
  34. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/images/index/foo-index-update-swagger.png +0 -0
  35. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/installation.md +0 -0
  36. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/getting_started/quick_start.md +0 -0
  37. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/images/bar-swagger.png +0 -0
  38. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/images/favicon.ico +0 -0
  39. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/images/foo-swagger.png +0 -0
  40. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/images/logo.png +0 -0
  41. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/images/model_util/foo-reverse-relations-swagger.png +0 -0
  42. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/index.md +0 -0
  43. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/release_notes.md +0 -0
  44. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/requirements.txt +0 -0
  45. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/tutorial/authentication.md +0 -0
  46. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/tutorial/crud.md +0 -0
  47. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/tutorial/filtering.md +0 -0
  48. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/docs/tutorial/model.md +0 -0
  49. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/main.py +0 -0
  50. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/mkdocs.yml +0 -0
  51. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/api.py +0 -0
  52. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/auth.py +0 -0
  53. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/decorators/__init__.py +0 -0
  54. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/decorators/operations.py +0 -0
  55. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/decorators/views.py +0 -0
  56. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/exceptions.py +0 -0
  57. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/factory/__init__.py +0 -0
  58. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/factory/operations.py +0 -0
  59. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/helpers/__init__.py +0 -0
  60. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/helpers/query.py +0 -0
  61. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/models/__init__.py +0 -0
  62. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/models/utils.py +0 -0
  63. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/parsers.py +0 -0
  64. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/renders.py +0 -0
  65. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/schemas/__init__.py +0 -0
  66. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/schemas/api.py +0 -0
  67. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/schemas/filters.py +0 -0
  68. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/schemas/generics.py +0 -0
  69. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/types.py +0 -0
  70. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/views/__init__.py +0 -0
  71. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/views/api.py +0 -0
  72. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/ninja_aio/views/mixins.py +0 -0
  73. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/pyproject.toml +0 -0
  74. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/requirements.dev.txt +0 -0
  75. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/run-local-coverage.sh +0 -0
  76. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/__init__.py +0 -0
  77. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/core/__init__.py +0 -0
  78. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/core/test_decorators.py +0 -0
  79. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/core/test_exceptions_api.py +0 -0
  80. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/core/test_renderer_parser.py +0 -0
  81. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/generics/__init__.py +0 -0
  82. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/generics/literals.py +0 -0
  83. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/generics/models.py +0 -0
  84. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/generics/request.py +0 -0
  85. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/generics/views.py +0 -0
  86. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/helpers/__init__.py +0 -0
  87. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/helpers/test_many_to_many_api.py +0 -0
  88. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/models/__init__.py +0 -0
  89. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/models/test_model_util.py +0 -0
  90. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/models/test_models_extra.py +0 -0
  91. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_app/__init__.py +0 -0
  92. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_app/models.py +0 -0
  93. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_app/schema.py +0 -0
  94. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_app/serializers.py +0 -0
  95. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_app/views.py +0 -0
  96. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_auth.py +0 -0
  97. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_decorators.py +0 -0
  98. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_exceptions.py +0 -0
  99. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_query_util.py +0 -0
  100. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/test_serializers.py +0 -0
  101. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/views/__init__.py +0 -0
  102. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/views/test_views.py +0 -0
  103. {django_ninja_aio_crud-2.12.2 → django_ninja_aio_crud-2.13.0}/tests/views/test_viewset.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-ninja-aio-crud
3
- Version: 2.12.2
3
+ Version: 2.13.0
4
4
  Summary: Django Ninja AIO CRUD - Rest Framework
5
5
  Author: Giuseppe Casillo
6
6
  Requires-Python: >=3.10, <3.15
@@ -293,6 +293,7 @@ Relations are declared via `M2MRelationSchema` objects (not tuples). Each schema
293
293
  - `related_schema`: optional pre-built schema for the related model (auto-generated if the `model` is a `ModelSerializer`)
294
294
  - `serializer_class`: optional `Serializer` class for plain Django models. When provided, `related_schema` is auto-generated from the serializer. Cannot be used when `model` is a `ModelSerializer`.
295
295
  - `append_slash`: bool to control trailing slash for the GET relation endpoint path. Defaults to `False` (no trailing slash) for backward compatibility. When `True`, the GET path ends with a trailing slash.
296
+ - `verbose_name_plural`: optional human-readable plural name for the related model, used in endpoint summaries and descriptions. When not provided, defaults to the related model's `_meta.verbose_name_plural`.
296
297
 
297
298
  If `path` is empty it falls back to the related model verbose name (lowercase plural).
298
299
  If `filters` is provided, a per-relation filters schema is auto-generated and exposed on the GET relation endpoint:
@@ -475,6 +476,19 @@ M2MRelationSchema(
475
476
  )
476
477
  ```
477
478
 
479
+ Example with custom verbose name:
480
+
481
+ ```python
482
+ M2MRelationSchema(
483
+ model=Tag,
484
+ related_name="tags",
485
+ verbose_name_plural="Article Tags", # Used in summaries: "Get Article Tags", "Add or Remove Article Tags"
486
+ add=True,
487
+ remove=True,
488
+ get=True,
489
+ )
490
+ ```
491
+
478
492
  ## Custom Views
479
493
 
480
494
  Preferred (decorators): see the section above.
@@ -1,6 +1,6 @@
1
1
  """Django Ninja AIO CRUD - Rest Framework"""
2
2
 
3
- __version__ = "2.12.2"
3
+ __version__ = "2.13.0"
4
4
 
5
5
  from .api import NinjaAIO
6
6
 
@@ -358,6 +358,7 @@ class ManyToManyAPI:
358
358
  related_schema,
359
359
  filters_schema,
360
360
  append_slash: bool,
361
+ verbose_name_plural: str,
361
362
  ):
362
363
  @self.router.get(
363
364
  self._get_api_path(rel_path, append_slash=append_slash),
@@ -366,8 +367,8 @@ class ManyToManyAPI:
366
367
  self.view_set.error_codes: GenericMessageSchema,
367
368
  },
368
369
  auth=m2m_auth,
369
- summary=f"Get {rel_util.model._meta.verbose_name_plural.capitalize()}",
370
- description=f"Get all related {rel_util.model._meta.verbose_name_plural.capitalize()}",
370
+ summary=f"Get {verbose_name_plural}",
371
+ description=f"Get all related {verbose_name_plural}",
371
372
  )
372
373
  @decorate_view(
373
374
  unique_view(f"get_{self.related_model_util.model_name}_{rel_path}"),
@@ -402,13 +403,13 @@ class ManyToManyAPI:
402
403
  related_model: ModelSerializer | Model,
403
404
  related_name: str,
404
405
  m2m_auth,
405
- rel_util: ModelUtil,
406
406
  rel_path: str,
407
407
  m2m_add: bool,
408
408
  m2m_remove: bool,
409
+ verbose_name_plural: str,
409
410
  ):
410
411
  action, schema_in = self._resolve_action_schema(m2m_add, m2m_remove)
411
- plural = rel_util.model._meta.verbose_name_plural.capitalize()
412
+ plural = verbose_name_plural
412
413
  summary = f"{action} {plural}"
413
414
 
414
415
  @self.router.post(
@@ -478,6 +479,10 @@ class ManyToManyAPI:
478
479
  m2m_add, m2m_remove, m2m_get = relation.add, relation.remove, relation.get
479
480
  filters_schema = self.relations_filters_schemas.get(related_name)
480
481
  append_slash = relation.append_slash
482
+ verbose_name_plural = (
483
+ relation.verbose_name_plural
484
+ or rel_util.model._meta.verbose_name_plural.capitalize()
485
+ )
481
486
 
482
487
  if m2m_get:
483
488
  self._register_get_relation_view(
@@ -488,6 +493,7 @@ class ManyToManyAPI:
488
493
  related_schema=related_schema,
489
494
  filters_schema=filters_schema,
490
495
  append_slash=append_slash,
496
+ verbose_name_plural=verbose_name_plural,
491
497
  )
492
498
 
493
499
  if m2m_add or m2m_remove:
@@ -495,10 +501,10 @@ class ManyToManyAPI:
495
501
  related_model=model,
496
502
  related_name=related_name,
497
503
  m2m_auth=m2m_auth,
498
- rel_util=rel_util,
499
504
  rel_path=rel_path,
500
505
  m2m_add=m2m_add,
501
506
  m2m_remove=m2m_remove,
507
+ verbose_name_plural=verbose_name_plural,
502
508
  )
503
509
 
504
510
  def _add_views(self):
@@ -424,10 +424,9 @@ class BaseSerializer:
424
424
  @classmethod
425
425
  def _warn_missing_relation_serializer(cls, field_name: str, model) -> None:
426
426
  """Emit warning for reverse relations without explicit serializer mapping."""
427
- if (
428
- not isinstance(model, ModelSerializerMeta)
429
- and not getattr(settings, "NINJA_AIO_TESTING", False)
430
- ) or getattr(settings, "NINJA_AIO_RAISE_SERIALIZATION_WARNINGS", False):
427
+ if not isinstance(model, ModelSerializerMeta) and getattr(
428
+ settings, "NINJA_AIO_RAISE_SERIALIZATION_WARNINGS", True
429
+ ):
431
430
  warnings.warn(
432
431
  f"{cls.__name__}: reverse relation '{field_name}' is listed in read fields "
433
432
  "but has no entry in relations_serializers; it will be auto-resolved only "
@@ -44,7 +44,9 @@ class M2MRelationSchema(BaseModel):
44
44
  it can be used to auto-generate the `related_schema`.
45
45
  append_slash (bool):
46
46
  Whether to append a trailing slash to the generated GET endpoint path. Defaults to False for backward compatibility.
47
-
47
+ verbose_name_plural (str | None):
48
+ Optional human-readable plural name for the related model, used in documentation and responses.
49
+
48
50
  Validation:
49
51
  - If `model` is not a ModelSerializerMeta, `related_schema` is required.
50
52
  - When `model` is a ModelSerializerMeta and `related_schema` is not provided, it will be
@@ -69,6 +71,7 @@ class M2MRelationSchema(BaseModel):
69
71
  related_schema: Optional[Type[Schema]] = None
70
72
  serializer_class: Optional[SerializerMeta] = None
71
73
  append_slash: bool = False
74
+ verbose_name_plural: Optional[str] = None
72
75
 
73
76
  model_config = ConfigDict(arbitrary_types_allowed=True)
74
77
 
@@ -47,4 +47,4 @@ LOGGING = {
47
47
  },
48
48
  }
49
49
 
50
- NINJA_AIO_TESTING = True
50
+ NINJA_AIO_RAISE_SERIALIZATION_WARNINGS = False