django-ninja-aio-crud 2.3.2__tar.gz → 2.4.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 (102) hide show
  1. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/PKG-INFO +29 -1
  2. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/README.md +28 -0
  3. django_ninja_aio_crud-2.4.0/docs/api/models/serializers.md +130 -0
  4. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/index.md +35 -12
  5. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/mkdocs.yml +1 -0
  6. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/__init__.py +1 -1
  7. django_ninja_aio_crud-2.4.0/ninja_aio/models/__init__.py +4 -0
  8. django_ninja_aio_crud-2.4.0/ninja_aio/models/serializers.py +738 -0
  9. django_ninja_aio_crud-2.3.2/ninja_aio/models.py → django_ninja_aio_crud-2.4.0/ninja_aio/models/utils.py +19 -662
  10. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/views/api.py +26 -9
  11. django_ninja_aio_crud-2.4.0/tests/test_app/serializers.py +31 -0
  12. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_app/views.py +16 -2
  13. django_ninja_aio_crud-2.4.0/tests/test_serializers.py +106 -0
  14. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_settings.py +2 -0
  15. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/views/test_viewset.py +36 -2
  16. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/.github/dependabot.yml +0 -0
  17. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/.github/workflows/coverage.yml +0 -0
  18. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/.github/workflows/docs.yml +0 -0
  19. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/.github/workflows/publish.yml +0 -0
  20. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/.gitignore +0 -0
  21. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/.pre-commit-config.yaml +0 -0
  22. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/LICENSE +0 -0
  23. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/CNAME +0 -0
  24. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/authentication.md +0 -0
  25. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/models/model_serializer.md +0 -0
  26. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/models/model_util.md +0 -0
  27. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/pagination.md +0 -0
  28. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/renderers/orjson_renderer.md +0 -0
  29. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/views/api_view.md +0 -0
  30. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/views/api_view_set.md +0 -0
  31. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/views/decorators.md +0 -0
  32. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/api/views/mixins.md +0 -0
  33. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/auth.md +0 -0
  34. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/contributing.md +0 -0
  35. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/extra.css +0 -0
  36. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/images/index/foo-index-create-swagger.png +0 -0
  37. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/images/index/foo-index-delete-swagger.png +0 -0
  38. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/images/index/foo-index-list-swagger.png +0 -0
  39. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/images/index/foo-index-retrieve-swagger.png +0 -0
  40. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/images/index/foo-index-swagger.png +0 -0
  41. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/images/index/foo-index-update-swagger.png +0 -0
  42. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/installation.md +0 -0
  43. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/getting_started/quick_start.md +0 -0
  44. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/images/bar-swagger.png +0 -0
  45. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/images/favicon.ico +0 -0
  46. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/images/foo-swagger.png +0 -0
  47. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/images/logo.png +0 -0
  48. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/images/model_util/foo-reverse-relations-swagger.png +0 -0
  49. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/release_notes.md +0 -0
  50. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/requirements.txt +0 -0
  51. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/tutorial/authentication.md +0 -0
  52. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/tutorial/crud.md +0 -0
  53. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/tutorial/filtering.md +0 -0
  54. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/docs/tutorial/model.md +0 -0
  55. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/main.py +0 -0
  56. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/api.py +0 -0
  57. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/auth.py +0 -0
  58. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/decorators/__init__.py +0 -0
  59. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/decorators/operations.py +0 -0
  60. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/decorators/views.py +0 -0
  61. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/exceptions.py +0 -0
  62. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/factory/__init__.py +0 -0
  63. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/factory/operations.py +0 -0
  64. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/helpers/__init__.py +0 -0
  65. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/helpers/api.py +0 -0
  66. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/helpers/query.py +0 -0
  67. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/parsers.py +0 -0
  68. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/renders.py +0 -0
  69. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/schemas/__init__.py +0 -0
  70. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/schemas/api.py +0 -0
  71. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/schemas/generics.py +0 -0
  72. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/schemas/helpers.py +0 -0
  73. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/types.py +0 -0
  74. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/views/__init__.py +0 -0
  75. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/ninja_aio/views/mixins.py +0 -0
  76. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/pyproject.toml +0 -0
  77. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/requirements.dev.txt +0 -0
  78. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/run-local-coverage.sh +0 -0
  79. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/__init__.py +0 -0
  80. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/core/__init__.py +0 -0
  81. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/core/test_decorators.py +0 -0
  82. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/core/test_exceptions_api.py +0 -0
  83. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/core/test_renderer_parser.py +0 -0
  84. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/generics/__init__.py +0 -0
  85. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/generics/literals.py +0 -0
  86. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/generics/models.py +0 -0
  87. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/generics/request.py +0 -0
  88. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/generics/views.py +0 -0
  89. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/helpers/__init__.py +0 -0
  90. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/helpers/test_many_to_many_api.py +0 -0
  91. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/models/__init__.py +0 -0
  92. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/models/test_model_util.py +0 -0
  93. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/models/test_models_extra.py +0 -0
  94. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_app/__init__.py +0 -0
  95. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_app/models.py +0 -0
  96. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_app/schema.py +0 -0
  97. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_auth.py +0 -0
  98. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_decorators.py +0 -0
  99. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_exceptions.py +0 -0
  100. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/test_query_util.py +0 -0
  101. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/views/__init__.py +0 -0
  102. {django_ninja_aio_crud-2.3.2 → django_ninja_aio_crud-2.4.0}/tests/views/test_views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-ninja-aio-crud
3
- Version: 2.3.2
3
+ Version: 2.4.0
4
4
  Summary: Django Ninja AIO CRUD - Rest Framework
5
5
  Author: Giuseppe Casillo
6
6
  Requires-Python: >=3.10, <3.15
@@ -262,6 +262,34 @@ class BookViewSet(APIViewSet):
262
262
 
263
263
  ---
264
264
 
265
+ ## Meta-driven Serializer (for vanilla Django models)
266
+
267
+ If you already have Django models and don't want to inherit from ModelSerializer, use the Meta-driven Serializer to generate dynamic schemas and integrate with APIViewSet.
268
+
269
+ Example:
270
+
271
+ ```python
272
+ from ninja_aio.models import serializers
273
+ from . import models
274
+
275
+ class BookSerializer(serializers.Serializer):
276
+ class Meta:
277
+ model = models.Book
278
+ schema_in = serializers.SchemaModelConfig(fields=["title", "published"])
279
+ schema_out = serializers.SchemaModelConfig(fields=["id", "title", "published"])
280
+ schema_update = serializers.SchemaModelConfig(optionals=[("title", str), ("published", bool)])
281
+
282
+ @api.viewset(models.Book)
283
+ class BookViewSet(APIViewSet):
284
+ serializer_class = BookSerializer
285
+ ```
286
+
287
+ - Works without modifying existing models
288
+ - Supports nested relations via relations_serializers
289
+ - APIViewSet will auto-generate missing schemas from the serializer
290
+
291
+ ---
292
+
265
293
  ## 🛠 Project Structure & Docs
266
294
 
267
295
  Documentation (MkDocs + Material):
@@ -227,6 +227,34 @@ class BookViewSet(APIViewSet):
227
227
 
228
228
  ---
229
229
 
230
+ ## Meta-driven Serializer (for vanilla Django models)
231
+
232
+ If you already have Django models and don't want to inherit from ModelSerializer, use the Meta-driven Serializer to generate dynamic schemas and integrate with APIViewSet.
233
+
234
+ Example:
235
+
236
+ ```python
237
+ from ninja_aio.models import serializers
238
+ from . import models
239
+
240
+ class BookSerializer(serializers.Serializer):
241
+ class Meta:
242
+ model = models.Book
243
+ schema_in = serializers.SchemaModelConfig(fields=["title", "published"])
244
+ schema_out = serializers.SchemaModelConfig(fields=["id", "title", "published"])
245
+ schema_update = serializers.SchemaModelConfig(optionals=[("title", str), ("published", bool)])
246
+
247
+ @api.viewset(models.Book)
248
+ class BookViewSet(APIViewSet):
249
+ serializer_class = BookSerializer
250
+ ```
251
+
252
+ - Works without modifying existing models
253
+ - Supports nested relations via relations_serializers
254
+ - APIViewSet will auto-generate missing schemas from the serializer
255
+
256
+ ---
257
+
230
258
  ## 🛠 Project Structure & Docs
231
259
 
232
260
  Documentation (MkDocs + Material):
@@ -0,0 +1,130 @@
1
+ # Serializer (Meta-driven)
2
+
3
+ The Serializer class provides dynamic schema generation and relation handling for existing Django models without requiring you to adopt the ModelSerializer base class. Use it when:
4
+
5
+ - You already have vanilla Django models in a project and want dynamic Ninja schemas.
6
+ - You prefer to keep models unchanged and define serialization externally.
7
+
8
+ It mirrors the behavior of ModelSerializer but reads configuration from a nested Meta class.
9
+
10
+ ## Key points
11
+
12
+ - Works with any Django model (no inheritance required).
13
+ - Generates read/create/update/related schemas on demand via ninja.orm.create_schema.
14
+ - Supports explicit relation serializers for forward and reverse relations.
15
+ - Plays nicely with APIViewSet to auto-wire schemas and queryset handling.
16
+
17
+ ## Configuration
18
+
19
+ Define a Serializer subclass with a nested Meta:
20
+
21
+ - model: Django model class.
22
+ - schema_in: SchemaModelConfig for create inputs.
23
+ - schema_out: SchemaModelConfig for read outputs.
24
+ - schema_update: SchemaModelConfig for patch/update inputs.
25
+ - relations_serializers: mapping of relation field name -> Serializer to include nested schemas for relations.
26
+
27
+ SchemaModelConfig fields:
28
+
29
+ - fields: list[str]
30
+ - optionals: list[tuple[str, type]]
31
+ - exclude: list[str]
32
+ - customs: list[tuple[str, type, Any]]
33
+
34
+ ## Example: simple FK
35
+
36
+ ```python
37
+ from ninja_aio.models import serializers
38
+ from . import models
39
+
40
+ class ArticleSerializer(serializers.Serializer):
41
+ class Meta:
42
+ model = models.Article
43
+ schema_in = serializers.SchemaModelConfig(
44
+ fields=["title", "content", "author"]
45
+ )
46
+ schema_out = serializers.SchemaModelConfig(
47
+ fields=["id", "title", "content", "author"]
48
+ )
49
+ schema_update = serializers.SchemaModelConfig(
50
+ optionals=[("title", str), ("content", str)]
51
+ )
52
+ ```
53
+
54
+ Generate schemas when needed:
55
+
56
+ ```python
57
+ ArticleSerializer.generate_read_s()
58
+ ArticleSerializer.generate_create_s()
59
+ ArticleSerializer.generate_update_s()
60
+ ArticleSerializer.generate_related_s()
61
+ ```
62
+
63
+ ## Example: reverse relation with nested serialization
64
+
65
+ ```python
66
+ class AuthorSerializer(serializers.Serializer):
67
+ class Meta:
68
+ model = models.Author
69
+ schema_out = serializers.SchemaModelConfig(
70
+ fields=["id", "name", "articles"] # reverse related name
71
+ )
72
+ relations_serializers = {
73
+ "articles": ArticleSerializer, # include nested article schema
74
+ }
75
+ ```
76
+
77
+ Notes:
78
+
79
+ - Forward relations are included as plain fields unless a related ModelSerializer/Serializer is declared.
80
+ - Reverse relations require an entry in relations_serializers when using vanilla Django models.
81
+ - When the related model is a ModelSerializer, related schemas can be auto-resolved.
82
+
83
+ ## Using with APIViewSet
84
+
85
+ You can attach a Serializer to an APIViewSet to auto-generate schemas and leverage queryset_request when present:
86
+
87
+ ```python
88
+ from ninja_aio.views import APIViewSet
89
+ from ninja_aio import NinjaAIO
90
+ from . import models
91
+
92
+ api = NinjaAIO()
93
+
94
+ @api.viewset(models.Article)
95
+ class ArticleViewSet(APIViewSet):
96
+ serializer_class = ArticleSerializer
97
+ # Optionally define query_params or custom handlers
98
+ ```
99
+
100
+ Behavior:
101
+
102
+ - If model is a ModelSerializer, APIViewSet uses the model to generate schemas.
103
+ - If model is a vanilla model and serializer_class is provided, APIViewSet uses the Serializer to generate missing schemas.
104
+ - ModelUtil uses serializer_class.queryset_request if defined to build optimized querysets.
105
+
106
+ ## Advanced: customs and optionals
107
+
108
+ Customs and optionals behave like ModelSerializer:
109
+
110
+ - customs: synthetic fields included in schemas (with default or required when default is Ellipsis).
111
+ - optionals: patch-like optional fields. In read schema, they are included with default None.
112
+
113
+ ```python
114
+ class PublishSerializer(serializers.Serializer):
115
+ class Meta:
116
+ model = models.Article
117
+ schema_update = serializers.SchemaModelConfig(
118
+ optionals=[("is_published", bool)],
119
+ customs=[("notify_subscribers", bool, True)],
120
+ )
121
+ ```
122
+
123
+ generate_update_s merges optionals and customs for the Patch schema.
124
+
125
+ ## When to choose Serializer vs ModelSerializer
126
+
127
+ - Serializer: Keep your existing models unchanged; define schemas near your API layer. Ideal for incremental adoption.
128
+ - ModelSerializer: Centralize API schema and hooks on the model class itself. Ideal for greenfield projects inside this framework.
129
+
130
+ Both approaches support nested relations and dynamic schema generation. Choose the one that best fits your project structure.
@@ -33,12 +33,11 @@ Traditional Django REST development requires:
33
33
  **Django Ninja Aio CRUD** eliminates this complexity:
34
34
 
35
35
  === "Traditional Approach"
36
- ```python
37
- # schema.py
38
- class UserSchemaOut(ModelSchema)
39
- class Meta:
40
- model = User
41
- fields = ['id', 'username', 'email']
36
+ ```python # schema.py
37
+ class UserSchemaOut(ModelSchema)
38
+ class Meta:
39
+ model = User
40
+ fields = ['id', 'username', 'email']
42
41
 
43
42
  class UserSchemaIn(ModelSchema):
44
43
  class Meta:
@@ -60,12 +59,11 @@ Traditional Django REST development requires:
60
59
  ```
61
60
 
62
61
  === "Django Ninja Aio CRUD"
63
- ```python
64
- # models.py
65
- class User(ModelSerializer):
66
- username = models.CharField(max_length=150)
67
- email = models.EmailField()
68
- password = models.CharField(max_length=128)
62
+ ```python # models.py
63
+ class User(ModelSerializer):
64
+ username = models.CharField(max_length=150)
65
+ email = models.EmailField()
66
+ password = models.CharField(max_length=128)
69
67
 
70
68
  class ReadSerializer:
71
69
  fields = ["id", "username", "email"]
@@ -92,6 +90,7 @@ Explore detailed documentation for each component:
92
90
 
93
91
  - **[Model Serializer](api/models/model_serializer.md)** - Schema generation and serialization
94
92
  - **[Model Util](api/models/model_util.md)** - Async CRUD utilities
93
+ - **[Serializer (Meta-driven)](api/models/serializers.md)** - Dynamic schemas for existing Django models without inheriting ModelSerializer
95
94
 
96
95
  #### Views
97
96
 
@@ -273,6 +272,30 @@ class User(ModelSerializer):
273
272
  optionals = [("username", str)] # Partial update schema
274
273
  ```
275
274
 
275
+ ### Serializer (Meta-driven)
276
+
277
+ Use when you have vanilla Django models and want dynamic serialization without changing your model base class.
278
+
279
+ ```python
280
+ from ninja_aio.models import serializers
281
+ from . import models
282
+
283
+ class BookSerializer(serializers.Serializer):
284
+ class Meta:
285
+ model = models.Book
286
+ schema_in = serializers.SchemaModelConfig(fields=["title", "published"])
287
+ schema_out = serializers.SchemaModelConfig(fields=["id", "title", "published"])
288
+ schema_update = serializers.SchemaModelConfig(optionals=[("title", str), ("published", bool)])
289
+ ```
290
+
291
+ Attach to an APIViewSet:
292
+
293
+ ```python
294
+ @api.viewset(models.Book)
295
+ class BookViewSet(APIViewSet):
296
+ serializer_class = BookSerializer
297
+ ```
298
+
276
299
  ### APIViewSet
277
300
 
278
301
  Automatically generates complete CRUD endpoints:
@@ -24,6 +24,7 @@ nav:
24
24
  - Models:
25
25
  - ModelSerializer: api/models/model_serializer.md
26
26
  - ModelUtil: api/models/model_util.md
27
+ - Serializer (Meta-driven): api/models/serializers.md
27
28
  - Authentication: api/authentication.md
28
29
  - Pagination: api/pagination.md
29
30
  - Authentication:
@@ -1,6 +1,6 @@
1
1
  """Django Ninja AIO CRUD - Rest Framework"""
2
2
 
3
- __version__ = "2.3.2"
3
+ __version__ = "2.4.0"
4
4
 
5
5
  from .api import NinjaAIO
6
6
 
@@ -0,0 +1,4 @@
1
+ from .utils import ModelUtil
2
+ from .serializers import ModelSerializer
3
+
4
+ __all__ = ["ModelUtil", "ModelSerializer"]