django-ninja-aio-crud 2.9.0__py3-none-any.whl → 2.10.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.
Potentially problematic release.
This version of django-ninja-aio-crud might be problematic. Click here for more details.
- {django_ninja_aio_crud-2.9.0.dist-info → django_ninja_aio_crud-2.10.0.dist-info}/METADATA +1 -1
- {django_ninja_aio_crud-2.9.0.dist-info → django_ninja_aio_crud-2.10.0.dist-info}/RECORD +9 -9
- ninja_aio/__init__.py +1 -1
- ninja_aio/models/utils.py +2 -2
- ninja_aio/schemas/__init__.py +2 -0
- ninja_aio/schemas/api.py +20 -1
- ninja_aio/views/mixins.py +63 -0
- {django_ninja_aio_crud-2.9.0.dist-info → django_ninja_aio_crud-2.10.0.dist-info}/WHEEL +0 -0
- {django_ninja_aio_crud-2.9.0.dist-info → django_ninja_aio_crud-2.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
ninja_aio/__init__.py,sha256=
|
|
1
|
+
ninja_aio/__init__.py,sha256=FZKyvJwguGusKjYpVUXSYB45Fssox9yEFHg47WX0BaE,120
|
|
2
2
|
ninja_aio/api.py,sha256=tuC7vdvn7s1GkCnSFy9Kn1zv0glZfYptRQVvo8ZRtGQ,2429
|
|
3
3
|
ninja_aio/auth.py,sha256=4sWdFPjKiQgUL1d_CSGDblVjnY5ptP6LQha6XXdluJA,9157
|
|
4
4
|
ninja_aio/exceptions.py,sha256=_3xFqfFCOfrrMhSA0xbMqgXy8R0UQjhXaExrFvaDAjY,3891
|
|
@@ -15,15 +15,15 @@ ninja_aio/helpers/api.py,sha256=2beyexep-ehgaA_1bV5Yuh3zRDVcRCMkrW94nmfDWEA,2081
|
|
|
15
15
|
ninja_aio/helpers/query.py,sha256=NMGkS_v-ZVYKNtf1XohEUzfwca52Eq5FTcQ5lehHjus,4682
|
|
16
16
|
ninja_aio/models/__init__.py,sha256=L3UQnQAlKoI3F7jinadL-Nn55hkPvnSRPYW0JtnbWFo,114
|
|
17
17
|
ninja_aio/models/serializers.py,sha256=I7pUz_vl0FElaVsrGaogT_Lj9T4uaNG7UDMGf5VMwW4,38468
|
|
18
|
-
ninja_aio/models/utils.py,sha256=
|
|
19
|
-
ninja_aio/schemas/__init__.py,sha256=
|
|
20
|
-
ninja_aio/schemas/api.py,sha256
|
|
18
|
+
ninja_aio/models/utils.py,sha256=dxzwqE25b0lFZ--30XxeIJB-y4xbIDtc624vGaa_wOg,32885
|
|
19
|
+
ninja_aio/schemas/__init__.py,sha256=_a092xZezlLc9QWCPWrybeklByCs39jbvf33zwdnrys,603
|
|
20
|
+
ninja_aio/schemas/api.py,sha256=InzZgIFU4Zxkgj9u_zZzAMYs_vdaPD5eu12gG7xAFoQ,1047
|
|
21
21
|
ninja_aio/schemas/generics.py,sha256=frjJsKJMAdM_NdNKv-9ddZNGxYy5PNzjIRGtuycgr-w,112
|
|
22
22
|
ninja_aio/schemas/helpers.py,sha256=Vti5BfHWpxaJXj_ixZBJb34VRwhHODrlVjRlIuHh_ug,8428
|
|
23
23
|
ninja_aio/views/__init__.py,sha256=DEzjWA6y3WF0V10nNF8eEurLNEodgxKzyFd09AqVp3s,148
|
|
24
24
|
ninja_aio/views/api.py,sha256=CW74JB1tsdWfv3Y3x4K9o8yXsrMxCKWZ4QalhqJGan8,22072
|
|
25
|
-
ninja_aio/views/mixins.py,sha256=
|
|
26
|
-
django_ninja_aio_crud-2.
|
|
27
|
-
django_ninja_aio_crud-2.
|
|
28
|
-
django_ninja_aio_crud-2.
|
|
29
|
-
django_ninja_aio_crud-2.
|
|
25
|
+
ninja_aio/views/mixins.py,sha256=01kEGMmpD3eTd8R5mX8sNr7KoizOfN0wvbV5y180IdE,13835
|
|
26
|
+
django_ninja_aio_crud-2.10.0.dist-info/licenses/LICENSE,sha256=yrDAYcm0gRp_Qyzo3GQa4BjYjWRkAhGC8QRva__RYq0,1073
|
|
27
|
+
django_ninja_aio_crud-2.10.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
28
|
+
django_ninja_aio_crud-2.10.0.dist-info/METADATA,sha256=-cSLMUj-s7djNL2RxRhLNkErv0yM49NK8CA8-zp-4zw,9964
|
|
29
|
+
django_ninja_aio_crud-2.10.0.dist-info/RECORD,,
|
ninja_aio/__init__.py
CHANGED
ninja_aio/models/utils.py
CHANGED
|
@@ -566,10 +566,10 @@ class ModelUtil:
|
|
|
566
566
|
serializable_fields = self._get_serializable_field_names(is_for)
|
|
567
567
|
for f in serializable_fields:
|
|
568
568
|
field_obj = getattr(self.model, f)
|
|
569
|
-
if isinstance(field_obj,
|
|
569
|
+
if isinstance(field_obj, ForwardOneToOneDescriptor):
|
|
570
570
|
select_rels.append(f)
|
|
571
571
|
continue
|
|
572
|
-
if isinstance(field_obj,
|
|
572
|
+
if isinstance(field_obj, ForwardManyToOneDescriptor):
|
|
573
573
|
select_rels.append(f)
|
|
574
574
|
return select_rels
|
|
575
575
|
|
ninja_aio/schemas/__init__.py
CHANGED
|
@@ -5,6 +5,7 @@ from .api import (
|
|
|
5
5
|
M2MAddSchemaIn,
|
|
6
6
|
M2MRemoveSchemaIn,
|
|
7
7
|
M2MSchemaIn,
|
|
8
|
+
RelationFilterSchema,
|
|
8
9
|
)
|
|
9
10
|
from .helpers import M2MRelationSchema, QuerySchema, ModelQuerySetSchema, ObjectQuerySchema, ObjectsQuerySchema
|
|
10
11
|
|
|
@@ -20,4 +21,5 @@ __all__ = [
|
|
|
20
21
|
"ModelQuerySetSchema",
|
|
21
22
|
"ObjectQuerySchema",
|
|
22
23
|
"ObjectsQuerySchema",
|
|
24
|
+
"RelationFilterSchema",
|
|
23
25
|
]
|
ninja_aio/schemas/api.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
from ninja import Schema
|
|
2
4
|
|
|
3
5
|
|
|
@@ -21,4 +23,21 @@ class M2MRemoveSchemaIn(Schema):
|
|
|
21
23
|
|
|
22
24
|
class M2MSchemaIn(Schema):
|
|
23
25
|
add: list = []
|
|
24
|
-
remove: list = []
|
|
26
|
+
remove: list = []
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class RelationFilterSchema(Schema):
|
|
30
|
+
"""
|
|
31
|
+
Schema for configuring relation-based filters in RelationFilterViewSetMixin.
|
|
32
|
+
|
|
33
|
+
Attributes:
|
|
34
|
+
filter_type: A tuple of (type, default_value) used to generate the query parameter
|
|
35
|
+
field in the filters schema. Example: (int, None) for optional integer filter.
|
|
36
|
+
query_param: The name of the query parameter exposed in the API endpoint.
|
|
37
|
+
This is what clients will use in requests (e.g., ?author_id=5).
|
|
38
|
+
query_filter: The Django ORM lookup to apply (e.g., "author__id", "category__slug").
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
filter_type: tuple[type, Any]
|
|
42
|
+
query_param: str
|
|
43
|
+
query_filter: str
|
ninja_aio/views/mixins.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from ninja_aio.views.api import APIViewSet
|
|
2
|
+
from ninja_aio.schemas import RelationFilterSchema
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
class IcontainsFilterViewSetMixin(APIViewSet):
|
|
@@ -273,3 +274,65 @@ class LessEqualDateFilterViewSetMixin(DateFilterViewSetMixin):
|
|
|
273
274
|
"""
|
|
274
275
|
|
|
275
276
|
_compare_attr = "__lte"
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
class RelationFilterViewSetMixin(APIViewSet):
|
|
280
|
+
"""
|
|
281
|
+
Mixin providing filtering for related fields in Django QuerySets.
|
|
282
|
+
|
|
283
|
+
This mixin applies filters on related fields based on configured RelationFilterSchema
|
|
284
|
+
entries. Each entry maps a query parameter name to a Django ORM lookup path.
|
|
285
|
+
|
|
286
|
+
Attributes:
|
|
287
|
+
relations_filters: List of RelationFilterSchema defining the relation filters.
|
|
288
|
+
Each schema specifies:
|
|
289
|
+
- query_param: The API query parameter name (e.g., "author_id")
|
|
290
|
+
- query_filter: The Django ORM lookup (e.g., "author__id")
|
|
291
|
+
- filter_type: Tuple of (type, default) for schema generation
|
|
292
|
+
|
|
293
|
+
Example:
|
|
294
|
+
class BookViewSet(RelationFilterViewSetMixin, APIViewSet):
|
|
295
|
+
relations_filters = [
|
|
296
|
+
RelationFilterSchema(
|
|
297
|
+
query_param="author_id",
|
|
298
|
+
query_filter="author__id",
|
|
299
|
+
filter_type=(int, None),
|
|
300
|
+
),
|
|
301
|
+
RelationFilterSchema(
|
|
302
|
+
query_param="category_slug",
|
|
303
|
+
query_filter="category__slug",
|
|
304
|
+
filter_type=(str, None),
|
|
305
|
+
),
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
# GET /books?author_id=5 -> queryset.filter(author__id=5)
|
|
309
|
+
# GET /books?category_slug=fiction -> queryset.filter(category__slug="fiction")
|
|
310
|
+
|
|
311
|
+
Notes:
|
|
312
|
+
- Filter values that are None or falsy are skipped.
|
|
313
|
+
- This mixin automatically registers query_params from relations_filters.
|
|
314
|
+
"""
|
|
315
|
+
|
|
316
|
+
relations_filters: list[RelationFilterSchema] = []
|
|
317
|
+
|
|
318
|
+
def __init_subclass__(cls, **kwargs):
|
|
319
|
+
super().__init_subclass__(**kwargs)
|
|
320
|
+
cls.query_params = {
|
|
321
|
+
**cls.query_params,
|
|
322
|
+
**{
|
|
323
|
+
rel_filter.query_param: rel_filter.filter_type
|
|
324
|
+
for rel_filter in cls.relations_filters
|
|
325
|
+
},
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async def query_params_handler(self, queryset, filters):
|
|
329
|
+
"""
|
|
330
|
+
Apply relation filters to the queryset based on configured relations_filters.
|
|
331
|
+
"""
|
|
332
|
+
base_qs = await super().query_params_handler(queryset, filters)
|
|
333
|
+
rel_filters = {}
|
|
334
|
+
for rel_filter in self.relations_filters:
|
|
335
|
+
value = filters.get(rel_filter.query_param)
|
|
336
|
+
if value is not None:
|
|
337
|
+
rel_filters[rel_filter.query_filter] = value
|
|
338
|
+
return base_qs.filter(**rel_filters) if rel_filters else base_qs
|
|
File without changes
|
{django_ninja_aio_crud-2.9.0.dist-info → django_ninja_aio_crud-2.10.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|