django-ninja-aio-crud 2.0.0rc6__tar.gz → 2.0.0rc7__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.
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/workflows/docs.yml +2 -2
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/PKG-INFO +1 -1
- django_ninja_aio_crud-2.0.0rc7/docs/api/renderers/orjson_renderer.md +20 -0
- django_ninja_aio_crud-2.0.0rc7/docs/api/views/decorators.md +65 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/__init__.py +1 -1
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/decorators.py +73 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/helpers.py +10 -2
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/views.py +12 -8
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/dependabot.yml +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/workflows/coverage.yml +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/workflows/publish.yml +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.gitignore +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.pre-commit-config.yaml +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/LICENSE +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/README.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/CNAME +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/authentication.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/models/model_serializer.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/models/model_util.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/pagination.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/views/api_view.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/views/api_view_set.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/contributing.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/extra.css +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/images/index/foo-index-create-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/images/index/foo-index-delete-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/images/index/foo-index-list-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/images/index/foo-index-retrieve-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/images/index/foo-index-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/images/index/foo-index-update-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/installation.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/getting_started/quick_start.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/bar-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/favicon.ico +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/foo-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/logo.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/model_util/foo-reverse-relations-swagger.png +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/index.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/release_notes.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/requirements.txt +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/tutorial/authentication.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/tutorial/crud.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/tutorial/filtering.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/tutorial/model.md +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_1/models.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_1/urls.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_1/views.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_2/auth.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_2/models.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_2/urls.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/examples/ex_2/views.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/main.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/mkdocs.yml +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/api.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/auth.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/exceptions.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/helpers/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/helpers/api.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/helpers/query.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/models.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/parsers.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/renders.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/api.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/generics.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/types.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/pyproject.toml +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/requirements.dev.txt +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/run-local-coverage.sh +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/test_decorators.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/test_exceptions_api.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/test_renderer_parser.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/literals.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/models.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/request.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/views.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/helpers/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/helpers/test_many_to_many_api.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/models/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/models/test_model_util.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/models/test_models_extra.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_app/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_app/models.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_app/schema.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_app/views.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_decorators.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_exceptions.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_query_util.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_settings.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/views/__init__.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/views/test_views.py +0 -0
- {django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/views/test_viewset.py +0 -0
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/workflows/docs.yml
RENAMED
|
@@ -34,10 +34,10 @@ jobs:
|
|
|
34
34
|
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
35
35
|
|
|
36
36
|
steps:
|
|
37
|
-
- uses: actions/checkout@
|
|
37
|
+
- uses: actions/checkout@v6
|
|
38
38
|
|
|
39
39
|
- name: Set up Python
|
|
40
|
-
uses: actions/setup-python@
|
|
40
|
+
uses: actions/setup-python@v6
|
|
41
41
|
with:
|
|
42
42
|
python-version: "3.13"
|
|
43
43
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ORJSON renderer option
|
|
2
|
+
|
|
3
|
+
This package uses an internal ORJSON-based renderer. Configure serialization options via Django settings:
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
# settings.py
|
|
7
|
+
import orjson
|
|
8
|
+
|
|
9
|
+
# Single option
|
|
10
|
+
NINJA_AIO_ORJSON_RENDERER_OPTION = orjson.OPT_INDENT_2
|
|
11
|
+
|
|
12
|
+
# Multiple options (bitwise OR)
|
|
13
|
+
NINJA_AIO_ORJSON_RENDERER_OPTION = (
|
|
14
|
+
orjson.OPT_INDENT_2 | orjson.OPT_NON_STR_KEYS
|
|
15
|
+
)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Notes:
|
|
19
|
+
- The value is an orjson option bitmask (e.g., `orjson.OPT_INDENT_2`, `orjson.OPT_NON_STR_KEYS`), and you can combine multiple options using `|`.
|
|
20
|
+
- If not set, the default `orjson.dumps` options are used.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# View decorators
|
|
2
|
+
|
|
3
|
+
This package provides:
|
|
4
|
+
|
|
5
|
+
- decorate_view: compose multiple decorators (sync/async views), preserving Python stacking order, and skipping None values.
|
|
6
|
+
- APIViewSet.extra_decorators: declarative per-operation decorators.
|
|
7
|
+
|
|
8
|
+
## decorate_view
|
|
9
|
+
|
|
10
|
+
Behavior:
|
|
11
|
+
|
|
12
|
+
- Order matches normal stacking: `@d1` over `@d2` ≡ `d1(d2(view))`.
|
|
13
|
+
- Works with sync/async views.
|
|
14
|
+
- Ignores None values, useful for conditional decoration.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from ninja_aio.decorators import decorate_view
|
|
20
|
+
from ninja_aio.views import APIViewSet
|
|
21
|
+
|
|
22
|
+
class MyViewSet(APIViewSet):
|
|
23
|
+
api = api
|
|
24
|
+
model = MyModel
|
|
25
|
+
|
|
26
|
+
def views(self):
|
|
27
|
+
@self.router.get("health/")
|
|
28
|
+
@decorate_view(authenticate, log_request)
|
|
29
|
+
async def health(request):
|
|
30
|
+
return {"ok": True}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Conditional decoration:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
cache_dec = cache_page(60) if settings.ENABLE_CACHE else None
|
|
37
|
+
|
|
38
|
+
@self.router.get("data/")
|
|
39
|
+
@decorate_view(cache_dec, authenticate)
|
|
40
|
+
async def data(request):
|
|
41
|
+
...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Note: decorate_view does not add an extra wrapper; each decorator should preserve metadata itself (e.g., functools.wraps).
|
|
45
|
+
|
|
46
|
+
## APIViewSet.extra_decorators
|
|
47
|
+
|
|
48
|
+
Attach decorators to CRUD operations without redefining views:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from ninja_aio.schemas.helpers import DecoratorsSchema
|
|
52
|
+
|
|
53
|
+
class MyViewSet(APIViewSet):
|
|
54
|
+
api = api
|
|
55
|
+
model = MyModel
|
|
56
|
+
extra_decorators = DecoratorsSchema(
|
|
57
|
+
list=[require_auth, cache_page(30)],
|
|
58
|
+
retrieve=[require_auth],
|
|
59
|
+
create=[require_auth],
|
|
60
|
+
update=[require_auth],
|
|
61
|
+
delete=[require_auth],
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
These are applied in combination with built-ins (e.g., unique_view, paginate) using decorate_view in the implementation.
|
|
@@ -143,3 +143,76 @@ def unique_view(self: object | str, plural: bool = False):
|
|
|
143
143
|
return func # Return original function (no wrapper)
|
|
144
144
|
|
|
145
145
|
return decorator
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def decorate_view(*decorators):
|
|
149
|
+
"""
|
|
150
|
+
Compose and apply multiple decorators to a view (sync or async) without adding an extra wrapper.
|
|
151
|
+
|
|
152
|
+
This utility was introduced to support class-based patterns where Django Ninja’s
|
|
153
|
+
built-in `decorate_view` does not fit well. For APIs implemented with vanilla
|
|
154
|
+
Django Ninja (function-based style), you should continue using Django Ninja’s
|
|
155
|
+
native `decorate_view`.
|
|
156
|
+
|
|
157
|
+
Behavior:
|
|
158
|
+
- Applies decorators in the same order as Python’s stacking syntax:
|
|
159
|
+
@d1
|
|
160
|
+
@d2
|
|
161
|
+
is equivalent to: view = d1(d2(view))
|
|
162
|
+
- Supports both synchronous and asynchronous views.
|
|
163
|
+
- Ignores None values, enabling conditional decoration.
|
|
164
|
+
- Does not introduce an additional wrapper; composition depends on each
|
|
165
|
+
decorator for signature/metadata preservation (e.g., using functools.wraps).
|
|
166
|
+
|
|
167
|
+
*decorators: Decorator callables to apply to the target view. Any None values
|
|
168
|
+
are skipped.
|
|
169
|
+
|
|
170
|
+
Callable: A decorator that applies the provided decorators in Python stacking order.
|
|
171
|
+
|
|
172
|
+
Method usage in class-based patterns:
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
*decorators: Decorator callables to apply to the target view. Any None
|
|
176
|
+
values are skipped.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
A decorator that applies the provided decorators in Python stacking order.
|
|
180
|
+
|
|
181
|
+
Examples:
|
|
182
|
+
Basic usage:
|
|
183
|
+
class MyAPIViewSet(APIViewSet):
|
|
184
|
+
api = api
|
|
185
|
+
model = MyModel
|
|
186
|
+
|
|
187
|
+
def views(self):
|
|
188
|
+
@self.router.get('some-endpoint/')
|
|
189
|
+
@decorate_view(authenticate, log_request)
|
|
190
|
+
async def some_view(request):
|
|
191
|
+
...
|
|
192
|
+
|
|
193
|
+
Conditional decoration (skips None):
|
|
194
|
+
class MyAPIViewSet(APIViewSet):
|
|
195
|
+
api = api
|
|
196
|
+
model = MyModel
|
|
197
|
+
cache_dec = cache_page(60) if settings.ENABLE_CACHE else None
|
|
198
|
+
def views(self):
|
|
199
|
+
@self.router.get('data/')
|
|
200
|
+
@decorate_view(self.cache_dec, authenticate)
|
|
201
|
+
async def data_view(request):
|
|
202
|
+
...
|
|
203
|
+
|
|
204
|
+
Notes:
|
|
205
|
+
- Each decorator is applied in the order provided, with the first decorator
|
|
206
|
+
wrapping the result of the second, and so on.
|
|
207
|
+
- Ensure that each decorator is compatible with the view’s sync/async nature.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
def _decorator(view):
|
|
211
|
+
wrapped = view
|
|
212
|
+
for dec in reversed(decorators):
|
|
213
|
+
if dec is None:
|
|
214
|
+
continue
|
|
215
|
+
wrapped = dec(wrapped)
|
|
216
|
+
return wrapped
|
|
217
|
+
|
|
218
|
+
return _decorator
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/helpers.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional, Type
|
|
1
|
+
from typing import List, Optional, Type
|
|
2
2
|
|
|
3
3
|
from ninja import Schema
|
|
4
4
|
from ninja_aio.types import ModelSerializerMeta
|
|
@@ -79,4 +79,12 @@ class QuerySchema(ModelQuerySetSchema):
|
|
|
79
79
|
|
|
80
80
|
class QueryUtilBaseScopesSchema(BaseModel):
|
|
81
81
|
READ: str = "read"
|
|
82
|
-
QUERYSET_REQUEST: str = "queryset_request"
|
|
82
|
+
QUERYSET_REQUEST: str = "queryset_request"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class DecoratorsSchema(Schema):
|
|
86
|
+
list: Optional[List] = []
|
|
87
|
+
retrieve: Optional[List] = []
|
|
88
|
+
create: Optional[List] = []
|
|
89
|
+
update: Optional[List] = []
|
|
90
|
+
delete: Optional[List] = []
|
|
@@ -7,7 +7,7 @@ from django.http import HttpRequest
|
|
|
7
7
|
from django.db.models import Model, QuerySet
|
|
8
8
|
from pydantic import create_model
|
|
9
9
|
|
|
10
|
-
from ninja_aio.schemas.helpers import ModelQuerySetSchema, QuerySchema
|
|
10
|
+
from ninja_aio.schemas.helpers import ModelQuerySetSchema, QuerySchema, DecoratorsSchema
|
|
11
11
|
|
|
12
12
|
from .models import ModelSerializer, ModelUtil
|
|
13
13
|
from .schemas import (
|
|
@@ -16,7 +16,7 @@ from .schemas import (
|
|
|
16
16
|
)
|
|
17
17
|
from .helpers.api import ManyToManyAPI
|
|
18
18
|
from .types import ModelSerializerMeta, VIEW_TYPES
|
|
19
|
-
from .decorators import unique_view
|
|
19
|
+
from .decorators import unique_view, decorate_view
|
|
20
20
|
|
|
21
21
|
ERROR_CODES = frozenset({400, 401, 404, 428})
|
|
22
22
|
|
|
@@ -178,6 +178,7 @@ class APIViewSet:
|
|
|
178
178
|
delete_docs = "Delete an object by its primary key."
|
|
179
179
|
m2m_relations: list[M2MRelationSchema] = []
|
|
180
180
|
m2m_auth: list | None = NOT_SET
|
|
181
|
+
extra_decorators: DecoratorsSchema = DecoratorsSchema()
|
|
181
182
|
|
|
182
183
|
def __init__(self) -> None:
|
|
183
184
|
self.error_codes = ERROR_CODES
|
|
@@ -309,7 +310,7 @@ class APIViewSet:
|
|
|
309
310
|
description=self.create_docs,
|
|
310
311
|
response={201: self.schema_out, self.error_codes: GenericMessageSchema},
|
|
311
312
|
)
|
|
312
|
-
@unique_view(self)
|
|
313
|
+
@decorate_view(unique_view(self), *self.extra_decorators.create)
|
|
313
314
|
async def create(request: HttpRequest, data: self.schema_in): # type: ignore
|
|
314
315
|
return 201, await self.model_util.create_s(request, data, self.schema_out)
|
|
315
316
|
|
|
@@ -330,8 +331,11 @@ class APIViewSet:
|
|
|
330
331
|
self.error_codes: GenericMessageSchema,
|
|
331
332
|
},
|
|
332
333
|
)
|
|
333
|
-
@
|
|
334
|
-
|
|
334
|
+
@decorate_view(
|
|
335
|
+
paginate(self.pagination_class),
|
|
336
|
+
unique_view(self, plural=True),
|
|
337
|
+
*self.extra_decorators.list,
|
|
338
|
+
)
|
|
335
339
|
async def list(
|
|
336
340
|
request: HttpRequest,
|
|
337
341
|
filters: Query[self.filters_schema] = None, # type: ignore
|
|
@@ -359,7 +363,7 @@ class APIViewSet:
|
|
|
359
363
|
description=self.retrieve_docs,
|
|
360
364
|
response={200: self.schema_out, self.error_codes: GenericMessageSchema},
|
|
361
365
|
)
|
|
362
|
-
@unique_view(self)
|
|
366
|
+
@decorate_view(unique_view(self), *self.extra_decorators.retrieve)
|
|
363
367
|
async def retrieve(request: HttpRequest, pk: Path[self.path_schema]): # type: ignore
|
|
364
368
|
query_data = self._get_query_data()
|
|
365
369
|
return await self.model_util.read_s(
|
|
@@ -384,7 +388,7 @@ class APIViewSet:
|
|
|
384
388
|
description=self.update_docs,
|
|
385
389
|
response={200: self.schema_out, self.error_codes: GenericMessageSchema},
|
|
386
390
|
)
|
|
387
|
-
@unique_view(self)
|
|
391
|
+
@decorate_view(unique_view(self), *self.extra_decorators.update)
|
|
388
392
|
async def update(
|
|
389
393
|
request: HttpRequest,
|
|
390
394
|
data: self.schema_update, # type: ignore
|
|
@@ -408,7 +412,7 @@ class APIViewSet:
|
|
|
408
412
|
description=self.delete_docs,
|
|
409
413
|
response={204: None, self.error_codes: GenericMessageSchema},
|
|
410
414
|
)
|
|
411
|
-
@unique_view(self)
|
|
415
|
+
@decorate_view(unique_view(self), *self.extra_decorators.delete)
|
|
412
416
|
async def delete(request: HttpRequest, pk: Path[self.path_schema]): # type: ignore
|
|
413
417
|
return 204, await self.model_util.delete_s(request, self._get_pk(pk))
|
|
414
418
|
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/workflows/coverage.yml
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/.github/workflows/publish.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/authentication.md
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/models/model_util.md
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/views/api_view.md
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/api/views/api_view_set.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/bar-swagger.png
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/images/foo-swagger.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/tutorial/authentication.md
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/docs/tutorial/filtering.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/helpers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/helpers/query.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/ninja_aio/schemas/generics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/test_decorators.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/test_exceptions_api.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/core/test_renderer_parser.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/__init__.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/generics/literals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/models/test_model_util.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/models/test_models_extra.py
RENAMED
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/test_app/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_ninja_aio_crud-2.0.0rc6 → django_ninja_aio_crud-2.0.0rc7}/tests/views/test_viewset.py
RENAMED
|
File without changes
|