django-ninja-aio-crud 0.1.1__py3-none-any.whl → 0.1.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-ninja-aio-crud
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Django Ninja AIO CRUD - Rest Framework
5
5
  Author: Giuseppe Casillo
6
6
  Requires-Python: >=3.10
@@ -34,24 +34,32 @@ Project-URL: Repository, https://github.com/caspel26/django-ninja-aio-crud
34
34
  ## 📝 Instructions
35
35
 
36
36
  ### 📚 Prerequisites
37
+
37
38
  - Install Python from the [official website](https://www.python.org/) (latest version) and ensure it is added to the system Path and environment variables.
38
39
 
39
40
  ### 💻 Setup your environment
41
+
40
42
  - Create a virtual environment
41
43
  ```bash
42
44
  python -m venv .venv
43
45
  ```
46
+
44
47
  ### ✅ Activate it
48
+
45
49
  - If you are from linux activate it with
50
+
46
51
  ```bash
47
52
  . .venv/bin/activate
48
53
  ```
54
+
49
55
  - If you are from windows activate it with
56
+
50
57
  ```bash
51
58
  . .venv/Scripts/activate
52
59
  ```
53
60
 
54
61
  ### 📥 Install package
62
+
55
63
  ```bash
56
64
  pip install django-ninja-aio-crud
57
65
  ```
@@ -63,14 +71,17 @@ pip install django-ninja-aio-crud
63
71
  > and why not ... [Buy me a coffee](https://buymeacoffee.com/caspel26)
64
72
 
65
73
  ### ModelSerializer
74
+
66
75
  - You can serialize your models using ModelSerializer and made them inherit from it. In your models.py import ModelSerializer
67
76
  ```Python
77
+ # models.py
78
+ from django.db import models
68
79
  from ninja_aio.models import ModelSerializer
69
80
 
70
81
 
71
82
  class Foo(ModelSerializer):
72
- name = mdoels.CharField()
73
- bar = models.CharField()
83
+ name = models.CharField(max_length=30)
84
+ bar = models.CharField(max_length=30)
74
85
 
75
86
  class ReadSerializer:
76
87
  fields = ["id", "name", "bar"]
@@ -81,14 +92,18 @@ class Foo(ModelSerializer):
81
92
  class UpdateSerializer:
82
93
  fields = ["name", "bar"]
83
94
  ```
95
+
84
96
  - ReadSerializer, CreateSerializer, UpdateSerializer are used to define which fields would be included in runtime schemas creation. You can also specify custom fields and handle their function by overriding custom_actions ModelSerializer's method(custom fields are only available for Create and Update serializers).
97
+
85
98
  ```Python
99
+ # models.py
100
+ from django.db import models
86
101
  from ninja_aio.models import ModelSerializer
87
102
 
88
103
 
89
104
  class Foo(ModelSerializer):
90
- name = mdoels.CharField()
91
- bar = models.CharField()
105
+ name = models.CharField(max_length=30)
106
+ bar = models.CharField(max_length=30)
92
107
  active = models.BooleanField(default=False)
93
108
 
94
109
  class ReadSerializer:
@@ -112,12 +127,15 @@ class Foo(ModelSerializer):
112
127
  self.active = True
113
128
  await self.asave()
114
129
  ```
115
- - post create method is a custom method that comes out to handle actions which will be excuted after that the object is created. It can be used, indeed, for example to handle custom fields' actions.
116
130
 
131
+ - post create method is a custom method that comes out to handle actions which will be excuted after that the object is created. It can be used, indeed, for example to handle custom fields' actions.
117
132
 
118
133
  ### APIViewSet
134
+
119
135
  - View class used to automatically generate CRUD views. in your views.py import APIViewSet and define your api using NinjaAPI class. As Parser and Render of the API you must use ninja_aio built-in classes which will serialize data using orjson.
136
+
120
137
  ```Python
138
+ # views.py
121
139
  from ninja import NinjAPI
122
140
  from ninja_aio.views import APIViewSet
123
141
  from ninja_aio.parsers import ORJSONParser
@@ -135,8 +153,11 @@ class FooAPI(APIViewSet):
135
153
 
136
154
  FooAPI().add_views_to_route()
137
155
  ```
156
+
138
157
  - and that's it, your model CRUD will be automatically created. You can also add custom views to CRUD overriding the built-in method "views".
158
+
139
159
  ```Python
160
+ # views.py
140
161
  from ninja import NinjAPI, Schema
141
162
  from ninja_aio.views import APIViewSet
142
163
  from ninja_aio.parsers import ORJSONParser
@@ -161,7 +182,7 @@ class FooAPI(APIViewSet):
161
182
  api = api
162
183
 
163
184
  def views(self):
164
- @self.router.post("numbers-sum/", response={200: ExampleSchemaOut)
185
+ @self.router.post("numbers-sum/", response={200: ExampleSchemaOut})
165
186
  async def sum(request: HttpRequest, data: ExampleSchemaIn):
166
187
  return 200, {sum: data.n1 + data.n2}
167
188
 
@@ -170,8 +191,11 @@ FooAPI().add_views_to_route()
170
191
  ```
171
192
 
172
193
  ### APIView
194
+
173
195
  - View class to code generic views class based. In your views.py import APIView class.
196
+
174
197
  ```Python
198
+ # views.py
175
199
  from ninja import NinjAPI, Schema
176
200
  from ninja_aio.views import APIView
177
201
  from ninja_aio.parsers import ORJSONParser
@@ -195,7 +219,7 @@ class SumView(APIView):
195
219
  router_tag = "Sum"
196
220
 
197
221
  def views(self):
198
- @self.router.post(self.api_router_path, response={200: ExampleSchemaOut)
222
+ @self.router.post("/", response={200: ExampleSchemaOut})
199
223
  async def sum(request: HttpRequest, data: ExampleSchemaIn):
200
224
  return 200, {sum: data.n1 + data.n2}
201
225
 
@@ -203,9 +227,91 @@ class SumView(APIView):
203
227
  SumView().add_views_to_route()
204
228
  ```
205
229
 
230
+ ### Relations
231
+ - You can also set ForeignKey and OneToOne relations into serialization(reverse relations are supported too). Django ninja aio crud will serialize every of these relation automatically.
232
+
233
+ > [!WARNING]
234
+ > Only ForeignKey and OneToOne relations are supported for serialization, ManyToMany relations are not supported yet.
235
+
236
+ - Define models:
237
+
238
+ ```Python
239
+ # models.py
240
+ class Bar(ModelSerializer):
241
+ name = models.CharField(max_length=30)
242
+ description = models.TextField(max_length=30)
243
+
244
+ # ReadSerializer with reverse OneToMany relation (foos)
245
+ class ReadSerializer:
246
+ fields = ["id", "name", "description", "foos"]
247
+
248
+ class CreateSerializer:
249
+ fields = ["name", "description"]
250
+
251
+ class UpdateSerializer:
252
+ fields = ["name", "description"]
253
+
254
+
255
+ class Foo(ModelSerializer):
256
+ name = models.CharField(max_length=30)
257
+ bar = models.ForeignKey(Bar, on_delete=models.CASCADE, related_name="foos")
258
+
259
+ class ReadSerializer:
260
+ fields = ["id", "name", "bar"]
261
+
262
+ class CreateSerializer:
263
+ fields = ["name", "bar"]
264
+
265
+ class UpdateSerializer:
266
+ fields = ["name"]
267
+ ```
268
+
269
+ - Define views:
270
+
271
+ ```Python
272
+ # views.py
273
+ from ninja import NinjAPI
274
+ from ninja_aio.views import APIViewSet
275
+ from ninja_aio.parsers import ORJSONParser
276
+ from ninja_aio.renders import ORJSONRender
277
+
278
+ from .models import Foo, Bar
279
+
280
+ api = NinjaAPI(renderer=ORJSONRenderer(), parser=ORJSONParser())
281
+
282
+
283
+ class FooAPI(APIViewSet):
284
+ model = Foo
285
+ api = api
286
+
287
+
288
+ class BarAPI(APIViewSet):
289
+ model = Bar
290
+ api = api
291
+
292
+
293
+ FooAPI().add_views_to_route()
294
+ BarAPI().add_views_to_route()
295
+ ```
296
+
297
+ - Now run your server and go to /docs url:
298
+
299
+ ### Docs
300
+
301
+ - Foo Schemas
302
+
303
+ ![Swagger UI](ninja_aio/docs/images/foo-swagger.png)
304
+
305
+ - Bar Schemas with reverse relation
306
+
307
+ ![Swagger UI](ninja_aio/docs/images/bar-swagger.png)
308
+
206
309
  ## 🔒 Authentication
310
+
207
311
  ### Jwt
312
+
208
313
  - AsyncJWTBearer built-in class is an authenticator class which use joserfc module. It cames out with authenticate method which validate given claims. Override auth handler method to write your own authentication method. Default algorithms used is RS256. a jwt Token istance is set as class atribute so you can use it by self.dcd.
314
+
209
315
  ```Python
210
316
  from ninja_aio.auth import AsyncJWTBearer
211
317
  from django.conf import settings
@@ -225,8 +331,11 @@ class CustomJWTBearer(AsyncJWTBearer):
225
331
  return None
226
332
  return request.user
227
333
  ```
334
+
228
335
  - Then add it to views.
336
+
229
337
  ```Python
338
+ # views.py
230
339
  from ninja import NinjAPI, Schema
231
340
  from ninja_aio.views import APIViewSet, APIView
232
341
  from ninja_aio.parsers import ORJSONParser
@@ -259,7 +368,7 @@ class SumView(APIView):
259
368
  auths = CustomJWTBearer()
260
369
 
261
370
  def views(self):
262
- @self.router.post(self.api_router_path, response={200: ExampleSchemaOut}, auth=self.auths)
371
+ @self.router.post("/", response={200: ExampleSchemaOut}, auth=self.auths)
263
372
  async def sum(request: HttpRequest, data: ExampleSchemaIn):
264
373
  return 200, {sum: data.n1 + data.n2}
265
374
 
@@ -268,6 +377,20 @@ FooAPI().add_views_to_route()
268
377
  SumView().add_views_to_route()
269
378
  ```
270
379
 
380
+ ## 📝 Pagination
381
+
382
+ - By default APIViewSet list view uses Django Ninja built-in AsyncPagination class "PageNumberPagination". You can customize and assign it to APIViewSet class. To make your custom pagination consult **<a href="https://django-ninja.dev/guides/response/pagination/#async-pagination">Django Ninja pagination documentation</a>**.
383
+
384
+ ```Python
385
+ # views.py
386
+
387
+ class FooAPI(APIViewSet):
388
+ model = Foo
389
+ api = api
390
+ pagination_class = CustomPaginationClass
391
+
392
+ ```
393
+
271
394
  ## 📌 Notes
272
395
  - Feel free to contribute and improve the program. 🛠️
273
396
 
@@ -0,0 +1,13 @@
1
+ ninja_aio/__init__.py,sha256=ZJAp30L0qJoTbf8E9aFP4hYCrnR_O1GU9LvZAzYSRms,70
2
+ ninja_aio/auth.py,sha256=hGgiblvffpHmmakjaxdNT3G0tq39-Bvc5oLNqjn4qd8,1300
3
+ ninja_aio/exceptions.py,sha256=PPNr1CdC7M7Kx1MtiBGuR4hATYQqEuvxCRU6uSG7rgM,543
4
+ ninja_aio/models.py,sha256=nKgY2q1gQRMwm6HJrrxBiWnUZIS6L6zG6wgsvqZKg6Q,10182
5
+ ninja_aio/parsers.py,sha256=e_4lGCPV7zs-HTqtdJTc8yQD2KPAn9njbL8nF_Mmgkc,153
6
+ ninja_aio/renders.py,sha256=uADkEyHQr4yet2h9j89Zjr9AbIElWCiLVk5HoqLSm10,1453
7
+ ninja_aio/schemas.py,sha256=EgRkfhnzZqwGvdBmqlZixMtMcoD1ZxV_qzJ3fmaAy20,113
8
+ ninja_aio/views.py,sha256=j72V0GHlTNdFDsO2f8ZMy_0aS7Hb4CKWN1t_st1ohDM,6319
9
+ ninja_aio/docs/images/bar-swagger.png,sha256=BTrE0i87JzKwxU0R4wDvNACZNR72mzemIQuR5Sh0N2k,73025
10
+ ninja_aio/docs/images/foo-swagger.png,sha256=ihHglnmRKwLttreOk8jI37typBCrw8dVPLOveL9Whyo,66298
11
+ django_ninja_aio_crud-0.1.3.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
12
+ django_ninja_aio_crud-0.1.3.dist-info/METADATA,sha256=eRULJJqS5A7FbdmIqtcYNOfFPN07y4QWOg5QPk2_mpw,10460
13
+ django_ninja_aio_crud-0.1.3.dist-info/RECORD,,
ninja_aio/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """ Django Ninja AIO CRUD - Rest Framework """
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.1.3"
Binary file
Binary file
ninja_aio/models.py CHANGED
@@ -204,18 +204,6 @@ class ModelSerializer(models.Model):
204
204
  return None
205
205
  return customs
206
206
 
207
- @classmethod
208
- def get_optional_fields(cls, s_type: type[S_TYPES]) -> list[str] | None:
209
- try:
210
- match s_type:
211
- case "create":
212
- optionals = cls.CreateSerializer.optionals
213
- case "update":
214
- optionals = cls.UpdateSerializer.optionals
215
- except AttributeError:
216
- return None
217
- return optionals
218
-
219
207
  @classmethod
220
208
  def generate_read_s(cls, depth: int = 1) -> Schema:
221
209
  fields, reverse_rels = cls.get_schema_out_data()
@@ -234,7 +222,6 @@ class ModelSerializer(models.Model):
234
222
  model=cls,
235
223
  name=f"{cls._meta.model_name}SchemaIn",
236
224
  fields=cls.CreateSerializer.fields,
237
- optional_fields=cls.get_optional_fields("create"),
238
225
  custom_fields=cls.get_custom_fields("create"),
239
226
  )
240
227
 
@@ -244,7 +231,6 @@ class ModelSerializer(models.Model):
244
231
  model=cls,
245
232
  name=f"{cls._meta.model_name}SchemaPatch",
246
233
  fields=cls.UpdateSerializer.fields,
247
- optional_fields=cls.get_optional_fields("update"),
248
234
  custom_fields=cls.get_custom_fields("update"),
249
235
  )
250
236
 
ninja_aio/views.py CHANGED
@@ -2,6 +2,7 @@ from typing import List
2
2
 
3
3
  from ninja import NinjaAPI, Router
4
4
  from ninja.constants import NOT_SET
5
+ from ninja.pagination import paginate, AsyncPaginationBase, PageNumberPagination
5
6
  from django.http import HttpRequest
6
7
 
7
8
  from .models import ModelSerializer
@@ -67,6 +68,7 @@ class APIViewSet:
67
68
  model: ModelSerializer
68
69
  api: NinjaAPI
69
70
  auths: list | None = NOT_SET
71
+ pagination_class: type[AsyncPaginationBase] = PageNumberPagination
70
72
 
71
73
  def __init__(self) -> None:
72
74
  self.router = Router(tags=[self.model._meta.model_name.capitalize()])
@@ -97,6 +99,7 @@ class APIViewSet:
97
99
  self.error_codes: GenericMessageSchema,
98
100
  },
99
101
  )
102
+ @paginate(self.pagination_class)
100
103
  async def list(request: HttpRequest):
101
104
  qs = await self.model.queryset_request(request)
102
105
  rels = self.model.get_reverse_relations()
@@ -1,11 +0,0 @@
1
- ninja_aio/__init__.py,sha256=g4F9YQdzat3-UYXtURHsJvuCpUEz__WI0ABfspZE9uo,69
2
- ninja_aio/auth.py,sha256=hGgiblvffpHmmakjaxdNT3G0tq39-Bvc5oLNqjn4qd8,1300
3
- ninja_aio/exceptions.py,sha256=PPNr1CdC7M7Kx1MtiBGuR4hATYQqEuvxCRU6uSG7rgM,543
4
- ninja_aio/models.py,sha256=G6AOtGNtaiQNZ1nG6rxv-xNRzZmSgbrNYwQjXmNeFmo,10710
5
- ninja_aio/parsers.py,sha256=e_4lGCPV7zs-HTqtdJTc8yQD2KPAn9njbL8nF_Mmgkc,153
6
- ninja_aio/renders.py,sha256=uADkEyHQr4yet2h9j89Zjr9AbIElWCiLVk5HoqLSm10,1453
7
- ninja_aio/schemas.py,sha256=EgRkfhnzZqwGvdBmqlZixMtMcoD1ZxV_qzJ3fmaAy20,113
8
- ninja_aio/views.py,sha256=pEtc0ovXvymfKJRtthd8cAps2RetTr9gzn-Xmxs763o,6126
9
- django_ninja_aio_crud-0.1.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
10
- django_ninja_aio_crud-0.1.1.dist-info/METADATA,sha256=g8k9GervfUVlbUBDLmqbzZM7zRRshnDQhThyKCgsMTI,8031
11
- django_ninja_aio_crud-0.1.1.dist-info/RECORD,,