django-ninja-aio-crud 0.3.1__py3-none-any.whl → 0.4.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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-ninja-aio-crud
3
- Version: 0.3.1
4
- Summary: Django Ninja AIO CRUD - Rest Framework
3
+ Version: 0.4.0
4
+ Summary: Django Ninja AIO CRUD - Rest Framework
5
5
  Author: Giuseppe Casillo
6
6
  Requires-Python: >=3.10
7
7
  Description-Content-Type: text/markdown
@@ -73,7 +73,7 @@ pip install django-ninja-aio-crud
73
73
  ### ModelSerializer
74
74
 
75
75
  - You can serialize your models using ModelSerializer and made them inherit from it. In your models.py import ModelSerializer
76
- ```Python
76
+ ```python
77
77
  # models.py
78
78
  from django.db import models
79
79
  from ninja_aio.models import ModelSerializer
@@ -95,7 +95,7 @@ class Foo(ModelSerializer):
95
95
 
96
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
97
 
98
- ```Python
98
+ ```python
99
99
  # models.py
100
100
  from django.db import models
101
101
  from ninja_aio.models import ModelSerializer
@@ -130,12 +130,34 @@ class Foo(ModelSerializer):
130
130
 
131
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.
132
132
 
133
+ - You can also define optional fields for you Create and Update serializers (remember to give your optional fields a default). To declare an optional fields you have to give the field type too.
134
+ ```python
135
+ # models.py
136
+ from django.db import models
137
+ from ninja_aio.models import ModelSerializer
138
+
139
+
140
+ class Foo(ModelSerializer):
141
+ name = models.CharField(max_length=30)
142
+ bar = models.CharField(max_length=30, default="")
143
+ active = models.BooleanField(default=False)
144
+
145
+ class ReadSerializer:
146
+ fields = ["id", "name", "bar"]
147
+
148
+ class CreateSerializer:
149
+ fields = ["name"]
150
+ optionals = [("bar", str), ("active", bool)]
151
+
152
+ class UpdateSerializer:
153
+ optionals = [[("bar", str), ("active", bool)]
154
+ ```
133
155
 
134
156
  ### APIViewSet
135
157
 
136
158
  - View class used to automatically generate CRUD views. in your views.py import APIViewSet and define your api using NinjaAIO class. NinjaAIO class uses built-in parser and renderer which use orjson for data serialization.
137
159
 
138
- ```Python
160
+ ```python
139
161
  # views.py
140
162
  from ninja_aio import NinjaAIO
141
163
  from ninja_aio.views import APIViewSet
@@ -157,7 +179,7 @@ FooAPI().add_views_to_route()
157
179
 
158
180
  - 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".
159
181
 
160
- ```Python
182
+ ```python
161
183
  # views.py
162
184
  from ninja import Schema
163
185
  from ninja_aio import NinjaAIO
@@ -196,7 +218,7 @@ FooAPI().add_views_to_route()
196
218
 
197
219
  - View class to code generic views class based. In your views.py import APIView class.
198
220
 
199
- ```Python
221
+ ```python
200
222
  # views.py
201
223
  from ninja import Schema
202
224
  from ninja_aio import NinjaAIO
@@ -235,7 +257,7 @@ SumView().add_views_to_route()
235
257
 
236
258
  - Define models:
237
259
 
238
- ```Python
260
+ ```python
239
261
  # models.py
240
262
  class Bar(ModelSerializer):
241
263
  name = models.CharField(max_length=30)
@@ -268,7 +290,7 @@ class Foo(ModelSerializer):
268
290
 
269
291
  - Define views:
270
292
 
271
- ```Python
293
+ ```python
272
294
  # views.py
273
295
  from ninja_aio import NinjaAIO
274
296
  from ninja_aio.views import APIViewSet
@@ -312,7 +334,7 @@ BarAPI().add_views_to_route()
312
334
 
313
335
  - 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
336
 
315
- ```Python
337
+ ```python
316
338
  from ninja_aio.auth import AsyncJWTBearer
317
339
  from django.conf import settings
318
340
  from django.http import HttpRequest
@@ -334,7 +356,7 @@ class CustomJWTBearer(AsyncJWTBearer):
334
356
 
335
357
  - Then add it to views.
336
358
 
337
- ```Python
359
+ ```python
338
360
  # views.py
339
361
  from ninja import Schema
340
362
  from ninja_aio import NinjaAIO
@@ -382,7 +404,7 @@ SumView().add_views_to_route()
382
404
 
383
405
  - 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>**.
384
406
 
385
- ```Python
407
+ ```python
386
408
  # views.py
387
409
 
388
410
  class FooAPI(APIViewSet):
@@ -0,0 +1,13 @@
1
+ ninja_aio/__init__.py,sha256=GPvxFosuQ4fZ9LpbRClXqv8e7BecmVUtj2nvbJyalus,119
2
+ ninja_aio/api.py,sha256=Fe6l3YCy7MW5TY4-Lbl80CFuK2NT2Y7tHfmqPk6Mqak,1735
3
+ ninja_aio/auth.py,sha256=3Pr8llYoCN59ZH3J_2qWmzjXxsy-rpQzXrVfwLfY25Q,1299
4
+ ninja_aio/exceptions.py,sha256=LP9GZpDk1fYMRRgGHSAstcCvgu5uSDLg8PPDANlZGTs,1008
5
+ ninja_aio/models.py,sha256=mIZofuGOsRATYQki7GIuz50OQWfMes41cvOOAAonQA0,13768
6
+ ninja_aio/parsers.py,sha256=e_4lGCPV7zs-HTqtdJTc8yQD2KPAn9njbL8nF_Mmgkc,153
7
+ ninja_aio/renders.py,sha256=mHeKNJtmDhZmgFpS9B6SPn5uZFcyVXrsoMhr149LeW8,1555
8
+ ninja_aio/schemas.py,sha256=EgRkfhnzZqwGvdBmqlZixMtMcoD1ZxV_qzJ3fmaAy20,113
9
+ ninja_aio/types.py,sha256=ZhFqRDP5g2A2er3izx36QjrYJxL_jgusbH7w7mVHNrk,339
10
+ ninja_aio/views.py,sha256=IT6rTCcjXcVYrCi4_uEwnGOGXeWlIB4ZuyXJp8Fsqqc,6971
11
+ django_ninja_aio_crud-0.4.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
12
+ django_ninja_aio_crud-0.4.0.dist-info/METADATA,sha256=0yQr4CWufJ7ZtXuhpTOchKQ-yOzG7o-wTaymDV0Tqvc,10832
13
+ django_ninja_aio_crud-0.4.0.dist-info/RECORD,,
ninja_aio/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
- """ Django Ninja AIO CRUD - Rest Framework """
1
+ """Django Ninja AIO CRUD - Rest Framework"""
2
2
 
3
- __version__ = "0.3.1"
3
+ __version__ = "0.4.0"
4
4
 
5
5
  from .api import NinjaAIO
6
6
 
7
- __all__ = ["NinjaAIO"]
7
+ __all__ = ["NinjaAIO"]
ninja_aio/api.py CHANGED
@@ -8,6 +8,7 @@ from ninja.constants import NOT_SET, NOT_SET_TYPE
8
8
 
9
9
  from .parsers import ORJSONParser
10
10
  from .renders import ORJSONRenderer
11
+ from .exceptions import set_api_exception_handlers
11
12
 
12
13
 
13
14
  class NinjaAIO(NinjaAPI):
@@ -19,14 +20,14 @@ class NinjaAIO(NinjaAPI):
19
20
  openapi_url: str | None = "/openapi.json",
20
21
  docs: DocsBase = Swagger(),
21
22
  docs_url: str | None = "/docs",
22
- docs_decorator = None,
23
+ docs_decorator=None,
23
24
  servers: list[dict[str, Any]] | None = None,
24
25
  urls_namespace: str | None = None,
25
26
  csrf: bool = False,
26
- auth: Sequence[Any]| NOT_SET_TYPE = NOT_SET,
27
+ auth: Sequence[Any] | NOT_SET_TYPE = NOT_SET,
27
28
  throttle: BaseThrottle | list[BaseThrottle] | NOT_SET_TYPE = NOT_SET,
28
29
  default_router: Router | None = None,
29
- openapi_extra: dict[str, Any] | None = None
30
+ openapi_extra: dict[str, Any] | None = None,
30
31
  ):
31
32
  super().__init__(
32
33
  title=title,
@@ -45,4 +46,8 @@ class NinjaAIO(NinjaAPI):
45
46
  openapi_extra=openapi_extra,
46
47
  renderer=ORJSONRenderer(),
47
48
  parser=ORJSONParser(),
48
- )
49
+ )
50
+
51
+ def set_default_exception_handlers(self):
52
+ set_api_exception_handlers(self)
53
+ super().set_default_exception_handlers()
ninja_aio/auth.py CHANGED
@@ -5,7 +5,6 @@ from ninja.security.http import HttpBearer
5
5
  from .exceptions import AuthError
6
6
 
7
7
 
8
-
9
8
  class AsyncJwtBearer(HttpBearer):
10
9
  jwt_public: jwk.RSAKey
11
10
  claims: dict[str, dict]
ninja_aio/exceptions.py CHANGED
@@ -1,3 +1,8 @@
1
+ from functools import partial
2
+ from ninja import NinjaAPI
3
+ from django.http import HttpRequest, HttpResponse
4
+
5
+
1
6
  class BaseException(Exception):
2
7
  error: str | dict = ""
3
8
  status_code: int = 400
@@ -22,3 +27,15 @@ class SerializeError(BaseException):
22
27
 
23
28
  class AuthError(BaseException):
24
29
  pass
30
+
31
+
32
+ def _default_serialize_error(
33
+ request: HttpRequest, exc: SerializeError, api: "NinjaAPI"
34
+ ) -> HttpResponse:
35
+ return api.create_response(request, exc.error, status=exc.status_code)
36
+
37
+
38
+ def set_api_exception_handlers(api: type[NinjaAPI]) -> None:
39
+ api.add_exception_handler(
40
+ SerializeError, partial(_default_serialize_error, api=api)
41
+ )
ninja_aio/models.py CHANGED
@@ -14,7 +14,7 @@ from django.db.models.fields.related_descriptors import (
14
14
  )
15
15
 
16
16
  from .exceptions import SerializeError
17
- from .types import S_TYPES, REL_TYPES, ModelSerializerMeta
17
+ from .types import S_TYPES, REL_TYPES, F_TYPES, ModelSerializerMeta
18
18
 
19
19
 
20
20
  class ModelUtil:
@@ -58,11 +58,18 @@ class ModelUtil:
58
58
  async def parse_input_data(self, request: HttpRequest, data: Schema):
59
59
  payload = data.model_dump()
60
60
  customs = {}
61
+ optionals = []
61
62
  if isinstance(self.model, ModelSerializerMeta):
62
63
  customs = {k: v for k, v in payload.items() if self.model.is_custom(k)}
64
+ optionals = [
65
+ k for k, v in payload.items() if self.model.is_optional(k) and v is None
66
+ ]
63
67
  for k, v in payload.items():
64
- if isinstance(self.model, ModelSerializerMeta) and self.model.is_custom(k):
65
- continue
68
+ if isinstance(self.model, ModelSerializerMeta):
69
+ if self.model.is_custom(k):
70
+ continue
71
+ if self.model.is_optional(k) and k is None:
72
+ continue
66
73
  field_obj = getattr(self.model, k).field
67
74
  if isinstance(field_obj, models.BinaryField):
68
75
  try:
@@ -73,7 +80,9 @@ class ModelUtil:
73
80
  rel_util = ModelUtil(field_obj.related_model)
74
81
  rel: ModelSerializer = await rel_util.get_object(request, v)
75
82
  payload |= {k: rel}
76
- new_payload = {k: v for k, v in payload.items() if k not in customs}
83
+ new_payload = {
84
+ k: v for k, v in payload.items() if k not in (customs.keys() or optionals)
85
+ }
77
86
  return new_payload, customs
78
87
 
79
88
  async def parse_output_data(self, request: HttpRequest, data: Schema):
@@ -106,12 +115,9 @@ class ModelUtil:
106
115
  return payload
107
116
 
108
117
  async def create_s(self, request: HttpRequest, data: Schema, obj_schema: Schema):
109
- try:
110
- payload, customs = await self.parse_input_data(request, data)
111
- pk = (await self.model.objects.acreate(**payload)).pk
112
- obj = await self.get_object(request, pk)
113
- except SerializeError as e:
114
- return e.status_code, e.error
118
+ payload, customs = await self.parse_input_data(request, data)
119
+ pk = (await self.model.objects.acreate(**payload)).pk
120
+ obj = await self.get_object(request, pk)
115
121
  if isinstance(self.model, ModelSerializerMeta):
116
122
  await obj.custom_actions(customs)
117
123
  await obj.post_create()
@@ -130,11 +136,7 @@ class ModelUtil:
130
136
  async def update_s(
131
137
  self, request: HttpRequest, data: Schema, pk: int | str, obj_schema: Schema
132
138
  ):
133
- try:
134
- obj = await self.get_object(request, pk)
135
- except SerializeError as e:
136
- return e.status_code, e.error
137
-
139
+ obj = await self.get_object(request, pk)
138
140
  payload, customs = await self.parse_input_data(request, data)
139
141
  for k, v in payload.items():
140
142
  if v is not None:
@@ -146,10 +148,7 @@ class ModelUtil:
146
148
  return await self.read_s(request, updated_object, obj_schema)
147
149
 
148
150
  async def delete_s(self, request: HttpRequest, pk: int | str):
149
- try:
150
- obj = await self.get_object(request, pk)
151
- except SerializeError as e:
152
- return e.status_code, e.error
151
+ obj = await self.get_object(request, pk)
153
152
  await obj.adelete()
154
153
  return HttpResponse(status=204)
155
154
 
@@ -161,6 +160,7 @@ class ModelSerializer(models.Model, metaclass=ModelSerializerMeta):
161
160
  class CreateSerializer:
162
161
  fields: list[str] = []
163
162
  customs: list[tuple[str, type, Any]] = []
163
+ optionals: list[str] = []
164
164
 
165
165
  class ReadSerializer:
166
166
  fields: list[str] = []
@@ -168,6 +168,7 @@ class ModelSerializer(models.Model, metaclass=ModelSerializerMeta):
168
168
  class UpdateSerializer:
169
169
  fields: list[str] = []
170
170
  customs: list[tuple[str, type, Any]] = []
171
+ optionals: list[str] = []
171
172
 
172
173
  @property
173
174
  def has_custom_fields_create(self):
@@ -181,6 +182,37 @@ class ModelSerializer(models.Model, metaclass=ModelSerializerMeta):
181
182
  def has_custom_fields(self):
182
183
  return self.has_custom_fields_create or self.has_custom_fields_update
183
184
 
185
+ @property
186
+ def has_optional_fields_create(self):
187
+ return hasattr(self.CreateSerializer, "optionals")
188
+
189
+ @property
190
+ def has_optional_fields_update(self):
191
+ return hasattr(self.UpdateSerializer, "optionals")
192
+
193
+ @property
194
+ def has_optional_fields(self):
195
+ return self.has_optional_fields_create or self.has_optional_fields_update
196
+
197
+ @classmethod
198
+ def _get_special_fields(cls, s_type: type[S_TYPES], f_type: type[F_TYPES]):
199
+ try:
200
+ match s_type:
201
+ case "create":
202
+ fields = getattr(cls.CreateSerializer, f_type)
203
+ case "update":
204
+ fields = getattr(cls.UpdateSerializer, f_type)
205
+ except AttributeError:
206
+ return []
207
+ return fields
208
+
209
+ @classmethod
210
+ def _is_special_field(
211
+ cls, s_type: type[S_TYPES], field: str, f_type: type[F_TYPES]
212
+ ):
213
+ special_fields = cls._get_special_fields(s_type, f_type)
214
+ return any(field in special_f for special_f in special_fields)
215
+
184
216
  @classmethod
185
217
  def verbose_name_path_resolver(cls) -> str:
186
218
  return "-".join(cls._meta.verbose_name_plural.split(" "))
@@ -284,71 +316,26 @@ class ModelSerializer(models.Model, metaclass=ModelSerializerMeta):
284
316
 
285
317
  @classmethod
286
318
  def is_custom(cls, field: str):
287
- customs = cls.get_custom_fields("create") or []
288
- customs.extend(cls.get_custom_fields("update") or [])
289
- return any(field in custom_f for custom_f in customs)
319
+ return cls._is_special_field(
320
+ "create", field, "customs"
321
+ ) or cls._is_special_field("update", field, "customs")
290
322
 
291
323
  @classmethod
292
- async def parse_input_data(cls, request: HttpRequest, data: Schema):
293
- payload = data.model_dump()
294
- customs = {k: v for k, v in payload.items() if cls.is_custom(k)}
295
- for k, v in payload.items():
296
- if cls.is_custom(k):
297
- continue
298
- field_obj = getattr(cls, k).field
299
- if isinstance(field_obj, models.BinaryField):
300
- try:
301
- payload |= {k: base64.b64decode(v)}
302
- except Exception as exc:
303
- raise SerializeError({k: ". ".join(exc.args)}, 400)
304
- if isinstance(field_obj, models.ForeignKey):
305
- rel: ModelSerializer = await field_obj.related_model.get_object(
306
- request, v
307
- )
308
- payload |= {k: rel}
309
- new_payload = {k: v for k, v in payload.items() if k not in customs}
310
- return new_payload, customs
324
+ def is_optional(cls, field: str):
325
+ return cls._is_special_field(
326
+ "create", field, "optionals"
327
+ ) or cls._is_special_field("update", field, "optionals")
311
328
 
312
329
  @classmethod
313
- async def parse_output_data(cls, request: HttpRequest, data: Schema):
314
- olds_k: list[dict] = []
315
- payload = data.model_dump()
316
- for k, v in payload.items():
317
- try:
318
- field_obj = getattr(cls, k).field
319
- except AttributeError:
320
- field_obj = getattr(cls, k).related
321
- if isinstance(v, dict) and (
322
- isinstance(field_obj, models.ForeignKey)
323
- or isinstance(field_obj, models.OneToOneField)
324
- ):
325
- rel: ModelSerializer = await field_obj.related_model.get_object(
326
- request, list(v.values())[0]
327
- )
328
- if isinstance(field_obj, models.ForeignKey):
329
- for rel_k, rel_v in v.items():
330
- field_rel_obj = getattr(rel, rel_k)
331
- if isinstance(field_rel_obj, models.ForeignKey):
332
- olds_k.append({rel_k: rel_v})
333
- for obj in olds_k:
334
- for old_k, old_v in obj.items():
335
- v.pop(old_k)
336
- v |= {f"{old_k}_id": old_v}
337
- olds_k = []
338
- payload |= {k: rel}
339
- return payload
330
+ def get_custom_fields(cls, s_type: type[S_TYPES]):
331
+ return cls._get_special_fields(s_type, "customs")
340
332
 
341
333
  @classmethod
342
- def get_custom_fields(cls, s_type: type[S_TYPES]):
343
- try:
344
- match s_type:
345
- case "create":
346
- customs = cls.CreateSerializer.customs
347
- case "update":
348
- customs = cls.UpdateSerializer.customs
349
- except AttributeError:
350
- return None
351
- return customs
334
+ def get_optional_fields(cls, s_type: type[S_TYPES]):
335
+ return [
336
+ (field, field_type, None)
337
+ for field, field_type in cls._get_special_fields(s_type, "optionals")
338
+ ]
352
339
 
353
340
  @classmethod
354
341
  def generate_read_s(cls, depth: int = 1) -> Schema:
@@ -364,78 +351,26 @@ class ModelSerializer(models.Model, metaclass=ModelSerializerMeta):
364
351
 
365
352
  @classmethod
366
353
  def generate_create_s(cls) -> Schema:
354
+ fields = getattr(cls.CreateSerializer, "fields", []) + [
355
+ field[0] for field in cls.get_optional_fields("create")
356
+ ]
357
+ customs = cls.get_custom_fields("create") + cls.get_optional_fields("create")
367
358
  return create_schema(
368
359
  model=cls,
369
360
  name=f"{cls._meta.model_name}SchemaIn",
370
- fields=cls.CreateSerializer.fields,
371
- custom_fields=cls.get_custom_fields("create"),
361
+ fields=fields,
362
+ custom_fields=customs,
372
363
  )
373
364
 
374
365
  @classmethod
375
366
  def generate_update_s(cls) -> Schema:
367
+ fields = getattr(cls.UpdateSerializer, "fields", []) + [
368
+ field[0] for field in cls.get_optional_fields("update")
369
+ ]
370
+ customs = cls.get_custom_fields("update") + cls.get_optional_fields("update")
376
371
  return create_schema(
377
372
  model=cls,
378
373
  name=f"{cls._meta.model_name}SchemaPatch",
379
- fields=cls.UpdateSerializer.fields,
380
- custom_fields=cls.get_custom_fields("update"),
374
+ fields=fields,
375
+ custom_fields=customs,
381
376
  )
382
-
383
- @classmethod
384
- async def get_object(cls, request: HttpRequest, pk: int | str):
385
- q = {cls._meta.pk.attname: pk}
386
- try:
387
- obj = (
388
- await (await cls.queryset_request(request))
389
- .prefetch_related(*cls.get_reverse_relations())
390
- .aget(**q)
391
- )
392
- except ObjectDoesNotExist:
393
- raise SerializeError({cls._meta.model_name: "not found"}, 404)
394
- return obj
395
-
396
- @classmethod
397
- async def create_s(cls, request: HttpRequest, data: Schema):
398
- try:
399
- payload, customs = await cls.parse_input_data(request, data)
400
- pk = (await cls.objects.acreate(**payload)).pk
401
- obj = await cls.get_object(request, pk)
402
- except SerializeError as e:
403
- return e.status_code, e.error
404
- payload |= customs
405
- await obj.custom_actions(payload)
406
- await obj.post_create()
407
- return await cls.read_s(request, obj)
408
-
409
- @classmethod
410
- async def read_s(cls, request: HttpRequest, obj: type["ModelSerializer"]):
411
- schema = cls.generate_read_s().from_orm(obj)
412
- try:
413
- data = await cls.parse_output_data(request, schema)
414
- except SerializeError as e:
415
- return e.status_code, e.error
416
- return data
417
-
418
- @classmethod
419
- async def update_s(cls, request: HttpRequest, data: Schema, pk: int | str):
420
- try:
421
- obj = await cls.get_object(request, pk)
422
- except SerializeError as e:
423
- return e.status_code, e.error
424
-
425
- payload, customs = await cls.parse_input_data(request, data)
426
- for k, v in payload.items():
427
- if v is not None:
428
- setattr(obj, k, v)
429
- await obj.custom_actions(customs)
430
- await obj.asave()
431
- updated_object = await cls.get_object(request, pk)
432
- return await cls.read_s(request, updated_object)
433
-
434
- @classmethod
435
- async def delete_s(cls, request: HttpRequest, pk: int | str):
436
- try:
437
- obj = await cls.get_object(request, pk)
438
- except SerializeError as e:
439
- return e.status_code, e.error
440
- await obj.adelete()
441
- return HttpResponse(status=204)
ninja_aio/types.py CHANGED
@@ -4,6 +4,7 @@ from django.db.models import Model
4
4
 
5
5
  S_TYPES = Literal["create", "update"]
6
6
  REL_TYPES = Literal["many", "one"]
7
+ F_TYPES = Literal["customs", "optionals"]
7
8
 
8
9
 
9
10
  class ModelSerializerType(type):
ninja_aio/views.py CHANGED
@@ -8,7 +8,6 @@ from django.db.models import Model
8
8
 
9
9
  from .models import ModelSerializer, ModelUtil
10
10
  from .schemas import GenericMessageSchema
11
- from .exceptions import SerializeError
12
11
  from .types import ModelSerializerMeta
13
12
 
14
13
  ERROR_CODES = frozenset({400, 401, 404, 428})
@@ -136,10 +135,7 @@ class APIViewSet:
136
135
  response={200: self.schema_out, self.error_codes: GenericMessageSchema},
137
136
  )
138
137
  async def retrieve(request: HttpRequest, pk: int | str):
139
- try:
140
- obj = await self.model_util.get_object(request, pk)
141
- except SerializeError as e:
142
- return e.status_code, e.error
138
+ obj = await self.model_util.get_object(request, pk)
143
139
  return await self.model_util.read_s(request, obj, self.schema_out)
144
140
 
145
141
  retrieve.__name__ = f"retrieve_{self.model._meta.model_name}"
@@ -1,13 +0,0 @@
1
- ninja_aio/__init__.py,sha256=_tjey_xwfvsIhCY5_zwh_pEW7Iubpix0RnfUSx_x9to,120
2
- ninja_aio/api.py,sha256=r0BOsZLdH-kqInbbXPmK8HeF-fQz756ih-MSFvfEBXI,1546
3
- ninja_aio/auth.py,sha256=hGgiblvffpHmmakjaxdNT3G0tq39-Bvc5oLNqjn4qd8,1300
4
- ninja_aio/exceptions.py,sha256=PPNr1CdC7M7Kx1MtiBGuR4hATYQqEuvxCRU6uSG7rgM,543
5
- ninja_aio/models.py,sha256=Ni4nO9U2DeWA3STX2wV8Jk5esqgwOSzfW7ZvA4hu1Hg,16500
6
- ninja_aio/parsers.py,sha256=e_4lGCPV7zs-HTqtdJTc8yQD2KPAn9njbL8nF_Mmgkc,153
7
- ninja_aio/renders.py,sha256=mHeKNJtmDhZmgFpS9B6SPn5uZFcyVXrsoMhr149LeW8,1555
8
- ninja_aio/schemas.py,sha256=EgRkfhnzZqwGvdBmqlZixMtMcoD1ZxV_qzJ3fmaAy20,113
9
- ninja_aio/types.py,sha256=gEHb6O9M07o5DHtxXH_KAcFJdq9lzq3ljmYbNLst8vs,297
10
- ninja_aio/views.py,sha256=LcUoCyBs4Sbgz8ugcu9nfm30xCKnEnEalROg-mUOCTg,7117
11
- django_ninja_aio_crud-0.3.1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
12
- django_ninja_aio_crud-0.3.1.dist-info/METADATA,sha256=c6tJqkqsYu7iUZdP5X5Rbm2jsGkeZOMAVGlDxtEJCOI,10135
13
- django_ninja_aio_crud-0.3.1.dist-info/RECORD,,