django-ninja-aio-crud 0.8.4__tar.gz → 0.9.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-ninja-aio-crud
3
- Version: 0.8.4
3
+ Version: 0.9.1
4
4
  Summary: Django Ninja AIO CRUD - Rest Framework
5
5
  Author: Giuseppe Casillo
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  """Django Ninja AIO CRUD - Rest Framework"""
2
2
 
3
- __version__ = "0.8.4"
3
+ __version__ = "0.9.1"
4
4
 
5
5
  from .api import NinjaAIO
6
6
 
@@ -57,15 +57,67 @@ class APIView:
57
57
  pass
58
58
  """
59
59
 
60
- def add_views(self):
60
+ def _add_views(self):
61
61
  self.views()
62
62
  return self.router
63
63
 
64
64
  def add_views_to_route(self):
65
- return self.api.add_router(f"{self.api_route_path}/", self.add_views())
65
+ return self.api.add_router(f"{self.api_route_path}", self._add_views())
66
66
 
67
67
 
68
68
  class APIViewSet:
69
+ """
70
+ A base class for creating API views with CRUD operations.
71
+
72
+ This class provides methods for creating, listing, retrieving, updating,
73
+ and deleting objects of a specified model. It supports pagination,
74
+ authentication, and custom query parameters.
75
+
76
+ ## Attributes:
77
+ - **model** (`ModelSerializer | Model`): The model for CRUD operations.
78
+ - **api** (`NinjaAPI`): The API instance to which the views are added.
79
+ - **schema_in** (`Schema | None`): Schema for input data in create/update operations.
80
+ - **schema_out** (`Schema | None`): Schema for output data in list/retrieve operations.
81
+ - **schema_update** (`Schema | None`): Schema for update operations.
82
+ - **auth** (`list | None`): Authentication classes for the views.
83
+ - **get_auth** (`list | None`): Authentication for GET requests.
84
+ - **post_auth** (`list | None`): Authentication for POST requests.
85
+ - **patch_auth** (`list | None`): Authentication for PATCH requests.
86
+ - **delete_auth** (`list | None`): Authentication for DELETE requests.
87
+ - **pagination_class** (`type[AsyncPaginationBase]`): Pagination class to use.
88
+ - **query_params** (`dict[str, tuple[type, ...]]`): Query parameters for filtering.
89
+ - **disable** (`list[type[VIEW_TYPES]]`): List of view types to disable.
90
+ - **api_route_path** (`str`): Base path for the API route.
91
+ - **list_docs** (`str`): Documentation for the list view.
92
+ - **create_docs** (`str`): Documentation for the create view.
93
+ - **retrieve_docs** (`str`): Documentation for the retrieve view.
94
+ - **update_docs** (`str`): Documentation for the update view.
95
+ - **delete_docs** (`str`): Documentation for the delete view.
96
+
97
+ ## Notes:
98
+ If the model is a ModelSerializer instance, schemas are generated
99
+ automatically based on Create, Read, and Update serializers.
100
+ Override the `views` method to add custom views.
101
+ Override the `query_params_handler` method to handle query params
102
+ and return a filtered queryset.
103
+
104
+ ## Methods:
105
+ - **create_view**: Creates a new object.
106
+ - **list_view**: Lists all objects.
107
+ - **retrieve_view**: Retrieves an object by its primary key.
108
+ - **update_view**: Updates an object by its primary key.
109
+ - **delete_view**: Deletes an object by its primary key.
110
+ - **views**: Override to add custom views.
111
+ - **add_views_to_route**: Adds the views to the API route.
112
+
113
+ ## Example:
114
+ class MyModelViewSet(APIViewSet):
115
+ model = MyModel # Your Django model
116
+ api = my_api_instance # Your NinjaAPI instance
117
+
118
+ MyModelViewSet().add_views_to_route()
119
+ """
120
+
69
121
  model: ModelSerializer | Model
70
122
  api: NinjaAPI
71
123
  schema_in: Schema | None = None
@@ -80,6 +132,11 @@ class APIViewSet:
80
132
  query_params: dict[str, tuple[type, ...]] = {}
81
133
  disable: list[type[VIEW_TYPES]] = []
82
134
  api_route_path: str = ""
135
+ list_docs = "List all objects."
136
+ create_docs = "Create a new object."
137
+ retrieve_docs = "Retrieve a specific object by its primary key."
138
+ update_docs = "Update an object by its primary key."
139
+ delete_docs = "Delete an object by its primary key."
83
140
 
84
141
  def __init__(self) -> None:
85
142
  self.error_codes = ERROR_CODES
@@ -87,12 +144,13 @@ class APIViewSet:
87
144
  self.schema_out, self.schema_in, self.schema_update = self.get_schemas()
88
145
  self.path_schema = self._generate_path_schema()
89
146
  self.filters_schema = self._generate_filters_schema()
90
- self.router_tag = " ".join(
91
- self.model._meta.verbose_name.capitalize().split(" ")
92
- )
147
+ self.model_verbose_name = self.model._meta.verbose_name.capitalize()
148
+ self.router_tag = self.model_verbose_name
93
149
  self.router = Router(tags=[self.router_tag])
94
150
  self.path = "/"
151
+ self.get_path = ""
95
152
  self.path_retrieve = f"{{{self.model_util.model_pk_name}}}/"
153
+ self.get_path_retrieve = f"{{{self.model_util.model_pk_name}}}"
96
154
  self.api_route_path = (
97
155
  self.api_route_path or self.model_util.verbose_name_path_resolver()
98
156
  )
@@ -161,10 +219,13 @@ class APIViewSet:
161
219
  return queryset
162
220
 
163
221
  def create_view(self):
164
- @self.router.post(
165
- self.path,
222
+ @self.api.post(
223
+ f"{self.api_route_path}/",
166
224
  auth=self.post_view_auth(),
225
+ summary=f"Create {self.model._meta.verbose_name.capitalize()}",
226
+ description=self.create_docs,
167
227
  response={201: self.schema_out, self.error_codes: GenericMessageSchema},
228
+ tags=[self.router_tag],
168
229
  )
169
230
  async def create(request: HttpRequest, data: self.schema_in): # type: ignore
170
231
  return 201, await self.model_util.create_s(request, data, self.schema_out)
@@ -173,13 +234,16 @@ class APIViewSet:
173
234
  return create
174
235
 
175
236
  def list_view(self):
176
- @self.router.get(
177
- self.path,
237
+ @self.api.get(
238
+ self.api_route_path,
178
239
  auth=self.get_view_auth(),
240
+ summary=f"List {self.model._meta.verbose_name_plural.capitalize()}",
241
+ description=self.list_docs,
179
242
  response={
180
243
  200: List[self.schema_out],
181
244
  self.error_codes: GenericMessageSchema,
182
245
  },
246
+ tags=[self.router_tag],
183
247
  )
184
248
  @paginate(self.pagination_class)
185
249
  async def list(
@@ -204,10 +268,13 @@ class APIViewSet:
204
268
  return list
205
269
 
206
270
  def retrieve_view(self):
207
- @self.router.get(
208
- self.path_retrieve,
271
+ @self.api.get(
272
+ f"{self.api_route_path}/{self.get_path_retrieve}",
209
273
  auth=self.get_view_auth(),
274
+ summary=f"Retrieve {self.model._meta.verbose_name.capitalize()}",
275
+ description=self.retrieve_docs,
210
276
  response={200: self.schema_out, self.error_codes: GenericMessageSchema},
277
+ tags=[self.router_tag],
211
278
  )
212
279
  async def retrieve(request: HttpRequest, pk: Path[self.path_schema]): # type: ignore
213
280
  obj = await self.model_util.get_object(request, self._get_pk(pk))
@@ -217,14 +284,17 @@ class APIViewSet:
217
284
  return retrieve
218
285
 
219
286
  def update_view(self):
220
- @self.router.patch(
221
- self.path_retrieve,
287
+ @self.api.patch(
288
+ f"{self.api_route_path}/{self.path_retrieve}",
222
289
  auth=self.patch_view_auth(),
290
+ summary=f"Update {self.model._meta.verbose_name.capitalize()}",
291
+ description=self.update_docs,
223
292
  response={200: self.schema_out, self.error_codes: GenericMessageSchema},
293
+ tags=[self.router_tag],
224
294
  )
225
295
  async def update(
226
296
  request: HttpRequest,
227
- data: self.schema_update, # type: ignore
297
+ data: self.schema_update, # type: ignore
228
298
  pk: Path[self.path_schema], # type: ignore
229
299
  ):
230
300
  return await self.model_util.update_s(
@@ -235,10 +305,13 @@ class APIViewSet:
235
305
  return update
236
306
 
237
307
  def delete_view(self):
238
- @self.router.delete(
239
- self.path_retrieve,
308
+ @self.api.delete(
309
+ f"{self.api_route_path}/{self.path_retrieve}",
240
310
  auth=self.delete_view_auth(),
311
+ summary=f"Delete {self.model._meta.verbose_name.capitalize()}",
312
+ description=self.delete_docs,
241
313
  response={204: None, self.error_codes: GenericMessageSchema},
314
+ tags=[self.router_tag],
242
315
  )
243
316
  async def delete(request: HttpRequest, pk: Path[self.path_schema]): # type: ignore
244
317
  return 204, await self.model_util.delete_s(request, self._get_pk(pk))
@@ -279,7 +352,7 @@ class APIViewSet:
279
352
  pass
280
353
  """
281
354
 
282
- def add_views(self):
355
+ def _add_views(self):
283
356
  if "all" in self.disable:
284
357
  self.views()
285
358
  return self.router
@@ -294,7 +367,5 @@ class APIViewSet:
294
367
  return self.router
295
368
 
296
369
  def add_views_to_route(self):
297
- return self.api.add_router(
298
- f"{self.api_route_path}/",
299
- self.add_views(),
300
- )
370
+ self._add_views()
371
+ return self.api.add_router(f"{self.api_route_path}", self.router, tags=[self.router_tag])